浅谈Python爬虫(八)【有道词典翻译API】
最近用到了有道的翻译接口。但是发现是有加密的。如下是他的请求参数。
i: 你好// 翻译的文本from: AUTO// 定值to: AUTO// 定值smartresult: dict// 定值client: fanyideskweb// 定值salt: 16194905157194// time + numsign: e44b8c53a99e5d54f03e82da13c95aa5lts: 1619490515719// timebv: 62c1eba97402d4ff4eb261254e974c27doctype: 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:/4/27 10:29import requestsimport hashlibimport timeimport randomclass YDDict(object):"""有道翻译"""@staticmethoddef 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, signdef translate(self, keyword='你好', data_from='AUTO', data_to='AUTO'):"""对keyword进行翻译params: params_from 文本语言params: params_to 翻译成的语言类型"""url = '/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': '/?keyfrom=fanyi-new.logo','Host': '','Origin': '','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中包含结果,自己解析一下OKprint(response.json())if __name__ == '__main__':t = YDDict()t.translate(keyword='中国')
这样可以正常获取到翻译的结果,但是如果请求比较频繁的话,ip会被Ban掉,建议使用代理IP。