在网上看了好几个用python调用网易有道翻译的教学贴,可惜对我等小白来说,放眼望去都是不懂的坑,感觉python还是需要实践来学习,就先把找到的填平这些坑的办法记录一下,可能涉及转载。
1. 各参数的获得
各参数的获得,是这个项目的关键点。
- 使用chrome-检查-network,然后在网页中输入需要翻译的内容,点击翻译,在检查中找到新生成的tranlate开头的name,进入

- 进入translate以后,点击headers,会发现真实的request url以及form data,这时会发现form data中的salt、sign、lts、bv这四个参数都是长串无规则字符串。多生成几次translate以后,发现bv字符串是固定的,lts13位,salt比lts多一位无规则数字,sign一直变化。推测应该是在js中用了加密
- 点击network-Initiator,发现全部指向同一个js
有道翻译的实践 - 点击进入 fanyi.min.js:1,点击pretty print(页面下方的{} 也行),直接进入fanyi.min.js:1所在行数,同时也把js代码格式化了。
- 通过breakpoint的形式寻找,链接就是真实的request url,在XHR/fetch Breakpoint中填入。再次在网页上点击翻译,检查中页面会自动停下。
有道翻译的实践 - 点击上图中右侧的call stack,寻找t.translate,会看到salt,ts,bv,sign生成之后的数据,点击generatesSaltSign(n)回溯过去。最终找到。
有道翻译的实践
2. 时间戳
python中时间戳是10位,但是在java中是13位,需要用到时间戳的时候代码如下:
import time
t = time.time() # 生成一个以秒为单位的10位时间戳,float类型的浮点数
t =int(t) # 对t取整,不要小数
print(t)
# jave中需要13位时间戳,可以把秒转换为毫秒
millis = int(round(time.time()* 1000)) # round()是四省五入,其实不要round也没事
print(millis)
# 13位时间戳转换成现在时间
now = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(millis/1000))
print(now)
3. salt的构成
salt的值是i,而i = r + parseInt(10* Math.random(), 10)。
Math.random()是js中的函数,随机生成[0,1)随机数,而10*Math.random() 就是生成[0,10)中的一个随机数。
parseInt(string, radix), 其中string就是字符串,radix表示进制,可选从2到32,譬如10就是十进制,16就是十六进制,2就是二进制。
4. sign的构成
sign的值是 n.md5(“fanyideskweb” + e + i +‘Y2FYu%TNSbMCxc3t2u^XT’),(最后一个值可能每人都不一样),i是salt,e是输入的值。关于e到底是怎么来的,我觉得应该从function(e)引出的,说明e是function的输入变量。
5. bv的构成
bv的值是n.md5(navigator.appVersion),是固定的,实际就是浏览器版本。appVersion可以通过鼠标悬停的方式获得
6. 最终的代码
最终的代码基本复制了大神的,确实写的简洁有力,记录一下。
# 向有道词典发送数据并获得翻译结果
import requests
import json
import time
import hashlib
import random
class YoudaoCrawl(object):
def __init__(self, word):
self.url = " http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"
self.headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
"Cookie": '[email protected]; JSESSIONID=aaa6iBvh3WJaGgn8RPGBx; OUTFOX_SEARCH_USER_ID_NCOO=1574258758.1928287; ___rl__test__cookies=1610087834528',
"Referer": "http://fanyi.youdao.com/"
}
self.word = word
self.post_body = {}
def generator_post_body(self):
ts = str(int(time.time()*1000)) # ts是string型数据
num = int(random.random() * 10)
salt = ts + str(num) # salt是string型数据
str_sign = 'fanyideskweb' + self.word + salt + 'Y2FYu%TNSbMCxc3t2u^XT'
md5 = hashlib.md5() # md5加密
md5.update(str_sign.encode('utf-8'))
sign = md5.hexdigest() # sign是string型数据
appVersion = '5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome' \
'/92.0.4515.159 Safari/537.36'
m_bv = hashlib.md5()
m_bv.update(appVersion.encode('utf-8'))
bv = m_bv.hexdigest() # bv是string型数据
self.post_body = {
"i": self.word,
"from": "AUTO",
"to": "AUTO",
"smartresult": "dict",
"client": "fanyideskweb",
"salt": salt,
"sign": sign,
"lts": ts,
"bv": bv,
"doctype": "json",
"version": "2.1",
"keyfrom": "fanyi.web",
"action": "FY_BY_REALTIME",
}
def send_request(self):
response =requests.post(self.url, headers=self.headers, data=self.post_body)
return response.json()
def parser_response(self, ret_dict):
"""从字典中提取翻译结果"""
ret = ret_dict['translateResult'][0][0]['tgt']
print("翻译的文本: {} , 翻译的结果 :{}".format(self.word, ret))
def run(self):
"""运行函数"""
self.generator_post_body()
ret_dict = self.send_request() # ???函数也能用self/???
self.parser_response(ret_dict)
if __name__ == "__main__" :
data = input("请输入需要翻译的内容: ")
spider = YoudaoCrawl(data)
spider.run()
时间戳参考链接
打点参考
代码参考