1. 项目概述:从一次真实的招标数据抓取说起
最近在帮朋友处理一个数据分析项目,需要获取某高校招标采购网的公开数据。目标网站是“同济xxxx招标采购网”,听起来是个正经的官方平台,本以为直接发个请求就能拿到结构化的数据,结果一脚踩进了前端加密的坑里。页面列表看着好好的,一点开详情或者尝试翻页,浏览器地址栏没变,数据却是通过一个 POST 请求加载的,请求体里一堆看不懂的乱码字符,明显是前端做了加密处理。这场景太典型了,就是现在越来越多的网站为了“安全”和反爬虫,把核心的数据请求参数甚至整个请求体都用JavaScript加密后再发送。这不就是经典的“JS逆向”实战场吗?正好结合“JS逆向”、“表单加密”和“数据解密”这几个关键词,把这个爬虫攻防的入门案例拆解清楚。无论你是想学习JS逆向的新手,还是工作中遇到了类似加密表单无从下手的数据分析师,这个案例都能给你一套清晰的排查思路和实操解法。我们不止要找到加密位置、扣出加密代码,更要理解它为什么这么设计,以及如何用Python稳稳地复现这个流程,最终拿到我们需要的招标数据。
2. 核心思路与逆向分析前的准备
2.1 目标网站行为分析与加密定位
面对一个加密的请求,第一步永远是观察。打开浏览器开发者工具(F12),切换到“网络”(Network)选项卡,清空记录后,在目标网站点击翻页或触发数据加载。很快就能发现一个 POST 请求,它的 Request Payload (请求负载)不是常见的 form-data 或 x-www-form-urlencoded 那种键值对,而是一整段像 aBcDeFg…== 这样的Base64编码字符串,或者更直接的乱码。这就是我们的核心目标:找出这个加密字符串是如何由原始查询参数(比如页码 page 、每页大小 size 、可能有的查询关键词 keyword )生成的。
关键技巧: 不要只看一个请求。多触发几次不同条件的搜索或翻页,对比多个请求的 Payload 。你会发现,虽然字符串完全不同,但长度可能呈现规律。这能帮你初步判断是仅对参数值加密,还是对整个参数结构(如JSON字符串)进行了加密。
在“同济xxxx招标采购网”的案例中,通过对比发现,每次请求的加密字符串长度都固定为一大长串,且改变页码时字符串完全不同,这暗示了可能是对包含页码、页大小等信息的整个JSON对象进行了加密。
2.2 JS逆向环境与工具链搭建
工欲善其事,必先利其器。JS逆向不需要多么复杂的装备,但以下几样是基础:
注意: 逆向分析仅用于学习网站前端交互原理、进行合规的公开数据采集(遵守 robots.txt ,不过度频繁请求)。绝对不要用于破解、干扰网站正常服务或获取非公开、用户隐私数据。
3. 逆向实战:定位并解析加密函数
3.1 搜索与追踪加密入口
加密的发生点,通常就在发起那个 POST 请求的JavaScript代码附近。在DevTools的Network面板,找到那个加密的 POST 请求,右键点击它,选择“Copy” -> “Copy as cURL”。这能帮你看到完整的请求头,其中可能包含重要的 Referer 、 User-Agent 以及自定义的 X-Requested-With 等信息,这些在后续用Python模拟请求时需要原样带上。
更直接的方法是,在该请求的“发起者”(Initiator)一列,点击那个JS文件链接,它会直接跳转到Sources面板中发起这个网络请求的代码行。这行代码通常是 fetch() 或 XMLHttpRequest.send() 。这里就是加密发生之后、发送请求的地方。我们的目标是向上回溯,找到加密发生的地方。
实操心得: 如果“发起者”链接不明显,可以尝试在格式化后的JS文件中搜索关键URL片段(如 /api/list )或请求方法( POST )。找到发送请求的代码后,查看它发送的数据变量,比如 data 或 payload 。这个变量在被 send 之前,一定经过了某个函数的处理。
3.2 关键断点设置与逻辑分析
假设我们找到了类似 xhr.send(encryptedData)