python爬虫爬取百度翻译结果
python作为一种轻量化的解释性语言,语法简单,学起来比件容易,掌握一门语言在信息社会对自己是很有帮助的。大家也知道,现在高校课程除了C语言、C++、汇编语言等,又开设了python语言,这足以证明python有多流行了。而且在一些工作要求中,需要掌握数据分析、数据清洗,而python由于自身有很多库来支持,仅仅需要少量的代码就可以实现丰富的功能。掌握好一门编程语言,在日常的工作学习中,往往能起到事半功倍的效果。因此,为了练习巩固成果,我参考了一些大神的代码,自己试试来爬取百度翻译,不然每次打开浏览器太麻烦了。
百度翻译爬虫
1.分析准备工作
爬虫就是模拟我们浏览的方式,通过浏览器(输入url网址)向服务器发送请求(requests),然后得到服务器的返回结果(response)。
第一步:按F12或者(鼠标右键进检查)进入开发者模式
因此我们首先打开谷歌浏览器,进入百度翻译的网站,按F12或者(鼠标右键今检查)进入开发者模式。如下图所示:
第二步:在翻译框内输入观察右边变化
在输入框输入你好,我们看到右边出现了一些变化,初次使用,单击network—XHR—response,我们发现找到了我们想要的结果,就在返回的一串json代码中,这里注意一下返回链接的顺序(很重要,这里容易栽跟头):1是langdetect(查询获取我们输入语言的种类)2.是返回结果,编程序也要按照这样的顺序来。
第三步 分析请求头部和数据参数
在头部我们发现了需要请求的网址URL,浏览器头的一些信息,formdata中的一些数据(
from: zh(你输入语言的类型)
to: en(翻译成什么语言)
query: (翻译的内容)
transtype: realtime#不管这个
simple_means_flag: 3#不管这个
sign: 232427.485594#这个很重要,这个需要我们获取
token: 5ad8811fd7f7e80f91b8984ad1ae9d79#这个在htnl页面可以找到
domain: common#不管这个
)
基本上到这里分析就结束了,sign关于这个值,读者可以自己多输入几次翻译的内容,可以看到只有sign和token的值在改变。
2.如何获取sign的值
获取sign的值需要会调试js代码,至少看得懂,复制刚才的URL到sources下面的如下图2处,点击加号完成。在3内输入内容观察左右变化。
点击图中大括号,经过不断的调试发现sign=y(n),由这个函数生成。将鼠标停留在y(函数上),发现由e函数而来。继续走。。
我们找到了生成sign的js代码。复制这段代码保存为baidu.js文件。
下面我们来尝试生成sign这个值。下图可以看到该值与我们输入的内容有关。
3.计算sign值
1.第一种方法,读取刚才的文件
代码如下:需要安装execjs库方法:pip3 install PyExecJS
使用方法:https://www.cnblogs.com/xiaoqianbook/p/11243689.html
import execjs with open(r"C:\Users\Administrator.USER-20200806OT\Desktop\baidu.js") as bs: jsdata=bs.read() sign=execjs.compile(jsdata).call('e','你') print(sign)
运行后提示缺少i参数,不慌,我们继续分析。发现这里面的值有点可疑,我们直接定义var i=‘320305.131321201’
加入变量值,再次运行成功算出sign的值。
2.第二种方法
函数运行原理如下,写了个小函数的功能,JS代码太长了,这里不粘贴,后面有的。pip install js2py
js1='''#两种方法读取js
function add(num1, num2) {
return num1 + num2;
}
''' context.execute(js1)#方法1 key=context.add(2,3) print(key) import execjs#方法2 key=execjs.compile(js1).call('add',2,3) print(key)
4.构建请求头,准备爬取百度翻译结果
a.构建头部
headers={ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36', 'x-requested-with': 'XMLHttpRequest' }#构建头部 session=requests.session()#获取cookie session.headers=headers#更新头部信息
b .构建数据请求
data={ 'from': lan_type,#语言类型 'to': 'en', 'query': word, 'transtype': 'realtime', 'simple_means_flag': '3', 'sign': sign, 'token': token, 'domain': 'common', }
c.获取token
import requests import re
url1="https://fanyi.baidu.com/translate"#url地址 headers={ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36', 'x-requested-with': 'XMLHttpRequest' }#构建头部 session=requests.session()#获取cookie session.headers=headers#更新头部信息 url="https://fanyi.baidu.com/langdetect"#URL1和URL的顺序很重要,顺序错误了则获取不到需要的token,产生错误 response=session.post(url1) token=re.findall(r"token: '(.*?)'",response.text)[0] response1=session.post(url,data={'query':"你好"}).json() print('token:',token) 运行结果:
E:\pycharm\venv\Scripts\python.exe E:/pycharm/1.py
token: 9b8bb341109338ba7e875bd9a9dd88ba Process finished with exit code 0
哈哈,你们看token出来了,我们可以开心的撸代码了,一切都具备了。
5.准备爬取数据
代码如下:
# 导入模块 import requests import re import ast import execjs from datetime import datetime # driver=webdriver.Chrome() # url="https://fanyi.baidu.com/translate" # driver.get(url) # #接下来注意了,要开始获取cookie了. # # 获取cookie列表 # cookie_list=driver.get_cookies()#这里主要是使用自带的get_cookies方法 # cookie_dict={} # driver.close() # # 格式化打印cookie # for cookie in cookie_list: # cookie_dict[cookie['name']]=cookie['value'] # print(cookie_dict) # print(cookie_list) #keyword=word #------------自定义函数获取输入语言的种类----------------------- def get_lan(word,session): url='https://fanyi.baidu.com/langdetect' response=session.post(url,data={'query':word}).json() lan=response['lan'] return lan#返回lan def translate(word,session,token,lan_type): with open(r'C:\Users\Administrator.USER-20200806OT\Desktop\baidu.js') as bs: bs=bs.read() sign=execjs.compile(bs).call('e',word) print('sign:',sign) data={ 'from': lan_type, 'to': 'en',# if self.lan != 'en' else 'zh', 'query': word, 'transtype':'realtime', 'simple_means_flag':3, 'sign': sign, 'token': token, 'domain': 'common' } url='https://fanyi.baidu.com/v2transapi' response=session.post(url,data=data).json() #print(response) answer=response['trans_result']['data'][0]['dst'] to_lan=response['trans_result']['to'] to_lans=langlist[to_lan] print('token:', token) print("当前时间:", time)#只要在调用自定义函数前定义,就可直接使用,不用传递参数 print(langlist[lan_type],':',word,'<<——译为——>>',to_lans,':',answer) home_page_url="https://fanyi.baidu.com/" headers={ 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36', "x-requested-with":"XMLHttpRequest", "origin": "https://fanyi.baidu.com", "referer": "https://fanyi.baidu.com/?aldtype=16047" } #获取cookie session=requests.session() session.headers=headers
word=('keyword')#自己输入内容 lan_type=get_lan(word,session) #顺序很重要 response1=session.get(home_page_url).text#顺序应该放在获取语言类型的后面,所以这里有问题,不然会发生错误,tokenh值与sign值不匹配,报错。 token=re.findall(r"token: '(.*?)'",response1)[0] time=re.findall(r"systime: '(\d+)'",response1)[0][:-3] time=datetime.fromtimestamp(float(time)) langlist=re.findall(r'langList: (.*?)account',response1,re.S)[0] langlist=ast.literal_eval(langlist.replace('\n','').replace(' ',''))[0] translate(word,session,token,lan_type) 结果:
sign: 138860.458077 token: ffb56cf41c9a891e79ef59605d06de69
当前时间: 2020-10-13 20:53:15 英语 : keyword <<——译为——>> 中文 : 关键字
Process finished with exit code 0
附js代码:
var i="320305.131321201" function a(r) { if (Array.isArray(r)) { for (var o = 0, t = Array(r.length); o < r.length; o++) t[o] = r[o]; return t } return Array.from(r) } 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) }
或者这样,这个是别人的,哈哈:
import js2py
context = js2py.EvalJs() js = r'''
function a(r) {
if (Array.isArray(r)) {
for (var o = 0, t = Array(r.length); o < r.length; o++)
t[o] = r[o];
return t
}
return Array.from(r)
}
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)
}
''' #js中添加一行gtk #u = 'null !== i ? i : (i = window[l] || "") || ""' js = js.replace('\'null !== i ? i : (i = window[l] || "") || ""\'',gtk) #print(js) #执行js context.execute(js) word=input("请输入你的语言>>") #调用函数得到sign sign = context.e(word) print("sign:",sign) #232427.485594
本文地址:https://blog.csdn.net/xiaomao1993/article/details/109051963
上一篇: 自定义控件:用户名输入框