首页 Google Translate的tk生成以及参数详情

Google Translate的tk生成以及参数详情

°只为大大 2017-09-25 Google Translate tk 15870 0

Google Translate

之前写过一个Visual Studio翻译的插件 里面使用了百度,有道,Bing以及Google翻译,其中本想使用google翻译的api来实现,但是Google翻译是要收费的,所以只好直接抓包https://translate.google.com页面中的翻译接口,但是其中有一个比较麻烦的tk参数,

插件下载地址 : https://marketplace.visualstudio.com/items?itemName=vs-publisher-1462295.VsTranslator 暂只支持Visual Studio 2013  2015

所以找到相关教程以分享

翻译 url :

http://translate.google.cn/translate_a/single?client=t&sl=zh-CN&tl=en&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&ssel=0&tsel=0&kc=0&tk=911980.765353&q=%E4%BD%A0%E5%A5%BD

tk加密过的 且不能随意修改,一个tk是通过翻译的文本加密而来, 下面是加密js

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

或者下面未加密的js代码

function shiftLeftOrRightThenSumOrXor(num, opArray) {
    return opArray.reduce((acc, opString) => {
        var op1 = opString[1];    //    '+' | '-' ~ SUM | XOR
        var op2 = opString[0];    //    '+' | '^' ~ SLL | SRL
        var xd = opString[2];    //    [0-9a-f]

        var shiftAmount = hexCharAsNumber(xd);
        var mask = (op1 == '+') ? acc >>> shiftAmount : acc << shiftAmount;
        return (op2 == '+') ? (acc + mask & 0xffffffff) : (acc ^ mask);
    }, num);
}

function hexCharAsNumber(xd) {
    return (xd >= 'a') ? xd.charCodeAt(0) - 87 : Number(xd);
}

function transformQuery(query) {
    for (var e = [], f = 0, g = 0; g < query.length; g++) {
      var l = query.charCodeAt(g);
      if (l < 128) {
          e[f++] = l;                    //    0{l[6-0]}
      } else if (l < 2048) {
          e[f++] = l >> 6 | 0xC0;        //    110{l[10-6]}
          e[f++] = l & 0x3F | 0x80;    //    10{l[5-0]}
      } else if (0xD800 == (l & 0xFC00) && g + 1 < query.length && 0xDC00 == (query.charCodeAt(g + 1) & 0xFC00)) {
          //    that's pretty rare... (avoid ovf?)
          l = (1 << 16) + ((l & 0x03FF) << 10) + (query.charCodeAt(++g) & 0x03FF);
          e[f++] = l >> 18 | 0xF0;        //    111100{l[9-8*]}
          e[f++] = l >> 12 & 0x3F | 0x80;    //    10{l[7*-2]}
          e[f++] = l & 0x3F | 0x80;        //    10{(l+1)[5-0]}
      } else {
        e[f++] = l >> 12 | 0xE0;        //    1110{l[15-12]}
        e[f++] = l >> 6 & 0x3F | 0x80;    //    10{l[11-6]}
        e[f++] = l & 0x3F | 0x80;        //    10{l[5-0]}
      }
    }
    return e;
}

function normalizeHash(encondindRound2) {
    if (encondindRound2 < 0) {
        encondindRound2 = (encondindRound2 & 0x7fffffff) + 0x80000000;
    }
    return encondindRound2 % 1E6;
}

function calcHash(query, windowTkk) {
    //    STEP 1: spread the the query char codes on a byte-array, 1-3 bytes per char
    var bytesArray = transformQuery(query);

    //    STEP 2: starting with TKK index, add the array from last step one-by-one, and do 2 rounds of shift+add/xor
    var d = windowTkk.split('.');
    var tkkIndex = Number(d[0]) || 0;
    var tkkKey = Number(d[1]) || 0;

    var encondingRound1 = bytesArray.reduce((acc, current) => {
        acc += current;
        return shiftLeftOrRightThenSumOrXor(acc, ['+-a', '^+6'])
    }, tkkIndex);

    //    STEP 3: apply 3 rounds of shift+add/xor and XOR with they TKK key
    var encondingRound2 = shiftLeftOrRightThenSumOrXor(encondingRound1, ['+-3', '^+b', '+-f']) ^ tkkKey;

    //    STEP 4: Normalize to 2s complement & format
    var normalizedResult = normalizeHash(encondingRound2);

    return normalizedResult.toString() + "." + (normalizedResult ^ tkkIndex)
}

// usage example:
var tk = calcHash('hola', '409837.2120040981');
console.log('tk=' + tk);
 // OUTPUT: 'tk=70528.480109'

google 上的地址 (2017-03-24) 此时的方法Ip=function(a) : https://translate.google.cn/translate/releases/twsfe_w_20170320_RC00/r/js/desktop_module_main.js

其他参数详情:

  • sl - 源语言 (auto代表自动检测) en
  • tl - 目标语言 zh-CN
  • q - 要翻译的文本 记得url编码一下 你好
  • ie - 输入的编码 UTF-8
  • oe - 输出的编码 UTF-8
  • tk - 上面js加密的结果 911980.765353
  • dt - may be included more than once and specifies what to return in the reply.Here are some values for dt. If the value is set, the following data will be returned:
  • 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.

参考:

  1. http://stackoverflow.com/questions/32053442/google-translate-tts-api-blocked
  2. http://stackoverflow.com/questions/26714426/what-is-the-meaning-of-google-translate-query-params

除另有声明外,本文章Google Translate的tk生成以及参数详情采用 知识共享(Creative Commons) 署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议 进行许可。

评论
目录