百度翻译之爬虫js逆向解析
爱吃豆腐的愉悦怪
编辑于 2022年10月30日 14:32

百度翻译网址  : https://fanyi.baidu.com

第一步分析网页

打开页面之后,摁F12,打开开发者工具,在文本框中输入想要翻译的词汇

这时,就能看到network中的请求响应:

https://fanyi.baidu.com/v2transapi?from=zh&to=en,请求方式为post,

鼠标往下移动,能看到请求自带Form Data的参数:

再重复一次操作:

就能得出两次请求所带的参数的不同之处。

想要得到动态sign的数据,需要点击下图选项,在参数中选择一个参数放到search中,然后点击处于蓝色方框的simple_means_flag

把鼠标移到sign: L(e)的这行的行数8392中点击,打上断点,在页面再点击一次翻译,就会显示出前端的数据,把鼠标移到L,他会显示出一个函数的调用,点击进入函数

点击f(e)

可以看得出来传入函数的型参r就是我们在页面输入的需要翻译字符, 点击下图红框选项,让它执行下一行,就会把参数显示出来了

把2703-2734行代码复制下来,放到本地保存fanyi_baidu_com.js文件

第二步 开始写爬虫程序

在pycharm的终端中下载第三方库 PyExecJS,jsonpath, requests

先写一个用户代理随机分配的函数

建立自定义的爬虫函数

在请求头(request headers)中找到User-Agent,  Cookie,  Referer, 复制里面的值下来到文件中,用来应对反爬策略

运行代码查看结果

跳出报错信息,知道了 i 未定义,主函数中并没有 i 这个变量, 于是把目标转移到网页当中选中watch点击+直接输入  点击+旁边的刷新,就能得到数据

在js文件中添加上这个参数

再试试打印结果

在watch这种输入n,得出的结果是 n ( r  , o )

把鼠标移到 p = (D , F), 点击进去直接黄色黄色高亮会跳到n ( r  , o )的函数

把这段代码复制下来,放到js文件中

最后再运行下代码

得到sign的参数, 使用变量接收,并把它放到字典中保存

使用requests的方法post开始爬取数据

使用jsonpath的方法解析json数据, 运行结果得出翻译结果

完整爬虫代码

def User_Agent():    import random    User_Agent_list = [        "Mozilla/5.0 (Windows NT 6.1; WOW64) appleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1"        "Mozilla/5.0 (X11; CrOS i686 2268.111.0) appleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",        "Mozilla/5.0 (Windows NT 6.1; WOW64) appleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",        "Mozilla/5.0 (Windows NT 6.2) appleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",        "Mozilla/5.0 (Windows NT 6.2; WOW64) appleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",        "Mozilla/5.0 (X11; Linux x86_64) appleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",        "Mozilla/5.0 (Windows NT 6.0) appleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",        "Mozilla/5.0 (Windows NT 6.1; WOW64) appleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",        "Mozilla/5.0 (Windows NT 5.1) appleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) appleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",        "Mozilla/5.0 (Windows NT 6.2) appleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",        "Mozilla/5.0 (Windows NT 6.1; WOW64) appleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",        "Mozilla/5.0 (Windows NT 6.2) appleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",        "Mozilla/5.0 (Windows NT 6.1; WOW64) appleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",        "Mozilla/5.0 (Windows NT 6.1) appleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",        "Mozilla/5.0 (Windows NT 6.2) appleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",        "Mozilla/5.0 (X11; Linux x86_64) appleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",        "Mozilla/5.0 (Windows NT 6.2; WOW64) appleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"    ]    return random.choices(User_Agent_list)[-1]

def baidu_fanyi():    from jsonpath import jsonpath    import execjs  # 导入执行js文件的第三方库    # 百度翻译    url = "https://fanyi.baidu.com/v2transapi?from=zh&to=en"    # 请求头    header = {        # 用户代理        'user-agent&#​39;: User_Agent(),        # 跳转网址        'referer&#​39;: "https://fanyi.baidu.com/&#​34;,        # 会话记录        'cookie&#​39;: "PSTM=1624889671; BDRCVFR[IZdXtXdDRBm]=EBD6F1bEM2tXZKdrHn8mvqV; BA"                  "IDUID=A40ADC4C6BA4061C4246C9BE890ADBCA:FG=1; H_PS_PSSID=; BIDUPSID"                  "=DF100614A15524BC80AF12360E70B2FE; Hm_lvt_64ecd82404c51e03dc91cb9e8"                  "c025574=1625065330; __yjs_duid=1_a8b2eaa3041ec1e82854c53f970c651c162"                  "5065329951; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SW"                  "ITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; Hm_lpvt_64ecd82404"                  "c51e03dc91cb9e8c025574=1625838257; ab_sr=1.0.1_NzM2MDM1OTRkNmFkN2RlYz"                  "kwNzYwMzYxYmQ4ZjFhZTNlOGI5ZDliMjRhZTRiODUzMzY5MDIxODcxM2YxZWQwNWY0ZmY"                  "0NTU4ODRjN2M3MjkwYWIyZWU2ZTcxODE3OWQ5MDM0M2IzZWZhNjkyNDgwN2RkNTU1YTI"                  "zN2RhYzM1NzMyZTU4OGFkOWNlMjNhYWEwMzc4MzcyNWIxNzM1NTg5ZA==; __yjs_st="                  "_Nzc4MmU3Mzk2NDRiYjA4ZTQ4YzY3NjQ3MGZlZmY5OWQ2OThjOTJhZjg2MGUzNjc2NTd"                  "mN2Y2OTMwYTlhZWJlOGUxOTAwY2E1OTY3MDY3YTg2ZDMwMDYxNTc2OTI4ZjRlNzlmODU"                  "5NDIzMjdkYzJjYzQ3YWRkOTY3ODJiZDc4NTVjYmQxZWE5ZmRjNjYyOGQ5OWNkZTRmZmY"                  "5OTk0YWE1OTk1MmEzYWZiN2Y0ZWFjYzI5YTFmMTAzY2Q2OWMyMWJmNzY1YWFmM2ZjYjJ"                  "mMDg2OTYyNTMzNDRlZjE4YzY2MmFmNDU4ZTdhMWRhODIzY2U1OWM4MWIwYzMzY2E2ZW"                  "RjYl83XzUxM2E1Yzhk&#​34;,    }    query = str(input("请输入要翻译的关键词: &#​34;))    # 读取js文件    with open('fanyi_baidu_com.js&#​39;, 'r&#​39;) as r:        read = r.read()    # 使用变量接收js第三方库的方法,并接收读取到的js文件    exe = execjs.compile(read)    sign = exe.call("e&#​34;, query)  # 执行js文件    print(sign)    # 参数    data = {    'from&#​39;: 'zh&#​39;,    'to&#​39;: 'en&#​39;,    'query&#​39;: query,    'transtype&#​39;: 'realtime&#​39;,    'simple_means_flag&#​39;: '3&#​39;,    'sign&#​39;: sign,    'token&#​39;: 'a8e3ac80bd327c34add38ea58ffbcef1',    'domain&#​39;: 'common&#​39;,    }    # print(data)    res = requests.post(url, data=data, headers=header).json()    print(jsonpath(res, "$..dst&#​34;)[0]) 完整js文件

   function n(r, o) {        for (var t = 0; t < o.length - 2; t += 3) {            var a = o.charAt(t + 2);            a = a >= "a&#​34; ? a.charCodeAt(0) - 87 : Number(a),            a = "+&#​34; === o.charAt(t + 1) ? r >>> a : r << a,            r = "+&#​34; === o.charAt(t) ? r + a & 4294967295 : r ^ a        }        return r    } function e(r) {        var o = r.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);        if (null === o) {            var t = r.length;            t > 30 && (r = "&#​34; + r.substr(0, 10) + r.substr(Math.floor(t / 2) - 5, 10) + r.substr(-10, 10))        } else {            for (var e = r.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), C = 0, h = e.length, f = []; h > C; C++)                "&#​34; !== e[C] && f.push.apply(f, a(e[C].split("&#​34;))),                C !== h - 1 && f.push(o[C]);            var g = f.length;            g > 30 && (r = f.slice(0, 10).join("&#​34;) + f.slice(Math.floor(g / 2) - 5, Math.floor(g / 2) + 5).join("&#​34;) + f.slice(-10).join("&#​34;))        }        var i = "320305.131321201&#​34;;        var u = void 0          , l = "&#​34; + String.fromCharCode(103) + String.fromCharCode(116) + String.fromCharCode(107);        u = null !== i ? i : (i = window[l] || "&#​34;) || "&#​34;;        for (var d = u.split(".&#​34;), m = Number(d[0]) || 0, s = Number(d[1]) || 0, S = [], c = 0, v = 0; v < r.length; v++) {            var A = r.charCodeAt(v);            128 > A ? S[c++] = A : (2048 > A ? S[c++] = A >> 6 | 192 : (55296 === (64512 & A) && v + 1 < r.length && 56320 === (64512 & r.charCodeAt(v + 1)) ? (A = 65536 + ((1023 & A) << 10) + (1023 & r.charCodeAt(++v)),            S[c++] = A >> 18 | 240,            S[c++] = A >> 12 & 63 | 128) : S[c++] = A >> 12 | 224,            S[c++] = A >> 6 & 63 | 128),            S[c++] = 63 & A | 128)        }        for (var p = m, F = "&#​34; + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(97) + ("&#​34; + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(54)), D = "&#​34; + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(51) + ("&#​34; + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(98)) + ("&#​34; + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(102)), b = 0; b < S.length; b++)            p += S[b],            p = n(p, F);        return p = n(p, D),        p ^= s,        0 > p && (p = (2147483647 & p) + 2147483648),        p %= 1e6,        p.toString() + ".&#​34; + (p ^ m)    };