调用翻译接口翻译词条

调用谷歌翻译接口方式

谷歌翻译的API从2011年12月1号起是一项收费的服务了, 通过上网查询资料, 整理了一套破解的方法,记录一下。

虽然调用谷歌给出的接口是收费的, 但是网页上谷歌的在线翻译(https://translate.google.cn/)是免费的。因此, 可以通过对在线翻译页面爬取的方式, 获取词条翻译后的结果。

整体的流程就是:拼装请求参数, 发送请求信息, 处理相应结果。下面逐条介绍。

拼装请求参数

通过抓包的方式, 查看请求的路径和请求的参数。举个例子:翻译“你好”。

翻译页面:


词条.png

翻译时, 对页面信息进行抓取,可以看到发送翻译请求的一些基本信息。比如说请求方式:GET。比如说请求参数:Query String Parameter。 比如说请求过程的cookie等。


请求信息.png
查询的参数.png

部分请求参数介绍:(汉语自己翻译的, 不知道对不对)

  • sl - source language code (auto for autodetection):原语言编码
  • tl - translation language:翻译后的语言
  • q - source text / word:翻以前文本
  • ie - input encoding (a guess):翻以前输入的编码
  • oe - output encoding (a guess):翻译后输出的编码
  • dt - may be included more than once and specifies what to return in the reply.可能包含多个,指定响应中返回什么。
    • t - translation of source text 原文本的翻译结果
    • at - alternate translations
    • rm - transcription / transliteration of source and translated texts
    • bd - dictionary, in case source text is one word (you get translations with articles, reverse translations, etc.)
    • md - definitions of source text, if it's one word
    • ss - synonyms of source text, if it's one word
    • ex - examples
    • rw - See also list.
  • client t probably represents the standalone google translate web app (as opposed to a mobile app, or the widget that pops up if you google search "translate")
  • srcrom seems to be present when the source text has no spelling suggestions

请求参数中比较重要的为:需要翻译的文本(q)、编码(ie)、code(sl), 翻译后编码(tl),还有一个tk,tk估计是用来防止爬取的吧。tk是根据tkk和翻译文字计算出来的。从google的js中可以看到:
TKK=eval('((function(){var a\x3d3334185392;var b\x3d-2857022239;return 423993+\x27.\x27+(a+b)})())')
当然也给出了tk的计算公式。不过给出公式太复杂:
_.Tk=function(a,b){var c=new _.Sk([a])
还好,国外大鸟给出了tk的计算方法。

var TKK = ((function() {  
  var a = 561666268;  
  var b = 1526272306;  
  return 406398 + '.' + (a + b);  
})());  
  
function b(a, b) {  
  for (var d = 0; d < b.length - 2; d += 3) {  
      var c = b.charAt(d + 2),  
          c = "a" <= c ? c.charCodeAt(0) - 87 : Number(c),  
          c = "+" == b.charAt(d + 1) ? a >>> c : a << c;  
      a = "+" == b.charAt(d) ? a + c & 4294967295 : a ^ c  
  }  
  return a  
}  
  
function tk(a) {  
    for (var e = TKK.split("."), h = Number(e[0]) || 0, g = [], d = 0, f = 0; f < a.length; f++) {  
        var c = a.charCodeAt(f);  
        128 > c ? g[d++] = c : (2048 > c ? g[d++] = c >> 6 | 192 : (55296 == (c & 64512) && f + 1 < a.length && 56320 == (a.charCodeAt(f + 1) & 64512) ? (c = 65536 + ((c & 1023) << 10) + (a.charCodeAt(++f) & 1023), g[d++] = c >> 18 | 240, g[d++] = c >> 12 & 63 | 128) : g[d++] = c >> 12 | 224, g[d++] = c >> 6 & 63 | 128), g[d++] = c & 63 | 128)  
    }  
    a = h;  
    for (d = 0; d < g.length; d++) a += g[d], a = b(a, "+-a^+6");  
    a = b(a, "+-3^+b+-f");  
    a ^= Number(e[1]) || 0;  
    0 > a && (a = (a & 2147483647) + 2147483648);  
    a %= 1E6;  
    return a.toString() + "." + (a ^ h)  
}  

或者通过下边函数计算tk, 就看TKK在哪定义了。
function tk(a, TKK) {  
    for (var e = TKK.split("."), h = Number(e[0]) || 0, g = [], d = 0, f = 0; f < a.length; f++) {  
        var c = a.charCodeAt(f);  
        128 > c ? g[d++] = c : (2048 > c ? g[d++] = c >> 6 | 192 : (55296 == (c & 64512) && f + 1 < a.length && 56320 == (a.charCodeAt(f + 1) & 64512) ? (c = 65536 + ((c & 1023) << 10) + (a.charCodeAt(++f) & 1023), g[d++] = c >> 18 | 240, g[d++] = c >> 12 & 63 | 128) : g[d++] = c >> 12 | 224, g[d++] = c >> 6 & 63 | 128), g[d++] = c & 63 | 128)  
    }  
    a = h;  
    for (d = 0; d < g.length; d++) a += g[d], a = b(a, "+-a^+6");  
    a = b(a, "+-3^+b+-f");  
    a ^= Number(e[1]) || 0;  
    0 > a && (a = (a & 2147483647) + 2147483648);  
    a %= 1E6;  
    return a.toString() + "." + (a ^ h)  
}  

但是tkk是固定的, 实际翻译过程中, tkk也是计算得到的。 因此需要先发送请求, 得到tkk, 再根据得到的tkk计算tk。

tk计算过程:

首先计算tkk, 上面说到过, tkk再原来的js中是计算过的。
TKK=eval('((function(){var a\x3d3334185392;var b\x3d-2857022239;return 423993+\x27.\x27+(a+b)})())')

因此, 可以先得到这个tkk。使用engin对象的eval方法, 这里先简单介绍流程,详细代码见后文。

HttpGet httpGet = new HttpGet("https://translate.google.cn/");
response = httpclient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
    result = EntityUtils.toString(response.getEntity(), "UTF-8");
}
if(StringUtils.isNotBlank(result)){
    if(result.indexOf("TKK") > -1){
       String tkkArea = result.split("TKK")[1];
       tkkArea= tkkArea.split("\\)\\;")[0];
       tkkArea= tkkArea+ ");";
       tkkArea= tkkArea.substring(1, tkkArea.length());
       ScriptEngineManager manager = new ScriptEngineManager();
       ScriptEngine engine = manager.getEngineByName("javascript");
       String tkk = (String) engine.eval(tkkArea);
}

有了tkk了, 就可以根据国外大鸟给的js代码计算tk了。在这里, 使用engin对象的eval方法和反射计算tk:

    public static String getTK(String word, String tkk){
        String result = null;
        try{
            if (engine instanceof Invocable){
                Invocable invocable = (Invocable) engine;
                result = (String) invocable.invokeFunction("tk", new Object[]{word, tkk});
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        return result;
    }

最终拼接的请求参数为:

StringBuffer buffer = new StringBuffer("https://translate.google.cn/translate_a/single?client=t");
        buffer.append("&sl=" + from);    // 翻以前语言code
        buffer.append("&tl=" + to);        // 翻译后语言code
        buffer.append("&hl=zh-CN&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&source=btn&kc=0");
        buffer.append("&tk=" + _tk);    // 计算得到的tk
        buffer.append("&q=" + word);  // 需要翻译的词条

发送请求

有了请求路径, 就可以发送请求了。 就类似于知道路径采集网站信息。

HttpGet httpGet = new HttpGet(url);
response = httpclient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
    result = EntityUtils.toString(response.getEntity(), "UTF-8");
}

请求结果处理

String result = browser.executeGet();
JSONArray array = (JSONArray) JSONArray.parse(result);
JSONArray r_array = array.getJSONArray(0);
StringBuffer r_buffer = new StringBuffer();
for(int i = 0; i < r_array.size(); i++){
     String _r = r_array.getJSONArray(i).getString(0);
     if(StringUtils.isNotBlank(_r)){
         r_buffer.append(_r);
     }
}

经过这些, 就可以实现文本的翻译了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容