本文利用爬虫+tkinter打造一个属于自己的简易翻译软件,代码较简单,但篇幅较长。
需要本文完整源码的小伙伴,可以关注公众号“python与EXCEL之交
”,在公众号后台发送“翻译
”二字获取!
前言
导入需要用到的模块:
from tkinter import * # 可视化界面模块
import hashlib # 解密模块
import time # 时间模块
import requests # 数据请求模块
import jsonpath # json 数据提取模块
import json # 配合jsonpath 把转换成json格式
本文一共有四个函数,包括加密参数破解、数据请求、可视化界面函数:
"""加密参数sign破解"""
def sign(e, i):
pass
"""加密参数bv破解"""
def bv():
pass
"""解密参数接收、数据请求、可视化界面关联"""
def data_text():
pass
"""可视化界面"""
def tk():
pass
"""启动器"""
if __name__ == '__main__':
tk()
可视化界面
我们先在tk()
函数中把可视化界面绘制出来,然后再敲打爬虫相关程序。
定义全局变量,这三个参数都是后面需要与爬虫程序关联的:
global text, entry, var
创建界面和界面标题:
root = Tk()
root.title('简易翻译')
# 显示界面
root.mainloop()
创建标签组件,设置字体和字号,定位都合适的位置:
# grid()默认0行0列
label = Label(root, text='请输入需要翻译的内容:', font=('隶书', 20)).grid()
# 输入框
entry = Entry(root, font=('隶书', 20)).grid(row=0, column=1)
创建翻译模式,value
所携带的参数是传入var
中,关联爬虫程序,当用户点击某个按钮时,所携带的参数会传入到请求函数,进行翻译模式的选择,而所携带的参数需要从网页中获取,到时会讲解。
# 设置只能单选按钮
var = StringVar()
button1 = Radiobutton(root, text='中译英', variable=var, value='en,zh-CHS')
button1.grid(row=1, column=0, sticky=S) # sticky位置,E S W N 代表东南西北
button2 = Radiobutton(root, text='英译中', variable=var, value='zh-CHS,en')
button2.grid(row=1, column=1, sticky=N)
创建列表框,展示翻译结果:
# 列表框
text = Listbox(root, font=('隶书', 16), width=50, heigh=15)
text.grid(row=2, columnspan=2)
创建开始按钮和退出按钮,最后显示界面。
# 开始翻译按钮
Button(root, text='开始翻译', font=('隶书', 15), command=data_text).grid(row=3, column=0)
# 退出按钮
Button(root, text='退出程序', font=('隶书', 15), command=root.quit).grid(row=3, column=1)
root.mainloop()
这样一个简易的可视化界面就创建好了。
爬虫程序
目标网址:
https://fanyi.youdao.com/
进入网页后,鼠标右键点击检查
或者按键盘上的F12
进入浏览器的开发者工具,点击Network
,因为数据是动态加载的,所以需要进入XHR
更容易筛选数据包。
接着在文本框中输入你想要翻译内容,然后点击翻译。这时浏览器的开发者工具就抓取了一条数据包,点开数据包发现是一条发送POST
请求的链接。
我们以前说过,POST
需要查看他所携带的参数的,所以我们往下拉,查看数据包所携带的参数。
在这些参数中,比较重要的是:i
、from
、to
、salt
、sign
、lts
、bv
。i
代表的是翻译的内容,from
和to
代表的是翻译模式,salt
和lts
不难看出是时间戳,sign
和bv
是经过加密的参数,这里我们先对sign
和bv
进行解密。
i: 中国 # 翻译的内容
from: zh-CHS # 中译英的中
to: en # 中译英的英
smartresult: dict
client: fanyideskweb
salt: 16200384705444 # 十四位的时间戳
sign: cb74e00c51e313c958423ea4d6487036 # 加密参数
lts: 1620038470544 # 十三位的时间戳
bv: 3d91b10fc349bc3307882f133fbc312a # 加密参数
doctype: json
version: 2.1
keyfrom: fanyi.web
action: FY_BY_CLICKBUTTION
复制sign
,按键盘上的CTRL+shift+f
进行全局搜索,找到了一条js文件
:
进入文件,然后点击左下角的中括号进行格式化:
接着在文件内按键盘上的CTRL+f进行搜索,结果有十一个。我们往下找到第四个是 链接提交 data 表单,这个是已经加密好的了,如果不知道是不是加密的可以打上断点试试。我们需要继续往下查找,找他们是如何生成的。
找到第五个的时候在右边打上断点:
然后再次翻译内容,程序就在这停下来了,我们发现ts
、bv
、salt
、sign
都是在这里生成的。
用鼠标放在navigator.appVersion
中就可以看到,bv
就是对浏览器的ua进行 MD5 加密;sign
就是两串字符串加入要翻译的内容e
、十四位的时间戳i
进行MD5 加密:
至此,我们就找到了bv和sign是如何生成的。这里我们直接用hashlib
进行解密:
md5_text = "fanyideskweb" + e + i + "Tbh5E8=q6U3EXe+&L[4c@"
# 需要带encode进行编码解码
signs = hashlib.md5(md5_text.encode(encoding='utf-8')).hexdigest()
ua = "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36"
ts = hashlib.md5(ua.encode(encoding='utf-8')).hexdigest()
在data_text函数中接收解密参数,传入请求链接,连接相应按钮。
key = entry.get()
from_to = var.get()
times = time.time()
salt = str(round(times * 10000))
lts = str(round(times * 1000))
sign_ = sign(key, salt)
data = {
'i': key, # 连接输入框
# 连接模式按钮;因为按钮传入的参数有两个,所以需要进行切割
'to': str(from_to.split(',')[0]),
'from': str(from_to.split(',')[1]),
'smartresult': 'dict',
'client': 'fanyideskweb',
'salt': salt,
'sign': sign_,
'lts': lts,
'bv': bv(),
'doctype': 'json',
'version': 2.1,
'keyfrom': 'fanyi.web',
'action': 'FY_BY_CLICKBUTTION'
}
url = 'https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
# 这里需要加入headers
resposen = requests.post(url=url, data=data, headers=headers)
json_data = json.loads(resposen.text)
tgt = jsonpath.jsonpath(json_data, '$..tgt')[0]
text.insert(END, tgt) # 连接文本框
text.see(END)
text.update()