浅谈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代码。

python有道智云api做翻译软件_python

点进去,然后点击左下角的花括号{}可以对代码进行格式化处理。
随后,我们采用最简单粗暴的办法 ---- 直接搜索参数。。。。
这里,我们搜索sign,然后在代码的8386行可以看到返回这个参数的代码。我们发现他是对一个字符串进行md5加密后得到的密文。

“fanyideskweb” + e + i + “…”

往上面看一看,图中的8381行有 i 的定义。即

i = r + 随机数

再往上看,图中的8380有 r 的定义。即

r = 时间戳

也就是说

i = 时间戳 + 随机数

那么还差 e 了。代码中可以看到,e是传进来的参数,不好分析。那么我们直接打断点调试一下。


python有道智云api做翻译软件_javascript_02


在这段代码的最后一行打断点(点一下就好),然后重新点击翻译按钮,可以看到如下

python有道智云api做翻译软件_时间戳_03


搜嘎。原来 e 就是我们输入的文本。这样,sign就解决了

sign = md5( “fanyideskweb” + 文本 + 时间戳 + 随机数 + “…” )

图中还可以看出。bv 就是 t。而 t 是对一个参数(navigator.appVersion)进行md5加密的结果,我们把鼠标放到参数上,可以看到它其实就是UA

python有道智云api做翻译软件_时间戳_04


这样所有的参数都解决了。接下来就是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。