• C++中使用Curl和JsonCpp调用有道翻译API实现在线翻译


    使用C++开发一个在线翻译工具,这个想法在我大脑中过了好几遍了,所以就搜了下资料,得知网络上有很多翻译API,这里我选择我平时使用较多的有道翻译API进行在线翻译工具开发的练习。翻译API返回的结果常见的有两种:xml和json格式,本文选择使用json数据来实现Berlin版本的在线翻译工具。

    开发环境:Ubuntu12.04 + GCC4.7

    一、 有道翻译API

    API 地址:http://fanyi.youdao.com/openapi

    这里我选择了数据调用接口key的申请,填入相关信息,然后系统会提供API Key和Keyfrom字段给你,同时会发送一份包含这2项的邮件到你所填写的邮箱。

    有道翻译API的数据接口如下:

    http://fanyi.youdao.com/openapi.do?keyfrom=<keyfrom>&key=<key>&type=data&doctype=<doctype>&version=1.1&q=要翻译的文本

    版本:1.1,请求方式:get,编码方式:utf-8

    主要功能:中英互译,同时获得有道翻译结果和有道词典结果(可能没有)

    参数说明:

     type - 返回结果的类型,固定为data

     doctype - 返回结果的数据格式,xml或json或jsonp

     version - 版本,当前最新版本为1.1

     q - 要翻译的文本,不能超过200个字符,需要使用utf-8编码

    errorCode:

     0 - 正常

     20 - 要翻译的文本过长

     30 - 无法进行有效的翻译

     40 - 不支持的语言类型

     50 - 无效的key

    二、 Curl和JsonCpp的安装

    2.1 Curl的安装

    Curl工程主页:http://curl.haxx.se/, 目前最新版本是curl-7.34.0,下载解压后进入curl-7.34.0目录,用如下命令安装:

    1 cd $CURL_HOME
    2 mkdir build
    3 cd build
    4 cmake ..
    5 make

    2.2 JsonCpp的安装

    JsonCpp工程主页:http://jsoncpp.sourceforge.net/,目前的最新版本是jsoncpp-src-0.5.0,下载解压后进入jsoncpp-src-0.5.0,使用Scons进行安装,Scons是一个Python编译系统,没有安装的童鞋需要先安装Scons,如下:

    1 sudo apt-get install scons

    Scons安装好之后就可以编译JsonCpp了,使用如下命令:

    1 scons platform=linux-gcc

    好了,JsonCpp已经成功安装了,为了后面程序编译链接过程中方便,我在JsonCpp路径下的libs文件夹中设置了一个软连接,如下:

    1 ln -s libjson_linux-gcc-4.7_libmt.a libjson_linux-gcc.a

    三、 在线翻译工具

    直接贴代码:

     1 /*
     2     Filename: translate.cc
     3     Author: BerlinSun
     4 */
     5 #include <iostream>
     6 #include "curl/curl.h"
     7 #include "json/json.h"
     8 
     9 using namespace std;
    10 
    11 void usage()
    12 {
    13     cout << "Usage: translate word_you_want_to_translate" << endl;
    14 }
    15 
    16 int writer(char *data, size_t size, size_t nmemb, string *writerData)
    17 {
    18     if (writerData == NULL)
    19         return 0;
    20     int len = size*nmemb;
    21     writerData->append(data, len); 
    22     return len;
    23 }
    24 
    25 int main(int argc, char *argv[])
    26 {
    27     if(argc < 2)
    28     {
    29         usage();
    30         exit(0);
    31     }
    32     string buffer;
    33     string translate_url = "http://fanyi.youdao.com/openapi.do?keyfrom=xxxxxx&key=xxxxxx&type=data&doctype=json&version=1.1&q=";
    34     translate_url += argv[1];
    35     CURL * curl;
    36     CURLcode res;
    37     curl = curl_easy_init();
    38     if (curl)
    39     {
    40         curl_easy_setopt(curl, CURLOPT_URL, translate_url.c_str());
    41         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
    42         curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
    43         res = curl_easy_perform(curl);
    44         curl_easy_cleanup(curl);
    45     }
    46     if (buffer.empty())
    47     {
    48         cout << "The server return NULL!" << endl;
    49         exit(0);
    50     }
    51     
    52     Json::Value root;
    53     Json::Reader reader;
    54     bool parsingSuccessful = reader.parse(buffer, root);
    55     
    56     if (!parsingSuccessful)
    57     {
    58         cout << "Failed to parse the data!" << endl;
    59         exit(0);
    60     }
    61     
    62     const Json::Value basic = root["basic"];
    63     const Json::Value phonetic = basic["phonetic"];
    64     const Json::Value explains = basic["explains"];
    65     cout << "Provided by Youdao dictionary!" << endl;
    66     cout << "-----------------------------" << endl;
    67     cout << argv[1] << "	英[" << phonetic.asString()  << "]" << endl;
    68     
    69     for(int i = 0; i < explains.size(); ++i)
    70         cout << explains[i].asString() << endl;
    71 
    72     return 0;
    73 }
    View Code

    PS:代码中红色加粗的部分就是你所申请到的key和keyfrom字段。

    CMake文件如下:

     1 project(test)
     2 cmake_minimum_required(VERSION 2.6)
     3 
     4 include_directories($ENV{JSONCPP_HOME}/include $ENV{CURL_HOME}/include)
     5 link_directories($ENV{JSONCPP_HOME}/libs/ $ENV{CURL_HOME}/build/lib)
     6 add_definitions(-std=c++0x)
     7 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
     8 
     9 set(source
    10     translate.cc)
    11 add_executable(translate ${source})
    12 target_link_libraries(translate json_linux-gcc)
    13 target_link_libraries(translate curl)

    程序执行效果如下:

    =====================================================================

    补充:

    之前实现这个工具的时候没有考虑汉译英,所以并没有对汉语进行测试,感谢yough90提出汉语没法翻译的问题,这个问题其实很好理解,编码问题,中文和英文使用不同的编码方式,解决方案也比较简单,libcurl提供了专门用于编码的方法:

    1 char *curl_easy_escape( CURL * curl , char * url , int length );

    在我们检测到我们传入的参数有非ASCII编码的时候,我们调用该函数对其进行转换:

    1 if ((*argv[1]&0x80) != 0)
    2 {
    3     type = 0;
    4     char *encode_word = curl_easy_escape(curl, argv[1], 0);
    5     translate_url += encode_word;
    6 } else {
    7     type = 1;
    8   translate_url += argv[1];
    9 }

    由于后面显示格式会有所不同,所以我加入一个type用来记住翻译类型,好了,修改后的代码如下:

     1 #include <iostream>
     2 #include "curl/curl.h"
     3 #include "json/json.h"
     4 
     5 using namespace std;
     6 
     7 void usage()
     8 {
     9     cout << "Usage: translate word_you_want_to_translate" << endl;
    10 }
    11 
    12 int writer(char *data, size_t size, size_t nmemb, string *writerData)
    13 {
    14     if (writerData == NULL)
    15         return 0;
    16     int len = size*nmemb;
    17     writerData->append(data, len); 
    18     return len;
    19 }
    20 
    21 int main(int argc, char *argv[])
    22 {
    23     if(argc < 2)
    24     {
    25         usage();
    26         exit(0);
    27     }
    28     string buffer;
    29     string translate_url = "http://fanyi.youdao.com/openapi.do?keyfrom=xxxxxxxx&key=xxxxxxxx&type=data&doctype=json&version=1.1&q=";
    30     CURL * curl;
    31     CURLcode res;
    32     curl = curl_easy_init();
    33 
    34     int type;
    35 
    36     if ((*argv[1]&0x80) != 0)
    37     {
    38         type = 0;
    39         char *encode_word = curl_easy_escape(curl, argv[1], 0);
    40         translate_url += encode_word;
    41     } else {
    42         type = 1;
    43         translate_url += argv[1];
    44     }
    45 
    46     if (curl)
    47     {
    48         curl_easy_setopt(curl, CURLOPT_URL, translate_url.c_str());
    49         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
    50         curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
    51         res = curl_easy_perform(curl);
    52         curl_easy_cleanup(curl);
    53     }
    54     if (buffer.empty())
    55     {
    56         cout << "The server return NULL!" << endl;
    57         exit(0);
    58     }
    59     
    60     Json::Value root;
    61     Json::Reader reader;
    62     bool parsingSuccessful = reader.parse(buffer, root);
    63     
    64     if (!parsingSuccessful)
    65     {
    66         cout << "Failed to parse the data!" << endl;
    67         exit(0);
    68     }
    69 
    70     if (root["errorCode"] != 0)
    71     {
    72         cout << "errorCode: " << root["errorCode"] << endl;
    73         exit(0);
    74     }
    75     const Json::Value basic = root["basic"];
    76     const Json::Value phonetic = basic["phonetic"];
    77     const Json::Value explains = basic["explains"];
    78     cout << "Provided by Youdao dictionary!" << endl;
    79     cout << "-----------------------------" << endl;
    80     const char *prefix = type == 0 ? "[" : "英[";
    81     cout << argv[1] << "	" << prefix << phonetic.asString()  << "]" << endl;
    82     
    83     for(int i = 0; i < explains.size(); ++i)
    84         cout << explains[i].asString() << endl;
    85 
    86     return 0;
    87 }

    这里,对之前博友提出的没有验证errorCode的问题也一并修复了!汉语翻译结果如下:

    谢谢大家的阅读!

    语音辞典功能见这里:http://www.cnblogs.com/berlin-sun/p/OnlineDictionary.html

  • 相关阅读:
    基于s5pv210的uboot总结
    QQ群笔记
    设计模式----适配器模式
    设计模式----桥接模式
    设计模式----建造者模式
    设计模式----原型模式
    设计模式----单例模式
    设计模式----工厂方法模式
    设计模式----设计原则
    JUnit单元测试--小试牛刀
  • 原文地址:https://www.cnblogs.com/berlin-sun/p/translateonline.html
Copyright © 2020-2023  润新知