likes
comments
collection
share

python 爬虫进阶-js逆向

作者站长头像
站长
· 阅读数 12

前言

我们需要了解一些 Python基本语法、爬虫库,html的查询,数据的处理与保存

Python

www.runoob.com/python/pyth…

  • 基础知识 语法与特性

requests

www.cnblogs.com/lanyinhao/p…

  • 使用Apache2 licensed 许可证的HTTP库,代替了urllib 支持HTTP连接保持和连接池,支持使用cookie保持会话,支持文件上传,支持自动响应内容的编码,支持国际化的URL和POST数据自动编码。

Beautiful Soup

cuiqingcai.com/1319.html

  • 提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。

爬虫与js逆向

百度翻译

百度翻译爬虫,通过百度翻译接口查询

分析

  • 打开百度翻译

url : fanyi.baidu.com/#en/zh/

分析流程

  1. 将浏览器切换至手机端,这样查看请求的参数可能会较少,点击下图中的按钮:

python 爬虫进阶-js逆向

  1. 查看请求接口

python 爬虫进阶-js逆向 python 爬虫进阶-js逆向 python 爬虫进阶-js逆向

  1. 查看请求参数是否有变化
  • 图一:

python 爬虫进阶-js逆向

  • 图二:

python 爬虫进阶-js逆向

经过分析,我们发现这里有两个参数发生变化,经过推断,这里的参数可能是使用js生成的,所以我们这里要对接口进行分析,破解,得到这里的值

分析结果

--分析目标-------分析结果-------------------
请求URL分析fanyi.baidu.com/v2transapi
请求方式分析POST
请求参数分析参看请求参数分析
请求头分析参看请求头分析
请求参数分析
参数KEY分析结果
query翻译单词(变化)
fromen(固定值不变)
tozh(固定值不变)
token900aa0a84929561d52bbee8c9222c0aa(经过请求测试,我们发现可以为固定值)
sign54706.276099

JS 逆向流程

注意: 在js逆向中,不是你要精通js才可以js逆向,你要懂一点js就可以做逆向,重要的逆向思维,对问题的思考方式

chrome 调试技巧

  1. search 打开查询面板
  2. 查询面板可以通过关键字查找所有出现关键字地方的代码
  3. 点击跟踪代码并且可以把代码格式化
  4. 对格式化的代码进行设置断点
  5. 鼠标光标移动到上面可以查看当前运行代码变量值,函数原始代码地方等等
JS 逆向流程
  1. 通过关键词切入到代码中,切入到发送请求的代码行,通过请求的url中提取关键字
  2. 在发送请求的代码添加断点,并且触发发送请求,确认寻找的代码是否正确
  3. 往上逆向,寻找目标参数以及生成逻辑
  4. 利用js2py模拟执行生成逻辑获取想要的内容

根据逆向流程查找我们所需的js代码

  1. 搜索关键字

python 爬虫进阶-js逆向

  1. 跟进代码,分析AJAX请求

python 爬虫进阶-js逆向

  1. 查找我们需要的值

python 爬虫进阶-js逆向

  • 准确的找到我们需要的值

python 爬虫进阶-js逆向

  • 复制我们需要的js代码

  • 代码如下:

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)
    }

编写爬虫代码

# !/usr/bin/python3
# -*- coding: utf-8 -*-

import js2py
import requests

js_ctx = js2py.EvalJs()

# 0:英译中 1:中译英
t_mode = 0


class Translation(object):

    def __init__(self, query):
        # 初始化
        self.url = "https://fanyi.baidu.com/v2transapi?from={0}&to={1}"
        self.query = query
        self.headers = {
            "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1",
            "Referer": "https://fanyi.baidu.com/",
            "Cookie": "BAIDUID=714BFAAF02DA927F583935C7A354949A:FG=1; BIDUPSID=714BFAAF02DA927F583935C7A354949A; PSTM=1553390486; delPer=0; PSINO=5; H_PS_PSSID=28742_1463_21125_18559_28723_28557_28697_28585_28640_28604_28626_22160; locale=zh; from_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; to_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; Hm_lvt_afd111fa62852d1f37001d1f980b6800=1553658863,1553766321,1553769980,1553770442; Hm_lpvt_afd111fa62852d1f37001d1f980b6800=1553770442; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1553766258,1553766321,1553769980,1553770442; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1553770442"
        }

    # js逆向获取sign的值
    def make_sign(self):
        with open("translation.js", "r", encoding="utf-8") as f:
            js_ctx.execute(f.read())

        # 调用js中的函数生成sign
        sign = js_ctx.e(self.query)
        # 将sign加入到data中
        return sign

    def make_data(self, sign):
        data = {
            "query": self.query,
            "token": "6f5c83b84d69ad3633abdf18abcb030d",
            "sign": sign
        }
        return data

    def get_content(self, data):
        if t_mode == 0:
            from_str = "en"
            to_str = "zh"
        else:
            from_str = "zh"
            to_str = "en"

        response = requests.post(
            url=self.url.format(from_str, to_str),
            headers=self.headers,
            data=data
        )
        return response.json()['trans_result']['data'][0]['dst']

    def run(self):
        # 获取sign的值
        sign = self.make_sign()
        # 构建参数
        data = self.make_data(sign)
        # 获取翻译内容
        content = self.get_content(data)
        print(content)


if __name__ == '__main__':
    t_mode = int(input("请输入翻译模式(0:英译中 1:中译英):"))
    query = input("请输入您要翻译的内容:")
    translation = Translation(query)
    translation.run()

注意

  • 此时我们运行代码会报错误,会讲我们缺少 r 的值

解决办法:回到浏览器,我们查找 r 的值,并将生成 r 的值的函数,加入到我们之前创建的 js 文件中,放在 G 函数的上面

python 爬虫进阶-js逆向

  • 生成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
    }
  • 我们重新运行代码,发现又会遇到一个错误,说是缺少 i 的值,所以我们的解决办法还是,继续进行 js 逆向,查找i的值

python 爬虫进阶-js逆向

  • 逆向分析
  1. 我们回到 function a()中,找到需要使用 i值的地方,打上断点

python 爬虫进阶-js逆向

  1. 打上断点之后刷新一下页面,我们再次将鼠标放在 i上,我们会看到一个浮点字符串,此时我们不确定 i 的值是否是变化的,所以我们换一个翻译的单词,刷新页面,再次查看 i 的值,我们发现 i 的值是固定的,所以我们可以在代码中,直接定义一个固定的i 值.

python 爬虫进阶-js逆向

我们在自定义的 js 代码最上面一行写入:

var i = "320305.131321201"

最后

运行代码,成功,完成了一次简单的百度翻译的 js 逆向尝试。

QQ音乐下载

qq音乐下载是怎样的流程

分析流程

  • 打开QQ音乐

url : y.qq.com/

  1. 将浏览器切换至手机端,这样查看请求的参数可能会较少,点击下图中的按钮:

python 爬虫进阶-js逆向

  1. 查看请求接口

python 爬虫进阶-js逆向 python 爬虫进阶-js逆向

  1. 通过单一歌曲的链接查看必须的传递参数 song_mid 继续搜寻可用链接:

python 爬虫进阶-js逆向

根据逆向流程查找我们所需的js代码

  1. 可查看必要参数sign值与data,拼接data,查看参数sign的得出

python 爬虫进阶-js逆向

  1. debug 调试 获取到js的方法与sign值的获取js代码

python 爬虫进阶-js逆向 python 爬虫进阶-js逆向

  1. getSecuritySign内部主要处理数据的js 方法如上 复制至sign.js中保存使用
  2. 该链接获取到的链接拼接为音乐的源

python 爬虫进阶-js逆向

最后拼接音乐源,即可完成下载

参考内容

github.com/Kr1s77/awes…

转载自:https://juejin.cn/post/6956889965481426952
评论
请登录