python作为一种轻量化的解释性语言,语法简单,学起来比件容易,掌握一门语言在信息社会对自己是很有帮助的。大家也知道,现在高校课程除了C语言、C++、汇编语言等,又开设了python语言,这足以证明python有多流行了。而且在一些工作要求中,需要掌握数据分析、数据清洗,而python由于自身有很多库来支持,仅仅需要少量的代码就可以实现丰富的功能。掌握好一门编程语言,在日常的工作学习中,往往能起到事半功倍的效果。因此,为了练习巩固成果,我参考了一些大神的代码,自己试试来爬取百度翻译,不然每次打开浏览器太麻烦了。
爬虫就是模拟我们浏览的方式,通过浏览器(输入url网址)向服务器发送请求(requests),然后得到服务器的返回结果(response)。
因此我们首先打开谷歌浏览器,进入百度翻译的网站,按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的值在改变。
获取sign的值需要会调试js代码,至少看得懂,复制刚才的URL到sources下面的如下图2处,点击加号完成。在3内输入内容观察左右变化。
点击图中大括号,经过不断的调试发现sign=y(n),由这个函数生成。将鼠标停留在y(函数上),发现由e函数而来。继续走。。
我们找到了生成sign的js代码。复制这段代码保存为baidu.js文件。
下面我们来尝试生成sign这个值。下图可以看到该值与我们输入的内容有关。
代码如下:需要安装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的值。
函数运行原理如下,写了个小函数的功能,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)
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#更新头部信息
data={
'from': lan_type,#语言类型
'to': 'en',
'query': word,
'transtype': 'realtime',
'simple_means_flag': '3',
'sign': sign,
'token': token,
'domain': 'common',
}
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出来了,我们可以开心的撸代码了,一切都具备了。
代码如下:
# 导入模块
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