python机器学习爬虫Python存档

python 爬虫进阶 - js逆向

2021-04-15  本文已影响0人  吾心仔

前言

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

Python

https://www.runoob.com/python/python-tutorial.html

requests

https://www.cnblogs.com/lanyinhao/p/9634742.html

Beautiful Soup

https://cuiqingcai.com/1319.html

爬虫与js逆向

百度翻译

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

分析

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

分析流程

  1. 将浏览器切换至手机端,这样查看请求的参数可能会较少,点击下图中的按钮:
image.pngimage.png
  1. 查看请求接口
image.pngimage.png
image.pngimage.png
image.pngimage.png
  1. 查看请求参数是否有变化
image.pngimage.png image.pngimage.png

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

分析结果

--分析目标--- ----分析结果-------------------
请求URL分析 https://fanyi.baidu.com/v2transapi
请求方式分析 POST
请求参数分析 参看请求参数分析
请求头分析 参看请求头分析
请求参数分析
参数KEY 分析结果
query 翻译单词(变化)
from en(固定值不变)
to zh(固定值不变)
token 900aa0a84929561d52bbee8c9222c0aa(经过请求测试,我们发现可以为固定值)
sign 54706.276099

JS 逆向流程

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

chrome 调试技巧

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

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

  1. 搜索关键字
image.pngimage.png
  1. 跟进代码,分析AJAX请求
image.pngimage.png
  1. 查找我们需要的值
image.pngimage.png image.pngimage.png
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 的值的函数,加入到我们之前创建的 js 文件中,放在 G 函数的上面

image.pngimage.png
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
    }
image.pngimage.png
  1. 我们回到 function a()中,找到需要使用 i值的地方,打上断点
image.pngimage.png
  1. 打上断点之后刷新一下页面,我们再次将鼠标放在 i上,我们会看到一个浮点字符串,此时我们不确定 i 的值是否是变化的,所以我们换一个翻译的单词,刷新页面,再次查看 i 的值,我们发现 i 的值是固定的,所以我们可以在代码中,直接定义一个固定的i 值.
image.pngimage.png

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

var i = "320305.131321201"

最后

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

QQ音乐下载

qq音乐下载是怎样的流程

分析流程

url : https://y.qq.com/

  1. 将浏览器切换至手机端,这样查看请求的参数可能会较少,点击下图中的按钮:
image.pngimage.png
  1. 查看请求接口
image.pngimage.png
image.pngimage.png
  1. 通过单一歌曲的链接查看必须的传递参数 song_mid 继续搜寻可用链接:
image.pngimage.png

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

  1. 可查看必要参数sign值与data,拼接data,查看参数sign的得出
image.pngimage.png
  1. debug 调试 获取到js的方法与sign值的获取js代码
image.pngimage.png
image.pngimage.png
  1. getSecuritySign内部主要处理数据的js 方法如上 复制至sign.js中保存使用
  2. 该链接获取到的链接拼接为音乐的源
image.pngimage.png

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

参考

https://github.com/Kr1s77/awesome-python-login-model

上一篇下一篇

猜你喜欢

热点阅读