Python爬虫进阶:JS逆向到底在逆什么?加密算法与四步实战拆解 📅 发布时间:2026/8/30 3:45:26 👁 浏览次数: Python爬虫进阶必学JS逆向到底在逆什么从加密算法到实战套路的完整拆解做爬虫的朋友应该都有过这种体验requests 写得很熟练XPath 和正则也信手拈来但面对某些大厂站点时请求发出去返回的不是 JSON 数据而是一段看不懂的加密字符串或者直接提示“签名校验失败”。这时候你才意识到爬虫真正的门槛不在 Python 语法而在浏览器和服务器之间那层厚厚的 JS 加密逻辑。很多人把 JS 逆向想得很神秘觉得它需要极高的前端功底、需要懂汇编、需要会脱壳。实际从工程视角看绝大多数业务场景下的 JS 逆向核心工作只有四步定位加密入口、分析加密逻辑、还原算法流程、用 Python 复现结果。真正让新手放弃的往往不是某一个算法有多难而是不知道从哪里下手找不到加密函数或者复现结果总是和浏览器对不上。这篇文章会用一套适合系统学习的思路把 Python 爬虫中的 JS 逆向拆开讲清楚。你会了解大厂接口为什么普遍加密标准算法和自定义算法怎么区分逆向过程中常用的工具链有哪些以及一个加密接口从定位到用 Python 复现的完整流程。文章最后还会给出从入门到进阶的学习路径和工程建议帮你从“跑通案例”走向“自己能分析”。如果你正处于 Python 爬虫已经入门、却被各种 sign、token、密文参数卡住的阶段这篇文章值得完整读完。建议先收藏再按章节动手实践。1. JS逆向到底在解决什么问题先给一个明确的判断JS 逆向不是一种“黑客技术”它是爬虫工程中处理“数据获取链路被加密保护”的标准手段。它的本质是把前端 JavaScript 中负责生成加密参数的逻辑分析清楚然后在 Python 或者其他语言中把它复现出来从而让服务器认为当前请求来自一个合法客户端。在没有 JS 加密保护的网站里爬虫的工作路径非常直接分析接口 → 构造请求 → 解析数据。但加了加密参数之后同样的路径会变成分析接口 → 发现请求里多了 sign / token / ts 等参数 → 搜索这些参数的生成逻辑 → 还原前端加密函数 → 在 Python 中复现 → 才能构造出合法请求。这一步卡住了大量爬虫开发者。很多人 Python 基础很好requests、Scrapy、爬虫与数据可视化都学得不错但一遇到“参数加密”就束手无策。原因不是 Python 不够熟练而是缺少一套浏览器端调试和 JS 代码分析的方法论。从学习路径来看JS 逆向位于“Python 爬虫”和“前端安全”的交叉地带。它需要三方面的能力抓包分析的基础知道请求头、GET 参数、POST body、Cookie 都在哪里哪些字段可疑。浏览器调试的能力会用断点、调用栈、全局搜索、Hook 等手段定位前端代码。算法的识别与复现能力能判断加密用的是 MD5、SHA、AES、RSA 这些标准算法还是经过混淆和魔改的私有算法。当你把这三块能力补齐再回头看“60 个案例解析”这类资料会发现里面讲的其实是同一套方法在不同站点上的重复应用。真正值钱的不是案例本身而是案例背后那个可以迁移的分析框架。2. 加密接口的底层逻辑大厂为什么要做这么复杂理解了“JS 逆向在解决什么问题”再来看“为什么会有这个问题”。很多初学者会困惑大厂服务器明明有接口前端能拿到数据我为什么不能直接请求答案是服务器根本没有义务向所有请求者开放数据接口前端能拿到数据是因为它完成了约定的认证和签名流程。大厂接口的加密本质上是一套“客户端身份校验”机制。服务器希望确认当前请求是来自自己的 Web 页面或 App而不是脚本程序。为了做到这一点前端需要在请求中携带一些难以伪造的参数。常见的手段包括时间戳校验请求中携带当前时间戳服务器判断请求是否过期。爬虫如果不知道时间戳怎么生成直接构造就会失败。签名参数把请求参数按照一定规则排序、拼接再通过某种算法生成 sign 值。服务器用同样的规则重新计算如果和请求中的 sign 不一致就拒绝响应。Cookie 动态生成部分站点首次访问时会在 Cookie 中写入动态校验值后续请求必须携带这个值才能获取数据。请求头参数把加密结果放进自定义请求头例如 x-sign、authorization服务器解析后判断请求是否合法。返回值加密接口返回的数据本身也是密文前端拿到后通过 JS 解密渲染爬虫即使请求成功拿到的也是一堆密文。这些手段不是单独的实际项目中经常组合使用。这也是为什么一个简单的数据接口浏览器 Network 面板里可能同时出现好几个看起来多余的参数。你要做的不是盲目猜测而是抓住其中一个“加密入口”顺藤摸瓜找到生成逻辑。从开发者的角度看这套机制确实提高了数据获取的门槛。但也要承认它带来的是合法前端和服务器之间的一种“安全默契”。作为爬虫开发者学习 JS 逆向的目的应当是解决自己遇到的、有合法授权的数据获取问题而不是对任何站点进行恶意攻击或绕过安全限制。3. 学习JS逆向需要准备的技术栈与工具链JS 逆向不像普通的 Python 爬虫教程装好 requests 就能跑。它需要一套跨语言、跨工具的工作环境。下面是推荐的基础技术栈这部分是后续所有案例分析的通用底座。3.1 运行环境建议准备 Python 3.8 以上版本和 Node.js 14 以上版本。Python 用于最终的数据请求和算法复现Node.js 用于直接执行或调试网页中的 JS 代码。两者的安装都比较简单Windows 和 Linux 下都有对应的安装包或包管理器。安装完成后建议先在命令行里确认版本避免后续执行示例时因为环境问题报错。python --version node -v npm -v如果 Python 命令无法识别通常是环境变量没有配置好需要把 Python 安装目录和 Scripts 子目录加入 PATH。近年来很多 Python 教程也反复强调“安装 Python 后第一件事是配置环境变量”这一步对后续使用 pip 安装第三方库非常重要。3.2 Python 第三方库Python 侧建议安装下面几个库它们覆盖了请求发送、JS 执行、数据处理等主要环节。pip install requests pip install PyExecJS pip install pycryptodomerequestsPython 爬虫必装的 HTTP 请求库几乎每个案例都会用到。PyExecJS在 Python 中调用 JavaScript 代码的桥接库。当你还没把 JS 还原成 Python 代码时可以直接用它在 Python 里执行原版 JS 函数。pycryptodomeAES、RSA 等标准加密算法的 Python 实现库。复现前端加密逻辑时经常用到。另外建议安装一个支持 JS 代码格式化的工具例如 jsbeautifier用于处理从网页里复制下来的压缩代码。pip install jsbeautifier3.3 Node.js 侧工具Node.js 在 JS 逆向中的价值是运行 JavaScript 片段。很多加密函数是浏览器环境里的完整函数直接用 Python 翻译容易出错但放到 Node.js 里执行结果几乎不会差。最常用的是 jsdom它可以在 Node.js 中模拟浏览器 DOM 环境。部分加密函数依赖 document、window、navigator 等浏览器对象直接运行会报 undefined用 jsdom 补一个简易环境就能跑通。npm install jsdom3.4 浏览器调试工具浏览器依然是 JS 逆向的主战场。Chrome DevTools 是必须熟练使用的工具重点掌握这几个面板Elements查看页面结构但 JS 逆向用得相对少。Network抓包分析接口请求查看请求头、参数、响应。Sources查看和调试 JS 源码可以下断点、查看调用栈。Console在页面上下文执行 JS 代码测试加密函数。除了浏览器抓包工具也是常用辅助。常见的选择有 Fiddler、Charles 和 Burp Suite。其中 Burp Suite 经常出现在爬虫与审计相关话题里它既能抓包也能对请求做修改和重放适合比较复杂的调试场景。4. 标准算法与自定义算法60个案例背后的加密分类框架很多人看到“60 个 Python 爬虫 JS 逆向案例解析”第一个反应是“我要把 60 个站点的逆向过程全部背下来”。这是最大的误区。真实工作中你会不断遇到新站点靠背案例根本跟不上。更好的做法是先把案例背后的加密算法体系建立起来。从逆向视角看前端加密算法可以分成两大类标准算法和自定义算法。4.1 标准算法标准算法是指公开的、有固定规范和固定输出格式的算法。这类算法在 JS 逆向中最常见也最容易处理因为只要识别出是哪种算法就能直接用 Python 的标准库或第三方库复现。常见标准算法包括MD5输出 32 位十六进制字符串常用于签名、摘要。识别特征字符串长度固定为 32字符范围是 0-9 和 a-f。SHA 系列SHA-1 输出 40 位SHA-256 输出 64 位常用于文件校验和签名。Base64输出由字母、数字、、/ 和 组成常用于二进制数据的文本传输。AES对称加密算法需要密钥和偏移量输出长度通常是 16 的倍数。前端代码里能看到 key 和 iv。RSA非对称加密算法包含公钥和私钥。前端通常只使用公钥加密识别特征是比较长的密钥字符串。HMAC基于哈希的消息认证码需要密钥常用于接口签名。识别标准算法主要有两个线索一个是看 JS 代码中的算法名称例如 md5、sha256、CryptoJS.AES另一个是看输出字符串的结构例如 32 位十六进制基本可以锁定 MD564 位十六进制基本可以锁定 SHA-256。4.2 自定义算法自定义算法是指开发者在标准算法基础上做的魔改或者完全自己写的一套逻辑。例如把 MD5 的结果拆开重排、在计算前给参数加固定盐值、把明文所有字符倒序后再加密、把标准算法结果再做一次字符替换。这类算法没有现成的 Python 库可以直接调用但并不意味着要手写加密算法。处理思路是把前端 JS 中的函数完整拿出来用 Node.js 或 PyExecJS 直接执行而不是强行翻译成 Python。4.3 混淆与 Webpack真正让逆向者头疼的往往不是算法本身而是代码的组织形式。现代前端项目大量使用构建工具打包JS 文件可能被压缩成一整行函数名全部变成无意义的字母。这种情况下直接阅读源码非常困难需要用格式化工具处理再通过搜索关键词定位加密函数。Webpack 是前端最常见的打包工具之一。它的特点是会把所有模块包在一个自执行函数里模块之间通过__webpack_require__这样的加载函数互相调用。逆向 Webpack 站点时通常需要找到模块加载器然后把包含加密函数的模块单独扣出来放到 Node.js 环境里补齐依赖运行。从 60 个案例提炼出的规律是绝大多数站点的加密强度并不高80% 的场景落在“标准算法 简单参数拼接”这个范围内。真正需要花大量时间的是那些上了 Webpack、混淆、反调试的站点而这些通常也不是靠“背案例”能解决的需要系统掌握调试技巧。5. 逆向四步法定位、分析、还原、复现无论面对多复杂的加密接口实战过程基本都遵循一个四步走的方法论。这套方法论比任何具体案例都重要强烈建议写代码前先把流程图在脑子里过一遍。5.1 第一步定位加密入口用浏览器开发者工具打开目标页面切到 Network 面板找到数据接口观察请求参数。重点看哪些参数是动态的、无法直接写死的。常见可疑参数有 sign、token、signature、encrypt、param、key 等。确定可疑参数后用全局搜索来定位 JS 代码中的生成逻辑。在 Sources 面板中按 CtrlShiftF输入参数名例如sign。搜索结果里会出现很多引用位置优先找赋值语句例如sign: btoa(...)、sign hex_md5(...)、params.sign ...这一类。如果全局搜索找不到可以在该参数生成的位置下断点。再次刷新页面或触发搜索请求发出前会命中断点然后通过调用栈向上追溯找到真正加密的那一层函数。5.2 第二步分析加密逻辑拿到加密函数后不要急着复制代码。先通读一遍弄清楚几个问题加密输入是什么是请求参数拼接的字符串还是某个固定字符串加时间戳加密输出是什么是十六进制字符串、Base64还是 JSON 结构有没有用到随机数、时间戳、Cookie 中的动态值有没有调用其他工具函数工具函数是否需要一起复制这个阶段可以借助 Console 面板直接调用函数测试。例如在断点处执行encrypt(test)看输出结果再尝试修改输入观察输出如何变化。通过控制变量法可以快速理解加密函数的输入输出关系。5.3 第三步还原算法如果加密函数使用标准算法直接用 Python 的 hashlib、Crypto 库复现。如果加密函数比较简单直接把 JS 逻辑翻译成 Python。如果加密函数依赖大量浏览器环境对象或者混淆程度高优先选择把整个 JS 代码复制到 Node.js 中执行而不是强行翻译。这里有一个很重要的判断标准不要为了“纯 Python 实现”而花大量时间翻译复杂 JS。工程上最重要的是结果一致而不是实现语言统一。用 Node.js 执行 JS 函数既省时间又准确在团队项目里也更稳妥。5.4 第四步用 Python 复现并验证最后一步是把分析结果整理成可复用的 Python 代码。代码里应该包含完整的请求头、参数构造逻辑、加密函数和请求发送逻辑。验证方法是用同一个请求参数分别在浏览器和 Python 中计算加密值对比是否一致再发送完整请求看是否能正常拿到数据。从经验来看很多新手在“复现”这一步最容易踩坑。原因通常不是算法本身分析错了而是细节没对齐例如字符串编码不一致、参数排序顺序错误、缺少某个请求头、Base64 填充符被处理方式不同。遇到这类问题不要灰心按下一章的排查思路一项项检查即可。6. 完整实战从加密接口到Python代码理论讲了一大堆这里用一个贴近真实业务的最小示例把四步法完整走一遍。为了便于演示这个示例模拟的是一个常见的“时间戳 签名”接口加密逻辑是参数拼接后做 MD5 摘要。6.1 假设场景假设目标接口为登录后获取商品列表的接口请求方式为 POST参数包括 page、limit、keyword、ts、sign。其中 ts 是 13 位毫秒时间戳sign 是加密签名。前端生成逻辑大致如下// 文件路径webpack打包后的某个chunk.js格式化后示意 function getSign(params, secretKey) { var keys Object.keys(params).sort(); var str ; for (var i 0; i keys.length; i) { str keys[i] params[keys[i]] ; } str key secretKey; return md5(str); }前端调用时传入业务参数和固定密钥生成 sign 后追加到请求参数里。服务器用同样的规则重新计算sign 一致才返回数据。6.2 定位加密函数在 Network 面板找到商品列表接口看到参数里有 sign就在 Sources 面板全站搜索sign。搜索结果里出现一个返回 md5 的函数再往上找调用处发现它接收的参数正是请求参数对象。这个函数就是我们要找的加密入口。6.3 用 Node.js 验证函数把 getSign 函数和它依赖的 md5 函数整理出来放到一个 js 文件里在 Node.js 中运行。为了模拟前端环境用简单的函数替代 md5后续再替换成真实标准库。// 文件路径test_sign.js const crypto require(crypto); function md5(str) { return crypto.createHash(md5).update(str, utf8).digest(hex); } function getSign(params, secretKey) { const keys Object.keys(params).sort(); let str ; for (let i 0; i keys.length; i) { str keys[i] params[keys[i]] ; } str key secretKey; return md5(str); } // 模拟测试 const params { page: 1, limit: 20, keyword: python, ts: 1699999999999 }; console.log(getSign(params, my_secret_key));运行这段代码会得到一个 32 位的十六进制字符串。这个结果可以作为后续 Python 实现的基准。node test_sign.js到这里标准算法的 md5 已经确定。如果实际项目里用的是 CryptoJS 这种库也一样能通过 Node.js 运行。6.4 用 Python 复现接下来把同样的逻辑翻译成 Python。这里用 request 构造请求用 hashlib 计算签名。文件结构如下# 文件路径get_product_list.py import hashlib import time import requests SECRET_KEY my_secret_key def generate_sign(params: dict) - str: keys sorted(params.keys()) raw_string for key in keys: raw_string f{key}{params[key]} raw_string fkey{SECRET_KEY} return hashlib.md5(raw_string.encode(utf-8)).hexdigest() def get_product_list(keyword: str python): url https://api.example.com/api/product/list params { page: 1, limit: 20, keyword: keyword, ts: str(int(time.time() * 1000)), } params[sign] generate_sign(params) headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://www.example.com/, Content-Type: application/x-www-form-urlencoded; charsetUTF-8, } response requests.post(url, dataparams, headersheaders, timeout10) return response.json() if __name__ __main__: result get_product_list() print(result)代码逻辑并不复杂。generate_sign 函数先把参数字典的 key 排序再拼接成keyvalue的字符串最后加上固定密钥计算 MD5。这里有一个容易被忽略的细节Python 计算 MD5 前必须把字符串 encode 成 bytes否则会报Unicode-objects must be encoded before hashing的错误。实际项目中如果前端用的是encodeURIComponent对参数值做了编码Python 侧也要对应处理。6.5 通过 PyExecJS 直接调用 JS 代码有的站点加密逻辑比这个复杂得多用 Python 翻译容易出错。这时候推荐直接用 PyExecJS 在 Python 里执行原版 JS 函数。# 文件路径execjs_demo.py import execjs js_code const crypto require(crypto); function md5(str) { return crypto.createHash(md5).update(str, utf8).digest(hex); } function getSign(params, secretKey) { const keys Object.keys(params).sort(); let str ; for (let i 0; i keys.length; i) { str keys[i] params[keys[i]] ; } str key secretKey; return md5(str); } ctx execjs.compile(js_code) params { page: 1, limit: 20, keyword: python, ts: 1699999999999 } sign ctx.call(getSign, params, my_secret_key) print(sign)运行结果应该和 Node.js 中计算的完全一致。如果你的真实案例里加密函数依赖了浏览器对象可以结合 Node.js 侧 jsdom 先补一个简易 document/window 环境再把补环境后的代码用 execjs 或子进程执行。6.6 运行验证执行上面的 Python 代码只要能打印出和浏览器一致的数据结构说明签名计算无误。如果返回的是错误信息优先检查sign 的计算结果和浏览器是否一致。请求头是否完整特别是 User-Agent、Referer、Cookie。请求参数里是否存在浏览器环境产生的额外字段。服务器是否对高频请求做了限流。7. 实战中的常见问题与排查思路以下问题是爬虫开发者在 JS 逆向实战中最常遇到的按出现的频率排列。问题现象可能原因排查方式解决方案全局搜索找不到 sign 生成位置参数名被混淆或变量名是动态拼接在 Network 面板中给请求参数下断点查看调用栈使用 XHR 断点或事件断点顺着调用栈向上找Node.js 中运行 JS 报 document 未定义加密函数依赖浏览器 DOM 对象查看报错位置确认是否引用了 window/document引入 jsdom 补环境或在函数外 mock 最小对象Python 计算的 MD5 和浏览器不一致字符串编码不同或拼接顺序错误把中间拼接结果打印出来对比统一使用 UTF-8 编码按前端源码中的顺序拼接请求返回参数校验失败缺少 Cookie 或动态 Token对比浏览器和 Python 请求的 Headers 差异先跑通带 Cookie 的请求再逐步减少多余 header接口返回的是密文而不是 JSON响应数据被加密搜索 decrypt 或 decode 关键词分析解密函数通常与加密函数在同一 JS 文件中执行 execjs 报编码错误代码中存在中文字符或特殊字符检查 JS 代码编码在 Python 文件头部声明 UTF-8使用 JsSource.encode(utf-8)请求过于频繁被限制触发了风控或限流查看响应状态码和响应体降低请求频率使用代理池避免高频突发请求这里特别想强调一条工程经验不要遇到问题就怀疑算法复杂。绝大多数不一致问题都出在细节上优先做“逐段对比”。把前端参数拼接的每一步和 Python 代码每一步打印出来找到第一个不一致的位置往往立刻就能定位原因。8. 学习路径与工程化建议如果把 JS 逆向当作一门技能来规划建议按下面的阶段循序渐进。每个阶段都有明确的目标不要急着挑战高难度站点。8.1 第一阶段爬虫基础与调试基础先熟练掌握 Python 爬虫的基础流程。环境搭建方面围绕 Python 安装、环境变量配置、pip 使用、requests 请求库、数据解析这几个点打牢基础。这一阶段的目标是能独立写爬虫抓取没有加密的静态网站。同时开始熟悉浏览器开发者工具。重点练习 Network 面板的抓包分析、Sources 面板的断点调试。新手可以从任意一个普通网站开始尝试找到它的数据接口看懂请求参数的含义。8.2 第二阶段标准算法识别与复现这一阶段的核心是“看到加密参数不慌”。准备一个笔记把 MD5、SHA、AES、RSA、Base64、HMAC 的特征记录下来。遇到加密接口时先判断它属于哪一类再想对应的 Python 实现。AES 和 RSA 比 MD5、SHA 略复杂因为涉及密钥、填充方式、分组模式和加密结果编码。建议亲手在 Node.js 和 Python 中分别实现一遍加解密确认结果一致。这一阶段可以用模拟资料和开源项目练手不一定要直接挑战大厂站点。8.3 第三阶段浏览器环境模拟与 JS 调用掌握从网页中提取加密函数放到 Node.js 或 execjs 中运行的能力。遇到依赖浏览器对象的代码学会用 jsdom 补环境。这个阶段的常见素材是各类带登录态、带签名参数的网站。8.4 第四阶段混淆对抗与代码还原处理 Webpack 打包、变量名混淆、字符串加密、控制流平坦化等问题。这是进阶内容建议有一定逆向基础后再接触。工具层面可以了解 AST抽象语法树用 Babel 或类似工具对代码做自动化还原。8.5 工程化建议当你可以独立完成逆向分析后不要把代码写成一次性脚本。从工程化角度有几点建议封装统一的签名生成模块。每个目标站点对应一个模块输入业务参数输出完整请求参数。参数与逻辑分离。密钥、URL、请求头尽量放进配置文件避免硬编码。做好日志记录。每次请求记录 URL、参数、状态码、响应摘要排查问题时非常有帮助。遵循最小权限原则。只获取业务需要的数据不做超出范围的越权请求。控制请求频率。设置合理的延时和重试机制避免对目标服务器造成压力。9. 合规提醒与长期成长方向最后必须强调一点JS 逆向技术本身是中性的但使用场景必须合规。在学习和实战过程中建议只在下面几种范围内操作自己有合法权限的站点或系统。已获得授权测试的个人或企业项目。公开的、不涉及个人隐私和商业机密的接口数据。用于学习研究且不对外产生破坏性影响的场景。不建议对涉及账号体系、支付、隐私数据、未授权内部系统的接口做逆向尝试。这不只是道德问题更可能触犯法律。爬虫开发者应该把“合法、合规、克制”作为基本职业素养。从长期成长来看JS 逆向只是反爬对抗中的一环。服务端还有 IP 限流、设备指纹、行为分析、验证码等更多防护手段。真正的高级爬虫工程师不是靠一两个逆向技巧取胜而是能把数据采集工程的全链路都想清楚包括采集策略、存储设计、任务调度、数据质量监控和合规边界。如果你正处在爬虫入门的瓶颈期被各种加密参数折腾到怀疑人生不用焦虑。按照这篇文章给出的四步法和学习路径从最基础的标准算法开始先跑通一个完整案例再逐步增加难度。你会发现所谓“逆向大神”并不是天生会破解所有加密他们只是把方法论练成了肌肉记忆。建议你现在就打开浏览器开发者工具随便找一个带签名参数的接口按“定位 → 分析 → 还原 → 复现”走一遍。跑通第一个案例之后后面的事会顺利很多。