百度翻译爬虫-使用execjs库逆向解析百度翻译

本文目标破解百度翻译接口,抓取翻译结果数据
python3安装execjs方法:pip install pyexecjs

  • 检查页面
    使用Chrome浏览器打开百度翻译,观察界面。
    右键查看源代码,发现密密麻麻全是看不懂JS代码,初步判定为是异步加载页面。
  • 初步测试
    打开开发者工具,进行抓包。
    随意输入中文测试,结果如下图:
    百度翻译爬虫-使用execjs库逆向解析百度翻译_第1张图片
    再次多输入几次单词,进行验证,结果返回类型同上
  • 分析抓到的包
    百度翻译爬虫-使用execjs库逆向解析百度翻译_第2张图片
    经过多个包对比,发现表单数据中的sign随着单词不同它们的值也不同,而token不变,如图
    百度翻译爬虫-使用execjs库逆向解析百度翻译_第3张图片
    由此可以,百度翻译对返回数据进行了加密处理。
  • 寻找sign和token
    百度翻译爬虫-使用execjs库逆向解析百度翻译_第4张图片
    经过搜索sign:找到了包含sign的 js 文件,单机点开查看 js文件。
    可以看到右侧密密麻麻的 js 代码,太过杂乱,所以必须借助与工具。
    安装扩展程序- - > JSON Viewer。具体安装方法不在此赘述了
    点击图中,箭头所指的花括号 { } ,进行Pretty print。得到格式化后的结果,如图所示:
    百度翻译爬虫-使用execjs库逆向解析百度翻译_第5张图片
    此时产生了心得疑问 函数中 sign:y( a ) 表示什么?token: window.common.token 又表示什么。
  • 断点调试
    百度翻译爬虫-使用execjs库逆向解析百度翻译_第6张图片
    调试得知a 的值, 可是 y( a ) 又表示什么。
    百度翻译爬虫-使用execjs库逆向解析百度翻译_第7张图片
    点击f e( r ) ,跳转到真正的函数中
    百度翻译爬虫-使用execjs库逆向解析百度翻译_第8张图片
    发现,此处是一堆位运算,依旧看不懂。所以必须想办法解析这段函数
  • 解析 sign 函数的 js 代码
    将6025-6073行代码复制,并保存到一个 js 文件中,调整好格式,作为备用
  function a(r) {
        if (Array.isArray(r)) {
            for (var o = 0, t = Array(r.length); o < r.length; o++)
                t[o] = r[o];
            return t
        }
        return Array.from(r)
    }
 function n(r, o) {
        for (var t = 0; t < o.length - 2; t += 3) {
            var a = o.charAt(t + 2);
            a = a >= "a" ? a.charCodeAt(0) - 87 : Number(a),
            a = "+" === o.charAt(t + 1) ? r >>> a : r << a,
            r = "+" === o.charAt(t) ? r + a & 4294967295 : r ^ a
        }
        return r
    }
function e(r) {
        var o = r.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);
        if (null === o) {
            var t = r.length;
            t > 30 && (r = "" + r.substr(0, 10) + r.substr(Math.floor(t / 2) - 5, 10) + r.substr(-10, 10))
        } else {
            for (var e = r.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), C = 0, h = e.length, f = []; h > C; C++)
                "" !== e[C] && f.push.apply(f, a(e[C].split(""))),
                C !== h - 1 && f.push(o[C]);
            var g = f.length;
            g > 30 && (r = f.slice(0, 10).join("") + f.slice(Math.floor(g / 2) - 5, Math.floor(g / 2) + 5).join("") + f.slice(-10).join(""))
        }
        var u = void 0
          , l = "" + String.fromCharCode(103) + String.fromCharCode(116) + String.fromCharCode(107);
        u = null !== i ? i : (i = window[l] || "") || "";
        for (var d = u.split("."), m = Number(d[0]) || 0, s = Number(d[1]) || 0, S = [], c = 0, v = 0; v < r.length; v++) {
            var A = r.charCodeAt(v);
            128 > A ? S[c++] = A : (2048 > A ? S[c++] = A >> 6 | 192 : (55296 === (64512 & A) && v + 1 < r.length && 56320 === (64512 & r.charCodeAt(v + 1)) ? (A = 65536 + ((1023 & A) << 10) + (1023 & r.charCodeAt(++v)),
            S[c++] = A >> 18 | 240,
            S[c++] = A >> 12 & 63 | 128) : S[c++] = A >> 12 | 224,
            S[c++] = A >> 6 & 63 | 128),
            S[c++] = 63 & A | 128)
        }
        for (var p = m, F = "" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(97) + ("" + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(54)), D = "" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(51) + ("" + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(98)) + ("" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(102)), b = 0; b < S.length; b++)
            p += S[b],
            p = n(p, F);
        return p = n(p, D),
        p ^= s,
        0 > p && (p = (2147483647 & p) + 2147483648),
        p %= 1e6,
        p.toString() + "." + (p ^ m)
    }
  • 使用execjs库调试 js 文件
import execjs

# 打开baidu.js文件
# 此处我将js保存为baidu.js 并放到python文件目录下
with open('baidu.js','r') as f:
    js = f.read()

#创建js对象
js_obj = execjs.compile(js)

# eval() 函数用来执行一个字符串表达式,并返回表达式的值。执行baidu.js中的e(r)函数
sign = js_obj.eval("e('你好')")
print(sign)

结果报错

execjs._exceptions.ProgramError: TypeError: 'i' 未定义

那么 i 是什么? js 文件看不出来结果,再去网页 js 中调试看看
百度翻译爬虫-使用execjs库逆向解析百度翻译_第9张图片
调试结果,与 i 相关的 l = ‘gtk’ u = ‘320305.131321201’。结果还是一头雾水
那么用次用一下万能的搜索
百度翻译爬虫-使用execjs库逆向解析百度翻译_第10张图片
居然有结果,还出现了gtk字样,赶紧点进去看看
百度翻译爬虫-使用execjs库逆向解析百度翻译_第11张图片
居然是script内的字段,而且是网页源代码中的内容。
至此我们知道了 u 和 l 都是网页源代码里的字段

  • 改变 js 文件中的 l 和 u 的值 再次调试
    注释上 var u = void 0, j 这几行 js 代码 ,自定义 u 的值,代码如下:
    注释
    运行结果为 232427.485594 恰好为上面翻译 你好 sign的结果!
    至此我们破解了 sign 的加密,那么token的值呢?
  • 获取token的值
    我们网页js中调试一下token
    百度翻译爬虫-使用execjs库逆向解析百度翻译_第12张图片
    与上面同样的思路,复制调试出来的值必能搜索
    百度翻译爬虫-使用execjs库逆向解析百度翻译_第13张图片成功找到token的值,并且发现它与sign所需参数 u 的值在同一文件里!
    而网页地址是https://fanyi.baidu.com/?aldtype=16047
    到此处我们以完全拿到百度翻译所需参数,sign和token
  • 构建代码
    完整代码

你可能感兴趣的:(技术,爬虫,python,python,js解析,爬虫)