調用翻譯接口翻譯詞條

調用谷歌翻譯接口方式

谷歌翻譯的API從2011年12月1號起是一項收費的服務了, 通過上網查詢資料, 整理了一套破解的方法,記錄一下。

雖然調用谷歌給出的接口是收費的, 但是網頁上谷歌的在線翻譯(https://translate.google.cn/)是免費的。因此, 可以通過對在線翻譯頁面爬取的方式, 獲取詞條翻譯后的結果。

整體的流程就是:拼裝請求參數(shù), 發(fā)送請求信息, 處理相應結果。下面逐條介紹。

拼裝請求參數(shù)

通過抓包的方式, 查看請求的路徑和請求的參數(shù)。舉個例子:翻譯“你好”。

翻譯頁面:


詞條.png

翻譯時, 對頁面信息進行抓取,可以看到發(fā)送翻譯請求的一些基本信息。比如說請求方式:GET。比如說請求參數(shù):Query String Parameter。 比如說請求過程的cookie等。


請求信息.png
查詢的參數(shù).png

部分請求參數(shù)介紹:(漢語自己翻譯的, 不知道對不對)

  • 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

請求參數(shù)中比較重要的為:需要翻譯的文本(q)、編碼(ie)、code(sl), 翻譯后編碼(tl),還有一個tk,tk估計是用來防止爬取的吧。tk是根據(jù)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)  
}  

或者通過下邊函數(shù)計算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也是計算得到的。 因此需要先發(fā)送請求, 得到tkk, 再根據(jù)得到的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了, 就可以根據(jù)國外大鳥給的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;
    }

最終拼接的請求參數(shù)為:

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);  // 需要翻譯的詞條

發(fā)送請求

有了請求路徑, 就可以發(fā)送請求了。 就類似于知道路徑采集網站信息。

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);
     }
}

經過這些, 就可以實現(xiàn)文本的翻譯了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容