前言
》模拟有道词典,制作翻译程序
》有道翻译网址:http://fanyi.youdao.com/
直接上代码:👇
import requests
import hashlib
import time
import random
import json
from urllib.parse import quote
url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
headers = {
"Accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Connection": "keep-alive",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Cookie": "OUTFOX_SEARCH_USER_ID=-198948014@10.169.0.84; OUTFOX_SEARCH_USER_ID_NCOO=1678156251.6498268; _ga=GA1.2.109926435.1582269589; UM_distinctid=170a4e98abc891-0b24cc8bee43ca-5e4f281b-144000-170a4e98abd72b; JSESSIONID=aaaPbNnhvgdpJe62qgofx; ___rl__test__cookies=1586153715407",
"Host": "fanyi.youdao.com",
"Origin": "http://fanyi.youdao.com",
"Referer": "http://fanyi.youdao.com/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36",
"X-Requested-With": "XMLHttpRequest",
}
data = {
"from": "AUTO",
"to": "AUTO",
"smartresult": "dict",
"client": "fanyideskweb",
"doctype": "json",
"version": "2.1",
"keyfrom": "fanyi.web",
"action": "FY_BY_REALTlME",
}
def md5_b(str): # md5加密
hash = hashlib.md5()
hash.update(str.encode("utf-8"))
return hash.hexdigest()
def get_data_params(t_str):
user_agent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36"
e = t_str
t = md5_b(user_agent)
r = str(int(time.time()*1000))
i = r+str(random.randint(0, 10))
data['i'] = e
data["ts"] = r
data["bv"] = t
data["salt"] = i
data["sign"] = md5_b("fanyideskweb" + e + i + "Nw(nmmbP%A-r6U3EUn]Aj")
return data
def main():
while True:
print("")
print("-"*50)
print('***模拟有道翻译。输入"exit()"即退出程序***')
print("")
fanyi = input("》请输入需要翻译的文字: ")
if fanyi == "exit()":
print("即将退出...")
break
print("")
response = requests.post(url=url, headers=headers, data=get_data_params(fanyi))
# print(response.text) # 打印结果测试
ret = json.loads(response.text)
# ret中的数据有翻译的结果和词典的结果
# ①输出: 翻译的结果
if ret["errorCode"] == 0: # 若ret中的"errorCode"值为0,则表示可以翻译该词,否则翻译不了,执行后面的else结果
print("》翻译结果为:" + ret["translateResult"][0][0]["tgt"])
else:
print("抱歉,翻译不了该词。")
# ②输出: 词典的结果
# 使用异常捕获,若需要翻译的内容为句子,则不会输出词典的结果
try:
d_ret = ret["smartResult"]["entries"]
print("")
fanyi_list = [x.strip() for x in d_ret if x.strip()]
print("》词典匹配结果({}个):".format(len(fanyi_list)))
for item in fanyi_list:
print("\t", item)
fanyi_encode = quote(fanyi) # 对需要翻译的词汇进行编码处理,转化为url的编码格式,并编写到下面的链接中(需要导包)
print("")
print("【详细链接:"+"http://dict.youdao.com/w/{}".format(fanyi_encode) + "】")
except:
pass
if __name__ == '__main__':
main()
time.sleep(1) # 延时1秒
解析
》有道翻译的实现效果,参考自:https://www.cnblogs.com/CYHISTW/p/12642367.html
1️⃣其中,发现需要的数据(含有 ts、bv、salt、sign 四个参数)都在这个构造函数中。对该构造函数进行分析,只需要获取 e、t、r、i 的值即可破解该构造函数:👇
- e:需要翻译的单词;
- navigator.appVersion:请求头user-agent信息;
- t:加密请求头user-agent信息;
- r:js获取到的时间戳;
- i:时间戳 + 一位随机数字【10 *Math.random():获取0-10的随机数;parseInt(xxx,10):将xxx数字转化为10进制数】
2️⃣将上面的数据封装成 python代码,构造成 data数据:
def get_data_params(t_str):
user_agent = "Mozilla/5.0 (Windows NT 10.0; WOW64) ......"
e = t_str
t = md5_b(user_agent)
r = str(int(time.time()*1000))
i = r+str(random.randint(0, 10))
data['i'] = e
data["ts"] = r
data["bv"] = t
data["salt"] = i
data["sign"] = md5_b("fanyideskweb" + e + i + "Nw(nmmbP%A-r6U3EUn]Aj")
return data
3️⃣有关Python3中的md5加密,可参考该文章:https://blog.csdn.net/qq_38607035/article/details/82591931
》在main()函数中实现主要方法
- 调用
requests
的post()
方法,传递相关的参数(url,请求头,需要翻译的内容) - 打印调用后的值,发现翻译的内容都在该值中,但要想提取翻译的内容,需要进行数据格式的转化
- 用
json
模块的loads()
方法,将请求到的response.text
(返回的是字符串格式),转化成字典的格式【可查看最后面的补充部分】。最终提取其中的 “翻译的结果” 和 “词典的结果” - 其中需要编写较多代码的是“词典的结果”,它的返回结果类似:"
['', 'you\r\n', 'thou\r\n', 'thee\r\n']
"。因此需要编写额外的代码去除不需要的空白部分(参照自己的另一篇文章:去除列表中的 “空/换行” 字符串)
fanyi_list = [x.strip() for x in d_ret if x.strip()]
- 接着对需要翻译的词汇进行编码处理,转化为
url
的编码格式,并编写到url链接
中(需要导包:from urllib.parse import quote
,调用quote()
方法)【详细可查看自己的另一篇文章:python3 的url编码】 - 然后,将代码封装在
while True
中,当输入exit()
时,break
退出程序 - 最后,安装
pyinstaller
模块将python文件进行打包成exe
格式。
pip install pyinstaller # 安装模块
# 新建一个文件夹,将 fanyi.py 文件移动到该文件夹内。
# 按住shift+鼠标右键,选择“打开powershell窗口”,在窗口中输入以下命令:
pyinstaller -F ./fanyi.py # 将py文件打包成一个exe文件,打包的结果会存放在dist的目录下
# 也可以下载ico格式的图标,将图标也打包到程序中
pyinstaller -F -i ./xxx.ico ./fanyi.py
补充:
关于load()和dump()的区别:
- loads: 是将 string 转换为 dict
- dumps: 是将 dict 转换为 string
- load: 是将 json格式字符串转化为 dict,读取文件
- dump: 是将 dict类型转换为 json格式字符串,存入文件