js解密入门--有道翻译

文章目录

      • 一、测试
      • 二、分析
        • 分析post的Form Data部分
      • 三、代码实现
      • 四、思路总结
      • 声明

有道翻译网站 http://fanyi.youdao.com/

一、测试

首先拿到这个网站, 按照正常的流程, 带上请求的header和Form Data部分, 但是每次response都是errorcode50

二、分析

打开调试窗口
js解密入门--有道翻译_第1张图片

在左边翻译框输入一个测试字符串,接下来注意这个请求是由那个js发起的

js解密入门--有道翻译_第2张图片
发现这个js文件fanyi.min.js, 注意min.js这是一个压缩版js文件

右键这个js文件 - Reveal in Sources panel, 会自动跳到Source栏 如下图
js解密入门--有道翻译_第3张图片

点击箭头位置{}, 将js文件格式化显示出来,拿到源码
js解密入门--有道翻译_第4张图片

分析post的Form Data部分

每次在翻译框输入一个内容, XHR一栏里都会异步得到一个返回结果,查看这个请求的response里可以得到我们的翻译结果

找到这条请求的header部分,发现每次请求的Form Data的这几个参数都是变化的,js加密也往往是在这个地对传输的数据进行加密

  • salt
  • sign
  • ts
  • bv
    js解密入门--有道翻译_第5张图片

尝试在刚才的fanyi.min.js文件中搜索这几个参数

define("newweb/common/service", ["./utils", "./md5", "./jquery-1.7"], function(e, t) {
    var n = e("./jquery-1.7");
    e("./utils");
    e("./md5");
    var r = function(e) {
        var t = n.md5(navigator.appVersion)
          , r = "" + (new Date).getTime()
          , i = r + parseInt(10 * Math.random(), 10);
        return {
            ts: r,
            bv: t,
            salt: i,
            sign: n.md5("fanyideskweb" + e + i + "n%A-rKaT5fb[Gy?;N5@Tj")
        }
    };

查看和测试已经大概知道这几个参数的作用了:

ts: 表示当前的时间戳的字符串, 注意js的时间戳和python的时间的有区别, js的时间戳是ms级的, 所以每次用python获得的时间戳都要*1000

bv: 是一个经过md5加密的navigator.appVersion, 在控制台的调试窗口输入navigator.appVersion,发现和User-agent几乎相同, 但是不同

salt: 是字符串ts加上一个随机的范围为[0-9]的整数拼接成的字符串

sign: 也是一个经过md5加密的字符串, e 表示翻译框内输入的内容

我们已经差不多知道原理了, 我们在翻译框内每次输入的内容, 被经过简单js加密发送到服务端验证, 才能得到我们想要的内容

三、代码实现

首先把上面比较重要的几个参数通过python代码实现
因为js学的比较浅,转变为python代码调试了很多次.

    # 得到当前时间戳
    # r = "" + (new Date).getTime()
    ts = r = str(int(round(time.time(), 3) * 1000))
    print(ts)

    # 时间戳和0-10按照字符串拼接
    # salt = i = r + parseInt(10 * Math.random(), 10)
    i = r + str(random.randint(0, 9))
    salt = int(i)
    print(salt)

    # bv = t = n.md5(navigator.appVersion)
    # app_version = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36"
    app_version = "5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36"
    bv = hashlib.md5(app_version.encode(encoding="utf-8")).hexdigest()
    print(bv)

    # 得到sign值
    # sign: n.md5("fanyideskweb" + e + i + "n%A-rKaT5fb[Gy?;N5@Tj")
    sign = hashlib.md5(("fanyideskweb" + "翻译" + i + "n%A-rKaT5fb[Gy?;N5@Tj").encode(encoding="utf-8")).hexdigest()
    print(sign)

最后拼接data和header部分,然后通过requests.post方法拿到返回值,得到的想要的结果

import time
import random
import hashlib
import requests

class YouDao:
    def __init__(self, url):
        self.url = url

    def get_data(self, content):
        # 得到当前时间戳
        # r = "" + (new Date).getTime()
        ts = r = str(int(round(time.time(), 3) * 1000))
        print(ts)

        # 时间戳和0-10按照字符串拼接
        # salt = i = r + parseInt(10 * Math.random(), 10)
        i = r + str(random.randint(0, 9))
        salt = int(i)
        print(salt)

        # bv = t = n.md5(navigator.appVersion)
        # app_version = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36"
        app_version = "5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36"
        bv = hashlib.md5(app_version.encode(encoding="utf-8")).hexdigest()
        print(bv)

        # 得到sign值
        # sign: n.md5("fanyideskweb" + e + i + "n%A-rKaT5fb[Gy?;N5@Tj")
        sign = hashlib.md5(("fanyideskweb" + content + i + "n%A-rKaT5fb[Gy?;N5@Tj").encode(encoding="utf-8")).hexdigest()
        print(sign)

        data = {
            'i': content,
            'from': "AUTO",
            'to': "AUTO",
            'smartresult': "dict",
            'client': "fanyideskweb",
            'salt': salt,
            'sign': sign,
            'ts': ts,
            'bv': bv,
            'doctype': "json",
            'version': "2.1",
            'keyfrom': "fanyi.web",
            'action': "FY_BY_REALTlME",
            'cache-control': "no-cache",
            'typoResult': 'false'
            }
        headers = {
            "Cookie": 'OUTFOX_SEARCH_USER_ID_NCOO=152157970.25320017; OUTFOX_SEARCH_USER_ID="[email protected]"; _ga=GA1.2.2012357562.1553937054; _ntes_nnid=6497242c22b4e2ef0d2f403b1c6b7bf2,1560146318693; JSESSIONID=aaarX_cgU_By9_aKjPkXw; ___rl__test__cookies={}'.format(ts),
            'Accept': "application/json, text/javascript, */*; q=0.01",
            'Origin': "http://fanyi.youdao.com",
            'User-Agent': "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36",
            'Referer': "http://fanyi.youdao.com/",
            'X-Requested-With': "XMLHttpRequest"
        }
        return data, headers

    def translate(self, content):
        data, headers = self.get_data(content)
        response = requests.post(self.url, data=data, headers=headers)
        print(response.text)


if __name__ == "__main__":
    url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"
    instance = YouDao(url)
    instance.translate("good")

四、思路总结

  • 先找对网站数据的传输方式,以及网站会对哪些数据进行加密
  • 通过调试js找到这些数据的加密规则, 这一段通常是最痛苦的。
  • python模拟js中加密的实现,然后调试拿到想要的结果为止

声明

该文章主要提供交流学习使用,请勿利用其进行不当行为。
爬虫刚入门,有不对的地方欢迎指正。

你可能感兴趣的:(spider)