百度翻译
实战案例(调试工具)
接下来. 我们来破解真正的百度翻译

通过抓包可以发现. 我们之前抓取的百度翻译其实是个伪翻译.
真正的一句话的翻译其实它的url应该是:https://fanyi.baidu.com/v2transapi?from=en&to=zh



接下来就是分析这一坨
y = {
from: d.fromLang, // 从xxxx
to: d.toLang, // 翻译成xxxx
query: e, // 被翻译的内容
transtype: r, // 固定的翻译类型
simple_means_flag: 3, // 常量
sign: L(e), // ????
token: window.common.token, // token. 这个在页面源代码里能找到
domain: R.getCurDomain() // 固定值.
};
现在有3个值, 无法直接确定. 一个是L(e), 一个是token. 另一个是R.getCurDomain()
先看token.

由于在我进行翻译的时候. 页面是没有刷新的. 所以, 这个token一般在进行翻译的时候是不会改变的.
接下来是这个domain的鬼东西, 我们在页面中设置一个断点. 并重新发送请求.



点进去返回的是个M. 找M

OK. M是常量. "common"
齐活. 剩下的就是L(e)了. 首先e是被翻译的内容. 所以这里是把"要翻译的内容"传递给了L. 但是这个L在哪里. 不好找. 很简单. 设置一个断点. 就可以.


程序停在这里了. 接下来就是这三个按钮. 从左到右.
第一个: 释放掉当前debug. 程序继续向后运行. 直到结束或下一个断点
第二个: 运行下一步. 相当于一行代码. 但是像咱们这里. 是在一个{}中间进行的断点. 而整个{}; 被认为是一行代码. 所以下面的 token等会被过掉.
第三个: 运行到当前行内部. 咱们这里就是运行到L(e)里面, 看看L(e)里面是干什么的.

这里就是那个L(e)了. 但这东西属实看不明白. 也不容易看明白. 里面是一个签名算法. 十分难搞.
仔细观察下. 发现该函数内部只调用了n() a()函数. 其他函数都是js内置的东西.OK 向上简单寻找就发现了. 这里是一个大闭包.

也就是说. 整个签名的计算. 就这些功能. 没有调用外界的其他功能. 那就好办了. 我们可以直接把这个闭包内的三个函数搞出来. 变成我们的js文件

尝试着签个名试试看:
import requests
import execjs
f = open("bbd.js", mode="r", encoding='utf-8')
js = execjs.compile(f.read())
# execjs._exceptions.ProgramError: ReferenceError: window is not defined.
ret = js.call('e', 'love')
print(ret)
报错了. 说这里面没有window
确实, 由于我们的js是在node里面运行的. node是没有window对象的. 怎么办?


整合起来这里要用到window['gtk'], 这玩意哪里找? 老实说. 真不好找. 在前面我们找token的时候. 偶然间, 发现了这样一段代码:

OK了 . 搞定...我们只要把js里面的window['gtk']修改成这个就好了

至此, 所有参数到位. 写代码就好了.
代码:
import requests
import execjs
f = open("baidu加密.js", mode="r", encoding='utf-8')
js = execjs.compile(f.read())
url = "https://fanyi.baidu.com/v2transapi?from=en&to=zh"
content = input("请输入一段英文:")
data = {
"from": "en",
"to": "zh",
"query": content,
"transtype": "realtime",
"simple_means_flag": "3",
"sign": js.call("e", content),
"token": "c63d27ea65fdf259bf4d56b792e47b17",
"domain": "common",
}
headers = {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Referer": "https://fanyi.baidu.com/",
"Cookie": "REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; BIDUPSID=7214BF57BA799CC46A76979BF673523E; PSTM=1623064780; __yjs_duid=1_7946e25e70873bbe5515a663714cef991623067825398; BAIDUID=C434B9AC411BEFD0688E2DD206C8429A:FG=1; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; MCITY=-131%3A; BDUSS=kl4RWZySlNaNlRrdWNkSVRXYjYtNGkyUzFCZlhmeklhMDFtcjRLM01GdG4zMVZoRVFBQUFBJCQAAAAAAAAAAAEAAACh3e-019TDvczlwfnB-bjnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGdSLmFnUi5hM; BDUSS_BFESS=kl4RWZySlNaNlRrdWNkSVRXYjYtNGkyUzFCZlhmeklhMDFtcjRLM01GdG4zMVZoRVFBQUFBJCQAAAAAAAAAAAEAAACh3e-019TDvczlwfnB-bjnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGdSLmFnUi5hM; H_PS_PSSID=34438_34440_34380_34496_33848_34450_34092_34107_26350_34425_22160; delPer=0; PSINO=2; BA_HECTOR=a08k202181a52h208d1gj6e0m0q; BAIDUID_BFESS=DDAD1DC127ED72714BFB37825559ACDB:FG=1; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1628330239,1628390196,1629451250,1630747372; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1630747372; ab_sr=1.0.1_ODBhYjIwYzRhMjk4NDNhZDYwYjRmZWZjM2QwY2E3MGNlMDRjYTI1ZjViODM2MDgxODk5NzJjNDFkZTAxYzc0OTVkYmNhYjZiMWMzZDFmNWFkN2QxMzAwMzZlZjhjYmE3ODkxZGRkNDJkNTY2N2M0NTQxODU5YmU4YTA1NGZjYTJkMDUzN2ZkMGVkMzlmOTU1M2ZlZTRhYWY4ZDQ5YTZmNTJjYmExYzk1ZTdiY2I5MTA4YjcyZDE3MWE1MTE5YjBj",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
}
resp = requests.post(url, data=data, headers=headers)
print(resp.json())
浙公网安备 33010602011771号