Google Translation API Analysis
题图来自网络
1 前言
为了实现一个本地单词测试系统 MemorizingWords (大致就是给定单词读音,用户反应出该单词的拼写和意思,然后校验)。 加之,之前我是一名标准的 Google 脑残粉,遂,研究 Google-Translate 网站的前端代码。分析出翻译和语音 API。 希望可以获取到相关的数据。
Google 的所有页面都是经过压缩的,HTML 页面也不例外。研究的时候异常艰难。
在研究相关的 JS 代码的时候,也是运气好,被我碰到了。对于这种排查接口的行为我总结出了一个经验,
可以通过搜索 XMLHttpRequest
,迅速定位到数据入口。之后打断点跟踪。如果当时没有找到这个,我不知道我还能不能找出这些数据。
还有,Google 在接口方面还是做了一点功课的,比如获取数据接口需要加上一个 Token, 这个 Token 是用 JS 前端生成的。 没有这个 Token,就无法正常获取数据。这个我后面会详细讲。
接口随时可能失效,请自行探索或者邮件我协助处理。 好的,让我们开始吧。
2 翻译
GET https://translate.google.cn/translate_a/single?client=t&sl=en&tl=${tl}&hl=en&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&rom=1&srcrom=1&ssel=3&tsel=6&kc=0&tk=${tk(word)}&q=${encodeURIComponent(word)}
核心参数:
- tl=en // 翻译语言
- hl=en // 被翻译语言
- ie=UTF-8
- oe=UTF-8
- tk=tk(word)
- q=encodeURIComponent(word)
其中生成 tk
(Token) 的方法函数如下。详细代码请戳 这里
var oM = function(a) { var b; if (null !== nM) b = nM; else { b = lM(String.fromCharCode(84)); var c = lM(String.fromCharCode(75)); b = [b(), b()]; b[1] = c(); b = (nM = window[b.join(c())] || k) || k } var d = lM(String.fromCharCode(116)) , c = lM(String.fromCharCode(107)) , d = [d(), d()]; d[1] = c(); c = cb + d.join(k) + Ff; d = b.split(jd); b = Number(d[0]) || 0; for (var e = [], f = 0, g = 0; g < a.length; g++) { var m = a.charCodeAt(g); 128 > m ? e[f++] = m : (2048 > m ? e[f++] = m >> 6 | 192 : (55296 == (m & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ? (m = 65536 + ((m & 1023) << 10) + (a.charCodeAt(++g) & 1023),e[f++] = m >> 18 | 240,e[f++] = m >> 12 & 63 | 128) : e[f++] = m >> 12 | 224,e[f++] = m >> 6 & 63 | 128),e[f++] = m & 63 | 128) } a = b; for (f = 0; f < e.length; f++) a += e[f], a = mM(a, $b); a = mM(a, Zb); a ^= Number(d[1]) || 0; 0 > a && (a = (a & 2147483647) + 2147483648); a %= 1E6; return c + (a.toString() + jd + (a ^ b)) }
有了获取翻译接口数据的 Token 之后,我以为就可以迅速的获取数据了,但是我失败了。Google 返回的数据不是标准的 JSON 数据格式。需要用特殊的方式转换。
转换核心是用 eval
函数。这个真是出乎我的意料,真是找了好久。
var Pb = "(", Ub = ")" var TK = function(a) { return eval(Pb + a + Ub) }
有了上述 2 个核心函数,你就可以欢快的去写脚本翻译单词啦。
3 语音
相对翻译数据来说,获取语音的接口就相对容易一些了。
Translate 页面接口
GET https://translate.google.cn/translate_tts?ie=UTF-8&total=1&idx=0&client=t&tl=en$(tk(word))&q=encodeURIComponent(word)
核心参数:
- ie=UTF-8
- tl=en // 发音语言
- tk=tk(word)
- q=encodeURIComponent(word)
tk
生成函数参照上一小节。该接口的发音是 Google “实时”计算出的值。所以,你给定任何字母组合,Google 都会返回一段语音数据。
另外,在 Google 搜索页面也有一个语音接口
GET https://ssl.gstatic.com/dictionary/static/sounds/de/0/[your-word-x].mp3
这个接口唯一的参数就是所查单词。但是有一个限制,就是有些单词可能没有发音文件,或者单词错误也不会有读音(废话)。
4 尾声
谷歌翻译页面的源代码被 Google 精心处理过,上述接口我也是花费了一个下午才排查出来。还有就是运气好,让我比较快速的找到了数据入口函数,不然真的很难破解。 所有 JS 代码都被压缩和混淆过的,所以肉眼不是很好分辨。分析的时候,一定要顶住!当发现一条路无法走通的时候,可以转换一下思路,曲线救国。一定会有出路的!
对于数据解析,也是颠覆了我之前的看法。原先我的脑海中只有 JSON 或者 XML。通过这次研究 Google 翻译页面的代码,让我的思路又多了一条。
最后感谢 Google 提供了这么好的服务。另外, https://translate.google.cn 不需要 Fan Qiang 也可以访问哦。
以上。