一、小试牛刀
在上课的时候,百度翻译之前的那个简单的接口,需要你多次尝试之后才能出来,其实只要我们打开network中的XHR就可以查看到。
步骤1:浏览器打开:fanyi.baidu.com, 按键顺序 F12>>>Network>>>XHR。
步骤2:输入job(在输入过程中会不断请求服务器),例如输入"j"时请求,”jo“时请求,"job"时也在请求,如下图:
步骤3:点开第3个我们可以看到url、请求方式、和请求数据。
步骤4:我们开始写爬虫程序。
由于我们已经看到这个接口获取翻译结果需要的参数很简单,我们就以翻译“job”为例写爬虫程序。
import requests
import json
def baidu_fanyi(kw):
"""
:param kw: 要查的单词 :return:
"""
# m目标url
base_url = "https://fanyi.baidu.com/sug"
data = {"kw":kw}
# 发起请求,返回响应
response = requests.post(base_url,data= data)
# 获取json数据
# 第一种 处理json数据
json_data= response.json()
# print(json_data)
data_list = json_data["data"]
for dict_data in data_list:
print(dict_data)
if __name__ == '__main__':
baidu_fanyi("job")
运行结果是:
{'k': 'job', 'v': 'n. 职业; (一件)工作; 职责; (作为一个单元处理的)作业 vt. 承包; 代客买卖 vi. '}
{'k': 'Jobo', 'v': '[地名] [厄瓜多尔] 霍沃'}
{'k': 'jobs', 'v': 'n. 职业; (一件)工作( job的名词复数 ); 职责; (作为一个单元处理的)作业'}
{'k': 'Jobs', 'v': '[人名] 乔布斯'}
{'k': 'JOBS', 'v': 'abbr. Job Opportunities and Basic Skills 工作环境与基本技能'}{'k': 'job', 'v': 'n. 职业; (一件)工作; 职责; (作为一个单元处理的)作业 vt. 承包; 代客买卖 vi. '}{'k': 'Jobo', 'v': '[地名] [厄瓜多尔] 霍沃'}{'k': 'jobs', 'v': 'n. 职业; (一件)工作( job的名词复数 ); 职责; (作为一个单元处理的)作业'}{'k': 'Jobs', 'v': '[人名] 乔布斯'}{'k': 'JOBS', 'v': 'abbr. Job Opportunities and Basic Skills 工作环境与基本技能'}
二、秘密翻译接口的参数破解
上面的你们是不是感觉太简单了点,不要着急!下面这个接口请求参数才是最难破解的直接上图。
这个接口里面最难获取的参数就是sign和token。
1、破解sign
步骤1:ctrl+F打开搜索框搜索“sign”, 找到sign所在的文件 index_e36080d.js
步骤2: 我们发现他是个js文件,所以我们在Sources中打开index_e36080d.js。
步骤3:我们把index_e36080d.js粘贴到我们pycharm中进行查看,搜索sign。
1、刚开始我们不难的发现会有很多不重要的信息出现。
2、在搜索的过程中,我们会发现sign:f(n)
3、使用ctrl+鼠标左键 点一下f,就会转调到下图中的地方。
4、f = t("translation:widget/translate/input/pGrab")中,显然translation:widget/translate/input/pGrab
被定义为一个方法的接口路由,推测所谓的t函数可能是调用这个接口方法。然后我们在pycharm中搜索translation:widget/translate/input/pGrab,找到这个函数。
步骤4:我们执行这个JavaScript函数。
鉴于很多学生没有node.js的环境,所以今天我们使用pyexecjs包来执行js代码。
1、安装pyexecjs包。
2、测试我们找到的函数作用。
(1)建立sign.js文件,把找到js代码粘贴进去。
function n(r, o) {
for (var t = 0; t < o.length - 2; t += 3) {
var a = o.charAt(t + 2);
a = a >= "a" ? a.charCodeAt(0) - 87 : Number(a),
a = "+" === o.charAt(t + 1) ? r >>> a : r << a,
r = "+" === 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 = "" + 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++)
"" !== e[C] && f.push.apply(f, a(e[C].split(""))),
C !== h - 1 && f.push(o[C]);
var g = f.length;
g > 30 && (r = f.slice(0, 10).join("") + f.slice(Math.floor(g / 2) - 5, Math.floor(g / 2) + 5).join("") + f.slice(-10).join(""))
}
var u = void 0
, l = "" + String.fromCharCode(103) + String.fromCharCode(116) + String.fromCharCode(107);
u = null !== i ? i : (i = window[l] || "") || "";
for (var d = u.split("."), 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 = "" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(97) + ("" + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(54)), D = "" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(51) + ("" + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(98)) + ("" + 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() + "." + (p ^ m)
}
(2)新建一个param_find.py开始测试js代码。但是我们不知道函数e和函数哪个是生成sign的,我们可以在sources中进行测试。
a. 在 sign:f(n)打个断点,然后刷线页面会出现下图中的情况。
b .鼠标放在f上会出现函数提示
c. 我们点击后转跳到函数e中,点击调试按钮开始调试。
d. 不难发现这个函数e就是来生成sign的,这时候我们看到了“job”,说明给这个函数参数应该是要翻译的内容,这样我们就搞定了,开始写Python代码执行js函数。
import execjs
def read_js(path):
with open(path, "r")as f:
f = f.read()
return f
res = execjs.compile(read_js("signa.js")).call("e", "job")
print(res)
执行之后报错了 i is not defined ,说明你还要传入i 的值320305.131321201 。
e . 通过调试js代码发现 i 应该是 320305.131321201 ,发现 i=window[l] 而上一行的 l,很明显是个定值 gtk。
需要注意的是,通过验证:查询其他单词 i 的值没有变
f. 我们sign.js中加这一行代码
var i = "320305.131321201"
g. 运行param_find.py得到231901.486124,我们比较一下翻译job的请求参数,发现sign就是 231901.486124,说明我们破解了js,成功生成了sign参数。
2、破解token
还是上面的思路我们首先在network中进行搜索token,然后按照同样的思路解决。
步骤1: 搜索哪些哪个文件中包含了token。
token为空表示第一次访问百度网站服务器端没有收到baiduid cookie,会导致翻译接口校验不通过,通过刷新解决
1、获取这个js文件。我们发现他其实可以通过请求https://fanyi.baidu.com/,这个链接获取html文件。
通过正则来获取如下js文件token的值
具体代码如下:
import re
import requests
import execjs
url = "https://fanyi.baidu.com"
headers = {
"Cookie": "BIDUPSID=EE1FBAB64E978CA7E15A21204784E059; PSTM=1574385249; MCITY=-233:; BAIDUID=8FE349D493E4028413DDDC33C39D13B2:FG=1; __yjs_duid=1_eb4f55bc190bb694fbbccd0271c4cce61614069225050; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; delPer=0; PSINO=2; BAIDUID_BFESS=BAF37D17762844A4E0C7143382B922B2:FG=1; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; H_PS_PSSID=33636_33256_33272_33709_33689_33595_33590_26350; ZD_ENTRY=baidu; BA_HECTOR=0la02ga1818l2ga4v31g58k0l0r; BCLID=10547301397971942590; BDSFRCVID=LMIOJexroG3VC5QeobuohXPMALweG7bTDYLEOwXPsp3LGJLVJeC6EG0Pts1-dEu-EHtdogKK0gOTH6KF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tJKJoCtatD_3fP36qR6sMJ8thmT22-us5Cnd2hcH0KLKEpnGWhoDbt4UKGj3XpOuJIjiaMjwWfb1MRjvh-LhefCN547QBTbd-H5bol5TtUJceCnTDMRh-lIZMb5yKMniMRr9-pPX3pQrh459XP68bTkA5bjZKxtq3mkjbPbDfn02eCKuDjRDKICV-frb-C62aKDshJTgBhcqJ-ovQTb4LTLubfni36Q3yNRu_P555l0bHxbeWfvpXn-R0hbjJM7xWeJpaJ5nJq5nhMJmKTLVbML0qto7-P3y523ion3vQpP-OpQ3DRoWXPIqbN7P-p5Z5mAqKl0MLPbtbb0xXj_0D6c3DG0Ht5Lsb5vfstcS24JED6rnhPF3hM-mXP6-35KHyH783fbt5R7vEfndWh3Yj-uUynQkBq37JD6y2UQOQ-JJSDQL0Ic_M6JXhtoxJpOgMnbMopvaKfcooqRvbURv2jDg3-A80U5dtjTO2bc_5KnlfMQ_bf--QfbQ0hOhqP-j5JIEoCvt-5rDHJTg5DTjhPrMK4QRWMT-MTryKKOC0KKheJA4LfosWh8IjhofKx-fKHnRhlR2B-3iV-OxDUvnyxAZyxomtfQxtNRJQKDE5p5hKq5S5-OobUPUDMJ9LUkqW2cdot5yBbc8eIna5hjkbfJBQttjQn3hfIkj2CKLtCvDqTrP-trf5DCShUFs-UbWB2Q-XPoO3KO4EI5hbtPKhl4JWb3utnQf5mkf3fbgylRp8P3y0bb2DUA1y4vpBtQmJeTxoUJ2-KDVeh5Gqfo15-0ebPRiJPb9Qg-qahQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0hDvPKITD-tFO5eT22-usBgjA2hcHMPoosIOKLToGbt4V5fn3XpOu0mJf0l05KfbUoqRHXnJi0btQDPvxBf7pWDTm_q5TtUJMqIDzbMohqfLn5MOyKMnitIv9-pPKWhQrh459XP68bTkA5bjZKxtq3mkjbPbDfn028DKu-n5jHjJyeH8j3J; BCLID_BFESS=10547301397971942590; BDSFRCVID_BFESS=LMIOJexroG3VC5QeobuohXPMALweG7bTDYLEOwXPsp3LGJLVJeC6EG0Pts1-dEu-EHtdogKK0gOTH6KF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF_BFESS=tJKJoCtatD_3fP36qR6sMJ8thmT22-us5Cnd2hcH0KLKEpnGWhoDbt4UKGj3XpOuJIjiaMjwWfb1MRjvh-LhefCN547QBTbd-H5bol5TtUJceCnTDMRh-lIZMb5yKMniMRr9-pPX3pQrh459XP68bTkA5bjZKxtq3mkjbPbDfn02eCKuDjRDKICV-frb-C62aKDshJTgBhcqJ-ovQTb4LTLubfni36Q3yNRu_P555l0bHxbeWfvpXn-R0hbjJM7xWeJpaJ5nJq5nhMJmKTLVbML0qto7-P3y523ion3vQpP-OpQ3DRoWXPIqbN7P-p5Z5mAqKl0MLPbtbb0xXj_0D6c3DG0Ht5Lsb5vfstcS24JED6rnhPF3hM-mXP6-35KHyH783fbt5R7vEfndWh3Yj-uUynQkBq37JD6y2UQOQ-JJSDQL0Ic_M6JXhtoxJpOgMnbMopvaKfcooqRvbURv2jDg3-A80U5dtjTO2bc_5KnlfMQ_bf--QfbQ0hOhqP-j5JIEoCvt-5rDHJTg5DTjhPrMK4QRWMT-MTryKKOC0KKheJA4LfosWh8IjhofKx-fKHnRhlR2B-3iV-OxDUvnyxAZyxomtfQxtNRJQKDE5p5hKq5S5-OobUPUDMJ9LUkqW2cdot5yBbc8eIna5hjkbfJBQttjQn3hfIkj2CKLtCvDqTrP-trf5DCShUFs-UbWB2Q-XPoO3KO4EI5hbtPKhl4JWb3utnQf5mkf3fbgylRp8P3y0bb2DUA1y4vpBtQmJeTxoUJ2-KDVeh5Gqfo15-0ebPRiJPb9Qg-qahQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0hDvPKITD-tFO5eT22-usBgjA2hcHMPoosIOKLToGbt4V5fn3XpOu0mJf0l05KfbUoqRHXnJi0btQDPvxBf7pWDTm_q5TtUJMqIDzbMohqfLn5MOyKMnitIv9-pPKWhQrh459XP68bTkA5bjZKxtq3mkjbPbDfn028DKu-n5jHjJyeH8j3J; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1616109895,1616110171,1616114964,1616138265; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1616138526; ab_sr=1.0.0_NmFiZmE4ZDBiODNkMjA5YTYwYmQyODExOWNlNjgwYjhkNGE4NTlmNWZmNDBmNTIwYzQxZmEyMzMyOWM0ZjA2ZjkyZDlhMGQ5YTI2YjIxYjljNjFmOTE4MzhjOWNiNjI1; __yjsv5_shitong=1.0_7_80992e39d5bba9b7737d7e4cc0e4876b0f75_300_1616138529336_124.114.149.34_63e643e3",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36",
}
html = requests.get(url,headers=headers).text
# print(html)
res = re.findall("<script>(.*?)</script>",html,re.S)
print(res[2])
res1 = re.findall(" token:(.*)systime:",res[2],re.S)
token = res1[0].strip().strip("'").strip("',")
print(token)
到现在我们已经破解百度翻译的加密请求参数。
想获取爬虫源码,请关注微信公众号:梓栋Code,回复“baidu”,获取源码。
三、json数据处理
把json数据进行解析,获取我们需要的结果。
处理的方法代码如下:
def processing_json(self):
"""处理json数据"""
with open(f"{self.query}.json","r",encoding="utf-8")as f:
res = f.read()
json_data = json.loads(res)
# print(json_data)
for _json in json_data["dict_result"]["synonym"][0]["synonyms"]:
print(_json["bx"])
res = _json["syn"].get("d")[0]
if isinstance(res,dict):
print(res["text"])
else:
print(res)
explain = json_data["liju_result"]["tag"]
explains = "-".join(explain)
print(explains)