浅谈Python爬虫(八)【有道词典翻译API】
最近用到了有道的翻译接口。但是发现是有加密的。如下是他的请求参数。
i: 你好 // 翻译的文本
from: AUTO // 定值
to: AUTO // 定值
smartresult: dict // 定值
client: fanyideskweb // 定值
salt: 16194905157194 // time + num
sign: e44b8c53a99e5d54f03e82da13c95aa5
lts: 1619490515719 // time
bv: 62c1eba97402d4ff4eb261254e974c27
doctype: json // 定值
version: 2.1 // 定值
keyfrom: fanyi.web // 定值
action: FY_BY_REALTlME // 定值
分析上面的参数列表,我们发现变化的参数只有 i(文本)、salt(时间戳+随机数)、lts(时间戳)、sign(未知)、bv(未知)。
也就是说,只需要判断出sign和bv就可以了。
我们找一下JS代码。在请求那里。点击Initiator,跳转到调用JS的顺序。发现全是同一个JS代码。
点进去,然后点击左下角的花括号{}可以对代码进行格式化处理。
随后,我们采用最简单粗暴的办法 ---- 直接搜索参数。。。。
这里,我们搜索sign,然后在代码的8386行可以看到返回这个参数的代码。我们发现他是对一个字符串进行md5加密后得到的密文。
“fanyideskweb” + e + i + “…”
往上面看一看,图中的8381行有 i 的定义。即
i = r + 随机数
再往上看,图中的8380有 r 的定义。即
r = 时间戳
也就是说
i = 时间戳 + 随机数
那么还差 e 了。代码中可以看到,e是传进来的参数,不好分析。那么我们直接打断点调试一下。
。
在这段代码的最后一行打断点(点一下就好),然后重新点击翻译按钮,可以看到如下
搜嘎。原来 e 就是我们输入的文本。这样,sign就解决了
sign = md5( “fanyideskweb” + 文本 + 时间戳 + 随机数 + “…” )
图中还可以看出。bv 就是 t。而 t 是对一个参数(navigator.appVersion)进行md5加密的结果,我们把鼠标放到参数上,可以看到它其实就是UA
这样所有的参数都解决了。接下来就是python代码实现了。全部代码如下
# -*- coding: utf-8 -*-
# Author: 玛卡巴卡
# Date: 2021/4/27 10:29
import requests
import hashlib
import time
import random
class YDDict(object):
"""有道翻译"""
@staticmethod
def get_data(keyword):
"""获取到其余的加密参数"""
md = hashlib.md5()
t = str(int(time.time() * 1000))
i = t + str(random.randrange(10))
md.update('fanyideskweb{}{}Tbh5E8=q6U3EXe+&L[4c@'.format(keyword, i).encode('utf8'))
sign = md.hexdigest()
return t, i, sign
def translate(self, keyword='你好', data_from='AUTO', data_to='AUTO'):
"""
对keyword进行翻译
params: params_from 文本语言
params: params_to 翻译成的语言类型
"""
url = 'https://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36',
'Referer': 'https://fanyi.youdao.com/?keyfrom=fanyi-new.logo',
'Host': 'fanyi.youdao.com',
'Origin': 'https://fanyi.youdao.com',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
}
t, i, sign = self.get_data(keyword)
data = {
"i": keyword,
"from": data_from,
"to": data_to,
"smartresult": "dict",
"client": "fanyideskweb",
"salt": i,
"sign": sign,
"lts": t,
# 这里bv是对UA加密得到的,所以也写成了定值
"bv": "62c1eba97402d4ff4eb261254e974c27",
"doctype": "json",
"version": "2.1",
"keyfrom": "fanyi.web",
"action": "FY_BY_REALTlME",
}
response = requests.post(url, headers=headers, data=data)
# json中包含结果,自己解析一下OK
print(response.json())
if __name__ == '__main__':
t = YDDict()
t.translate(keyword='中国')
这样可以正常获取到翻译的结果,但是如果请求比较频繁的话,ip会被Ban掉,建议使用代理IP。