这次我们来看一套在爬虫圈流传很广的实战资料:60个Python爬虫JS逆向案例解析。它不打算讲什么是 requests、什么是 BeautifulSoup,而是直接把爬虫过程中最让人头疼的JS逆向、加密参数、签名算法拆开揉碎,用大量实战题目带你从定位加密入口开始,一直做到用Python复现,最后把逆向结果落到可运行的抓取脚本里。
这类案例合集最值得关注的是范围。从标题就能看出,它覆盖了三块东西:一是JS逆向的常规操作,比如找加密函数、打断点、观察调用栈、扣代码、补环境;二是企业级接口里最常见的加密算法,比如MD5、SHA系列、AES、RSA、Base64变种、HMAC签名等;三是把逆向结果转成Python代码的完整过程。很多新手卡住的地方不是不知道算法,而是不知道在网页里怎么找到算法入口。这套案例解决的主要就是这个问题。
先给结论:这套资料适合已经会Python基础语法、能用requests写简单爬虫、但一遇到加密参数就不知道怎么下手的读者。硬件上没有门槛,不需要显卡,不需要高端服务器,一台普通电脑就够了。操作系统Windows、macOS、Linux都行,只要你装好Python和Node.js。本文会围绕这套资料给出完整的使用方法、学习路线、调试思路、工程化落地方式,以及最常见的报错排查清单,帮助你判断值不值得花时间学,以及怎么学效率最高。
1. 核心能力速览
先按一张表把这套资料的特点说清楚。
| 能力项 | 说明 |
|---|---|
| 资料类型 | 爬虫JS逆向实战案例合集,包含60个案例 |
| 核心主题 | Python爬虫、JS逆向、逆向加密、标准算法 |
| 主要功能 | 讲解定位加密参数、还原签名算法、用Python复现加密逻辑 |
| 覆盖算法 | 常见哈希算法、对称加密、非对称加密、编码算法、签名机制 |
| 前置要求 | Python基础语法、requests基本使用、浏览器开发者工具基本操作 |
| 硬件要求 | 普通电脑即可,无特殊硬件要求 |
| 学习方式 | 案例驱动,建议边看边调试 |
| 工程落地 | 案例结果可封装成Python函数,用于批量请求任务 |
| 适合读者 | 想突破爬虫加密瓶颈的初中级Python工程师、安全测试学习者 |
| 合规边界 | 仅限授权测试环境、公开接口学习和个人技术研究,禁止未授权抓取 |
需要说明一点:60个案例并不是让你“背下来”,而是让你通过大量重复,形成一套固定的逆向分析习惯。算法本身是公开标准,真正值钱的是定位逻辑和调试方法。
2. 适用人群、学习边界与合规提醒
2.1 这套资料适合谁
如果你属于下面任何一类,这套案例合集会很有帮助:
- 会写Python脚本,但遇到接口里的
sign、token、encrypt这类参数就不知道怎么处理。 - 想理解企业级Web前端常见的加密体系,但不想去啃晦涩的密码学教材。
- 已经能抓包,但不清楚怎么从JS文件里找到加密入口。
- 希望把爬虫请求写得像真实客户端,减少被服务端拒绝的概率。
- 做安全测试或接口测试,需要理解前端参数是怎么生成的。
2.2 学习边界与红线
这里必须强调合规问题。JS逆向本身是一项技术能力,可以用于研究、漏洞挖掘、接口测试、开发辅助工具,但绝不能用于未授权抓取他人数据、绕过付费机制、恶意攻击或窃取个人信息。国内《个人信息保护法》《数据安全法》《网络安全法》对数据抓取和利用有明确要求。使用这套案例时,应当遵守下面的安全边界:
- 只能在获得授权的测试环境、自己的服务器、开源项目或公开API上进行学习。
- 不要用里面的方法去抓取需要登录才能访问的私有数据。
- 抓取前检查目标网站的robots协议和服务条款。
- 不要针对具体网站做逆向绕过或分享绕过方案。
- 涉及用户信息、版权内容时必须获得授权。
简单说:算法可以学,工程落地要克制,测试目标要合法。技术本身是中性的,使用方式决定了它是工具还是风险。
3. 学习环境与工具链准备
学习这套案例前,先把环境准备好。下面是一套通用配置清单,适用于Windows、macOS和Linux三平台。
3.1 基础环境
| 工具 | 用途 | 说明 |
|---|---|---|
| Python 3.9+ | 运行爬虫脚本、复现算法 | 建议3.10或3.11,兼容性更稳 |
| Node.js 18+ | 调试JS代码、快速验证函数 | 部分加密函数用Node执行更直接 |
| Chrome / Edge | 抓包、打断点、观察调用栈 | 开发者工具是主战场 |
| 代码编辑器 | 管理案例代码 | VS Code是常见选择 |
| 抓包工具 | 分析请求、拦截响应 | Charles、Fiddler、Burp Suite等 |
3.2 Python环境安装
Windows下建议直接到Python官网下载安装包,安装时勾选“Add Python to PATH”。如果你已有Python环境,只需要确认版本:
python --version pip --version需要安装的核心库一般包括requests、pycryptodome、execjs等:
pip install requests pycryptodome execjs这里说明一下:pycryptodome用来在Python里实现AES、DES、RSA等标准算法;execjs可以在Python中调用本机Node.js执行JS代码,适合处理无法快速用Python重写的混淆函数。
3.3 Node.js安装
很多案例在扣出JS函数之后,不会马上手工转成Python,而是先用Node跑一遍确认逻辑。安装Node后验证:
node --version npm --version3.4 浏览器开发者工具准备
打开Chrome或Edge,按F12进入开发者工具,重点熟悉四个面板:
- Network:查看请求URL、请求头、请求体、响应体。
- Sources:查看JS文件、打断点、跟踪调用栈。
- Console:手动执行JS片段,快速验证函数输出。
- Application:查看Cookie、LocalStorage、SessionStorage。
这套工具链整体上没有难装的软件,装完就能进入案例实操。这也是这类资料一个很明显的优势:软门槛低,硬门槛主要在分析思维。
4. 六类高频JS逆向场景拆解
60个案例虽然数量多,但底层场景是有规律的。根据这类资料的常见结构,可以归纳为六类,每一类背后对应一套固定的解决方案。
4.1 参数加密类
这是最普遍的一类。接口里多了一个sign、s、v之类的参数,每次请求都不一样。处理思路是:
- 在开发者工具Network面板找到发起请求的XHR。
- 找到请求参数里加密字段的名字。
- 在Sources面板中全局搜索这个字段名。
- 定位到生成该字段的JS函数。
- 在函数入口打断点,观察入参和返回值。
- 把函数逻辑用Python或Node实现。
这类案例的核心是让人学会“通过参数名反向定位函数”,而不是一上来就猜算法。
4.2 标准算法识别类
企业级加密最常见的不是高深算法,而是标准算法的组合:
- 编码类:Base64、Hex。
- 摘要类:MD5、SHA1、SHA256、HMAC-MD5、HMAC-SHA256。
- 对称加密:AES-CBC、AES-ECB、DES。
- 非对称加密:RSA。
识别方法可以放在搜索加密参数后的代码里看,比如看到createHash、createHmac、CryptoJS.AES、JSEncrypt这些关键字,基本就能判断算法类型。标准算法有一个好处:可以直接用pycryptodome或者Python内置hashlib复现,不用扣整个JS文件。
4.3 请求头与Cookie校验类
有些接口的加密不在请求体里,而在请求头或Cookie中。常见的有:
User-Agent带指纹信息。Authorization是动态token。- Cookie中某个字段由JS生成,服务端校验。
这部分案例训练的是“完整还原请求链路”的能力,不能只看一个请求,要看页面触发请求前执行了哪些JS。
4.4 浏览器环境检测类
有些JS会检测当前运行环境是不是真实浏览器,比如检查window.navigator.webdriver、window.chrome、document.hidden等属性。这类在Python爬虫里很常见,处理方式分成两种:一是把环境检测部分的JS逻辑用Python模拟返回,二是用Node配合jsdom等库补环境。
4.5 反爬与请求频率限制类
这类案例实际上不是纯JS逆向,而是讲爬虫请求怎么被服务端限制、怎么在合规范围内合理低频访问。比如接口返回验证码、滑块、429状态码时的应对思路。这里必须提醒:这部分内容只能用于理解反爬机制,在授权环境下做研究,不能用来自动化绕过验证码或规避服务端限制。
4.6 扣代码与补环境类
当加密逻辑复杂,没法简单用Python重写时,常见做法是把JS文件里的关键函数抠出来,放到一个独立的JS脚本里,然后用Node运行。如果运行时报错提示缺少浏览器对象,就要补简易环境。execjs就是在这种场景下常用的桥梁。
5. 通用JS逆向分析流程与代码示例
不管你面对的是哪一类场景,下面这套流程可以覆盖大部分情况。建议把这套流程作为“肌肉记忆”反复练习,60个案例本质上就是在强化这套流程。
5.1 定位请求与加密参数
第一步,打开浏览器开发者工具的Network面板,勾选Fetch/XHR,刷新页面,找到目标接口。观察请求URL和请求体,找到加密字段。
5.2 全局搜索加密字段名
切到Sources面板,按Ctrl+Shift+F打开全局搜索,输入加密字段名,比如sign。搜索结果会有很多,优先看名字里带create、getSign、makeSign、encrypt的JS函数。
5.3 打断点并观察入参
在候选函数的return语句处打断点,重新触发请求。此时浏览器会停在断点位置,可以在Scope面板看到函数的入参和局部变量。这一步是核心,目的是搞清楚加密函数的输入是什么。
5.4 手动执行JS验证
在Console里手动调用这个函数,传入同样的参数,看输出是否和Network里抓到的参数一致。如果一致,说明函数定位正确。
下面给出一个教学示例。假设页面里有一段核心加密逻辑的JS简化为:
const crypto = require('crypto'); function buildSign(params, secret) { // 按key排序后拼接 const signStr = Object.keys(params) .sort() .map(key => `${key}=${params[key]}`) .join('&'); // HMAC-SHA256签名 return crypto.createHmac('sha256', secret) .update(signStr) .digest('hex'); } module.exports = { buildSign };这是一个标准算法封装,它真实业务里经常出现。用Python同步实现:
import hashlib import hmac from typing import Dict def build_sign(params: Dict[str, str], secret: str) -> str: sign_str = "&".join( f"{key}={params[key]}" for key in sorted(params) ) return hmac.new( secret.encode("utf-8"), sign_str.encode("utf-8"), hashlib.sha256, ).hexdigest()两段代码的输入输出完全一致。这就是“JS逆向转Python”的本质:把页面里看到的算法逻辑用Python再实现一遍,不是抄代码,而是理解参数拼接规则和算法类型。
5.5 用Python调用JS兜底
有些场景下,JS代码被压缩混淆,手工还原成本太高。此时可以用Node子进程或者execjs调用JS文件,直接拿结果。下面是Node子进程方式:
import json import subprocess def build_sign_by_node(payload: dict) -> str: proc = subprocess.run( ["node", "sign.js", json.dumps(payload)], capture_output=True, text=True, timeout=10, ) if proc.returncode != 0: raise RuntimeError(f"node执行失败: {proc.stderr}") return proc.stdout.strip()这里的sign.js是已经扣出来的独立JS文件。这个模式的优点是见效快,缺点是依赖Node环境,部署到服务器时也需要安装Node。所以更稳妥的做法是:先用Node确认逻辑,再用Python重写,最终去掉对Node的依赖。
6. 从JS逆向到Python批量任务落地
单个接口逆向完成后,要考虑工程化问题。60个案例如果只停留在“能跑通”,实际价值有限;把它变成稳定的Python任务模块,才是真正的落地。
6.1 模块目录结构
建议按下面的结构组织代码:
crawler_workspace/ ├── algorithms/ # 标准算法复现,如aes_cbc.py、rsa_encrypt.py ├── decrypt/ # 从JS抠出的降级方案,如node_bridge.py ├── clients/ # 各类请求客户端,封装session、header、sign ├── tasks/ # 批量任务脚本 ├── data/ # 抓取结果数据 ├── logs/ # 运行日志 └── tests/ # 算法一致性验证这样的好处是:算法实现、请求逻辑、批量任务分层管理,后续切换业务目标时只需要改clients和tasks。
6.2 登录态与请求头管理
逆向成功之后,请求能不能稳定跑起来,还取决于header和Cookie。用requests.Session管理连接,统一设置UA、Referer,把动态参数通过预处理函数注入。
import requests session = requests.Session() session.headers.update({ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Referer": "https://example.com/", }) def inject_dynamic_params(url: str, payload: dict) -> dict: """ 把JS逆向得到的签名逻辑注入到请求参数中。 实际实现需要按目标接口的签名规则替换。 """ payload = dict(payload) # 这里调用上面实现的build_sign,按业务定制入参 # payload["sign"] = build_sign(payload, secret) return payload def fetch_once(url: str, base_payload: dict) -> dict: payload = inject_dynamic_params(url, base_payload) resp = session.get(url, params=payload, timeout=10) resp.raise_for_status() return resp.json()这里没有写到具体签名函数,原因是要提醒你:生产环境里每个接口的签名规则都不同,先把5.4里的算法测试跑通,再把函数接进来。
6.3 批量任务与失败重试
批量爬取不是“写个for循环跑所有URL”这么简单。要控制请求频率、记录状态、失败重试、去重。下面是一个通用模板:
import logging import time from typing import Callable, Iterable logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") def run_batch( requests_iter: Iterable[dict], fetch_func: Callable, interval: float = 1.0, max_retry: int = 3, ): for i, req in enumerate(requests_iter, start=1): for attempt in range(1, max_retry + 1): try: data = fetch_func(**req) # 这里插入结果存储逻辑 logging.info(f"第{i}个请求成功") break except Exception as exc: logging.warning(f"第{i}个请求第{attempt}次失败: {exc}") if attempt == max_retry: logging.error(f"第{i}个请求重试耗尽,跳过") else: time.sleep(interval * attempt) time.sleep(interval)使用这个模板有几个必须注意的点:请求间隔不能太短,避免给目标服务器造成压力;每次失败要记录日志;重试次数要有限制;对已经抓取过的数据要做去重。
6.4 数据存储与结构化
60个案例里,最后通常会落到数据保存。单机场景建议先用SQLite或CSV,数据量大再考虑MySQL或对象存储。关键是设计好主键和去重字段,避免重复数据堆积。
一个简单的CSV追加例子:
import csv from pathlib import Path OUTPUT = Path("data/result.csv") def append_result(row: dict): is_new = not OUTPUT.exists() with open(OUTPUT, "a", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=list(row.keys())) if is_new: writer.writeheader() writer.writerow(row)这里只做示例。真实业务里,建议先落本地文件再定期导入数据库,防止批量任务中断导致数据丢失。
7. 算法一致性与性能验证
做完逆向和工程化,不能直接上线,先做一致性验证。
7.1 验证JS输出和Python输出是否一致
运行一套脚本,对同一组输入分别调用JS函数和Python函数,比对结果:
import json import subprocess def js_sign_for_test(payload: dict, js_path: str) -> str: proc = subprocess.run( ["node", js_path, json.dumps(payload)], capture_output=True, text=True, timeout=10, ) return proc.stdout.strip() def test_sign_consistency(): test_cases = [ {"name": "test", "ts": "1710000000"}, {"uid": "10086", "ts": "1710000001", "page": "1"}, {"keyword": "python", "limit": "10"}, ] for case in test_cases: js_result = js_sign_for_test(case, "sign.js") py_result = build_sign(case, "secret_key") assert js_result == py_result, f"case {case} 不一致" print(f"case {case} -> {py_result}")这一步非常关键。很多案例跑不通,原因不是算法没找对,而是某个字段的编码方式或大小写规则不一致,比对之后就清楚了。
7.2 观察响应速度与请求成功率
在小批量任务里统计:平均响应时间、状态码分布、失败率。如果失败率高,先看是否频率过快触发限流。
单机爬虫的性能瓶颈往往不在CPU,而在目标服务器的响应速度和网络延迟。请求间隔建议从1秒起步,根据目标接口的实际情况调整。不要为了追求速度去压缩间隔,尤其不要对生产环境的接口做高频请求。
7.3 资源占用观察
这类案例不需要显卡,运行时的资源占用主要集中在:
- 浏览器开发者工具:占内存约500MB到1GB。
- Node.js调试进程:内存占用不高,但频繁调用会有进程创建开销。
- Python批量任务:requests请求是IO密集型,CPU占用很低,使用进程池收益有限。
如果使用execjs或者Node子进程,要警惕每次调用都重新启动Node带来的延迟,批量场景下优先改成Python原生实现。
8. 常见问题与排查方法
下面把学习这套案例时最容易碰到的问题整理成表。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| Python执行报错ModuleNotFoundError | 依赖库未安装 | pip list确认包 | pip install 对应依赖 |
| JS函数在浏览器里正常,Node里报错 | 代码依赖浏览器对象 | 看报错中的变量名 | 用jsdom补环境或改写函数 |
| 算法复现结果和页面不一致 | 参数拼接顺序或编码方式不同 | 打印中间值逐段对比 | 用单元测试锁定差异 |
| 请求返回403 | 请求头或Cookie校验失败 | 对比浏览器请求头 | 用Session保存Cookie并补全headers |
| 请求返回429 | 请求频率过高 | 查看响应头Retry-After | 增大间隔,加重试机制 |
| execjs执行JS超时 | JS代码中存在死循环或依赖浏览器API | 用Node命令行单独执行 | 拆分函数,单独验证 |
| 批量任务中途崩溃 | 未处理网络异常或数据存储异常 | 查看日志文件 | 增加重试、事务、断点续跑 |
| 同一个函数多次调用返回不同结果 | 函数内部依赖时间戳或随机数 | 对比入参中的动态字段 | 把动态字段也纳入参数拼接 |
| 找不到加密入口 | 搜索字段名不准 | 看请求体字段是否有加前缀 | 改用网络面板的Initiator查看调用栈 |
| 签名算法识别错误 | 误把Base64当AES | 查看JS中关键词 | 关注createCipher、decrypt等API |
8.1 定位不到加密函数的排查思路
有时候搜索参数名搜不到结果,这是因为前端代码做了压缩或者把字段名改了。这种情况下不要继续盲搜,换两个方向:
- 使用Network面板里该请求的Initiator,直接查看调用它的JS函数。
- 搜索加密字段的常见函数名,比如
sign、encrypt、token、getParam。
8.2 算法结果对不上的排查思路
如果确认算法类型一致,但Python结果和页面结果不同,按顺序检查:
- 参数拼接顺序是否一致。
- 是否用了
JSON.stringify而不是普通字符串拼接。 - Base64编码时是否包含URL-safe处理。
- 密钥是否需要解码,比如Base64解码后再传给AES。
- AES的IV是否固定,是否取自定义字符串。
- 时间戳是否在运行时生成,导致每次签名不同。
9. 学习方法与最佳实践
60个案例如果只是“看一遍”,效果很差。技术类内容必须上手调试。下面给出一套适合大多数人的学习路径。
9.1 第一种学法:按算法类型刷
先快速扫一遍案例目录,把涉及MD5、SHA、HMAC的案例放到前面;再刷AES、DES对称加密案例;最后刷RSA非对称加密案例。这样每刷一个类型,都是在强化同一种标准化实现方式。
9.2 第二种学法:按调试难度刷
先做“直接搜参数名就能找到函数”的简单案例,再挑战压缩混淆案例。通过难度递进,逐步建立对JS调试工具的信任感。
9.3 建立自己的训练库
每个案例跑通后,把以下信息记录在一个Markdown文件里:
- 目标接口的请求方式。
- 加密参数名。
- 定位方式:搜索、Initiator还是Hook。
- 算法类型。
- 参数拼接规则。
- Python实现代码。
- 踩过的坑。
这样做30个案例后,你会形成一套自己的逆向笔记,比单纯收藏别人的整理更有价值。
9.4 工程化最佳实践
- 第一个案例先小参数测试,不要在完整业务上直接跑。
- 保留一套最小可运行配置,便于快速回滚。
- 加密实现、请求逻辑、批量任务分文件管理。
- 批量任务必须有日志、重试、去重和断点续跑能力。
- 接口服务或本地脚本要限制访问范围,不要暴露到公网。
- 涉及人脸、声音、版权素材、个人信息时必须确认授权。
- 发布或商用前做效果复核,确认数据来源合法合规。
10. 总结
这套60个Python爬虫JS逆向案例解析,最核心的价值不是“60个能直接抄的答案”,而是通过大量重复,让你形成一套稳定的逆向分析流程:定位加密参数、搜索函数入口、打断点观察入参、验证算法类型、用Python或Node复现、批量工程化落地。真正吃透这套流程后,你面对接口加密问题时不会再靠猜,而是能一步步拆解出请求参数的生成逻辑。
如果你已经会Python基础语法和requests爬虫,建议从最简单的案例开始,先把浏览器开发者工具的断点调试练熟,再进入算法复现阶段。最容易踩的坑,是拿到一个案例后不调试就复制代码,结果遇到稍微变化的目标接口就完全不会处理。正确的做法是把案例里的调试路径走一遍,理解每一步为什么这样做,再尝试用自己的方式实现一遍。
第一次刷建议按算法类型分类,而不是按案例编号从小到大,这样能更快建立起标准算法与Python代码之间的对应关系。跑通三五个案例之后,你就可以开始搭建自己的签名实现工具库,把常见算法封装成独立函数。后续再遇到新的目标接口,大部分工作都会变成“套模板 + 微调参数”。
这套资料的整体难度曲线适中,从新手到进阶都有覆盖。坚持把前20个案例完整调试完,跨过最开始的“找不到入口”阶段后,后面会越来越顺。建议收藏备用,也建议给自己定一个目标:每周精做三个案例,并且每个案例都写成调试笔记。