python 爬虫进阶 - js逆向

前言

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

Python

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

  • 基础知识 语法与特性

requests

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

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

Beautiful Soup

https://cuiqingcai.com/1319.html

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

爬虫与js逆向

百度翻译

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

分析

  • 打开百度翻译

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

分析流程

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

image.png
image.png

image.png
image.png
  1. 查看请求参数是否有变化
  • 图一:
image.png
image.png
  • 图二:
image.png
image.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.png
image.png
  1. 跟进代码,分析AJAX请求
image.png
image.png
  1. 查找我们需要的值
image.png
image.png
  • 准确的找到我们需要的值
image.png
image.png
  • 复制我们需要的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 函数的上面

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

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

var i = "320305.131321201"

最后

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

QQ音乐下载

qq音乐下载是怎样的流程

分析流程

  • 打开QQ音乐

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

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

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

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

  1. 可查看必要参数sign值与data,拼接data,查看参数sign的得出
image.png
image.png
  1. debug 调试 获取到js的方法与sign值的获取js代码
image.png
image.png

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

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

参考

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335