python3爬虫与GUI:基于有道词典的词典小工具

最近看到了一篇文章,一个基于有道的词典小工具,心血来潮,想着自己来写一个试试看。

下面我将用python完成接口的对接(即进行抓包),并且用pyQT5实现对应的GUI界面。接下来就是事件机制的编写了,这样任务就完成了。

分析

在分析的过程中需要分析网页中的JS代码,因为有道现在使用加密算法来进行翻译结果的加密了。下面一一进行简单的说明。

首先用Chrome浏览器打开有道在线翻译页面,随便输入一个中文,会自动检测翻译成英文。(在我们已经都知道有道现在是加密的情况下我就不废话太多了,下面直接挑重点的说。)打开其自带的开发者工具查看到相关的包信息:

如果多翻译试几次翻译会发现上图所指的两个参数是持续变化的,还有一个i是输入的词,这个是在正常不过的,没什么疑义。

找到相应的JS整体代码

为了知道加密算法的过程以及整个流程是怎么一回事,找到网页的整体JS代码是唯一的选择。

先借助火狐浏览器分析翻译的接口,可快速的发现JS代码的所在处:

知道了JS文件的所在处,我们可在Chrome浏览器下找到这个地址:

新建标签页打开:

发现这是一个混淆的JS代码,需要进行格式化才可知道其庐山真面目!
推荐两个反混淆的网站:
http://tool.oschina.net/codeformat/jshttp://www.bm8.com.cn/jsConfusion/

将混淆的代码复制粘贴在以上任意的一个网站,选择点击格式化之后即可得最终正解代码,之后为了查找关键词,我将这些代码编入一个文件中(Mac直接用文本编辑创建新文件即可。):

格式化之后的JS代码一览。

之后查找关键词salt,找到对应上方的所指的参数位置。其中的乱码不用管,对分析代码没什么影响。

分析内容过程

分析了一下之后,在Chrome浏览器中运行一下相关的代码,然后进入关于时间戳转换的网站进行简单的转换,会发现这是一个有关时间戳的随机生成的一串数字:

结合上下文(即salt关键词的上下一点范围即可),发现有md5算法的字样出现了。

代码中关键的相关的内容。之后我们会用python来模拟这些代码来进行相关参数的输出。

Chrome试着运行一下。

将运行之后的数字填入转换得出结果。

在得知了两个随着翻译变化的关键词之一salt的生成原理之后,再来看看最后一个突破点,即找到关键词sign的生成原理,在这之后利用python模仿运行生成再代人相关的参数即可完成需要的翻译结果的输出。

其实往上看一点点就能发现诀窍了:

结合md5算法以及必要的几个参数即可得出sign的生成值。

这样一来思路就都清晰明了了,仅仅需要代码的实现了。

代码

以下代码已经套上了结合pyQt5开发出来了GUI的整体代码。

关于pyQt5不清楚可参考我之前的相关博文,或者是利用好搜索引擎。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
"""
函数目标:
基于有道的GUI搜索小工具
编写时间:
2018-5-08
"""
import time
import requests
import hashlib
import random
import json
import sys
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtWidgets import (QPushButton, QWidget, QLabel, QLineEdit, QTextEdit, QGridLayout, QApplication,
QComboBox)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def save_translateResult(self, word):
"""
本函数用于翻译结果的返回。
"""
r = str(int(time.time() * 1000 + random.randint(1, 10))) # 模仿JS代码的仿写
S = 'fanyideskweb'
n = word
D = "ebSeFb%=XZ%T[KZ)c(sy!" # 在完整的JS代码中可找到
o = hashlib.md5((S + n + str(r) + D).encode('utf-8')).hexdigest()
data = {
'i': word,
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': S,
'salt': r,
'sign': o,
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTIME',
'typoResult': 'false'
}
url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
# 在代理中需要加入cookies信息,否则会出现代码错误信息的返回
header = {
'Cookie': XXXXXXXXXXXXXXXXXXXntes_nnid=25aff2b1480f17471ca1585f6f2f4293,15120241366',
'Referer': 'http://fanyi.youdao.com/',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36'
}
response = requests.post(url=url, headers=header, data=data)
response.encoding = 'utf-8'
translateResult = json.loads(response.text)["translateResult"][0][0]['tgt']
return translateResult
def take_test(self, word):
"""
本函数用于输出测试。
"""
try:
return self.save_translateResult(word)
except AttributeError:
return "输入点有误/输出出现问题!!"
def initUI(self):
# 组件添加
combo = QComboBox(self)
combo.addItem('有道词典')
label = QLabel("请输入:")
line = QLineEdit()
button_1 = QPushButton('开始翻译', self)
button_2 = QPushButton('退出', self)
button_3 = QPushButton('清空', self)
result = QTextEdit()
# 布局设置
grip = QGridLayout()
grip.setSpacing(4)
grip.addWidget(label, 1, 0)
grip.addWidget(line, 2, 0)
grip.addWidget(button_3, 2, 1)
grip.addWidget(button_1, 3, 0)
grip.addWidget(button_2, 3, 1)
grip.addWidget(result, 4, 0)
self.setLayout(grip)
combo.move(500, 0)
# 基于Macbook设置基本的快捷键以及推出程序的信号槽
button_1.setShortcut('return')
button_2.setShortcut('command+q')
button_2.clicked.connect(QCoreApplication.instance().quit)
button_3.setShortcut('esc')
def translate():
"""
本函数用于返回翻译按钮之后的结果输出!
"""
result.setText(self.take_test(line.text()))
button_1.clicked.connect(translate)
def clear():
"""
本函数用于输入输出框的清空!
"""
line.setText("")
result.setText("")
button_3.clicked.connect(clear)
# 设置窗口大小
self.setGeometry(500, 150, 600, 500)
self.setWindowTitle("有道翻译小工具")
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

上面的cookies值是必须要的!否则会出现错误,当然,在上面的代码我的cookies数值我进行了隐藏更改,如果需要测试运行,可加上自己浏览器上有道在线翻译的cookies

运行演示:

最后

  • 代码中的模块可参考:

1. JavaScript parseInt() 函数:http://www.w3school.com.cn/js/jsref_parseInt.asp

2. time.time():返回当前时间的时间戳。:http://qinxuye.me/article/details-about-time-module-in-python/

3. random.randint:https://www.cnblogs.com/yd1227/archive/2011/03/18/1988015.html

4. hashlib:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319556588648dd1fb0047a34d0c945ee33e8f4c90cc000

其他的自行查找。特别是pyQt5这个库,可查看我之前写的文章作为参考:https://liujunjie11.github.io/2018/04/28/python3爬虫与GUI:一个简易的搜索实用小工具/#more

  • 参考:

1. http://study.163.com/course/courseLearn.htm?courseId=1004108008#/learn/video?lessonId=1047998193&courseId=1004108008

2. https://cuiqingcai.com/5024.html

3. https://blog.csdn.net/karmacode/article/details/79145728

4. https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319556588648dd1fb0047a34d0c945ee33e8f4c90cc000

5. http://qinxuye.me/article/details-about-time-module-in-python/

6. https://www.cnblogs.com/yd1227/archive/2011/03/18/1988015.html

关于python的加密算法以及加密原理:

1. https://www.oudahe.com/p/python/z545/

2. https://www.oudahe.com/p/python/z545/

最后不懂的模块知识可利用好搜索引擎。

实际上也参考了我自己的文章:

https://liujunjie11.github.io/2018/04/28/python3爬虫与GUI:一个简易的搜索实用小工具/#more

以及pyqt5的官网教程:

https://maicss.gitbooks.io/pyqt5/content/事件和信号.html

  • 关于将python文件打包生成app的工具库:

py2app:.py –> .dmg

py2exe:.py –> .exe

---------------本文终---------------

文章作者:刘俊

最后更新:2019年01月02日 - 14:01

许可协议: 转载请保留原文链接及作者。