一、拼多多反爬虫机制与 JS 逆向的必要性 拼多多的前端页面数据加载并非传统的服务端渲染,而是大量采用异步请求(AJAX)加载数据。这些异步请求的参数(如sign、token等)往往经过 JavaScript 加密处理,直接通过 Python 的requests库发送请求,会因参数无效被服务器拒绝。 例如,当我们在拼多多搜索 “手机” 时,浏览器的网络请求中会出现一个获取商品列表的接口,其请求参数包含一串加密的sign值。这个sign值是由前端 JS 根据请求参数、时间戳、固定密钥等信息计算得出的。如果无法还原这个加密过程(即 JS 逆向),就无法构造有效的请求参数,自然无法获取数据。 JS 逆向的本质,是通过分析前端 JavaScript 代码,还原其数据加密、参数生成的逻辑,再将该逻辑用 Python 或其他语言复现,从而构造出符合服务器要求的请求。对于拼多多这类平台,入门级的 JS 逆向主要聚焦于参数加密逻辑的还原,这也是本文的核心内容。 二、JS 逆向的基础步骤(以拼多多商品接口为例) 步骤 1:抓包分析请求参数 首先需要使用浏览器的开发者工具(Chrome/Firefox 的 F12)抓取目标接口的请求信息。以拼多多网页版商品列表接口为例:
- 打开拼多多网页版,搜索 “手机”;
- 打开开发者工具的「Network」标签,筛选「XHR/Fetch」类型的请求;
- 找到商品列表对应的接口(如/api/search/get),查看其请求参数和响应数据。 此时会发现,请求参数中包含page(页码)、keyword(关键词)、timestamp(时间戳)、sign(签名)等参数,其中sign是加密后的字符串,也是我们需要逆向的核心。 步骤 2:定位加密 JS 代码 找到sign参数的生成逻辑,是 JS 逆向的关键。常用方法有两种:
- 全局搜索:在开发者工具的「Sources」标签中,使用快捷键Ctrl+Shift+F搜索sign或sign=,定位到包含该参数生成的 JS 代码段;
- 断点调试:在请求发起的代码处设置断点,逐步执行代码,观察sign参数的生成过程。
拼多多的前端代码经过了压缩混淆,但入门级的加密逻辑往往不会过于复杂。我们可以通过观察代码中的加密函数(如 MD5、SHA256 等哈希函数,或自定义的拼接加密),确定sign的生成规则。
步骤 3:还原加密逻辑
找到加密代码后,需要理解其逻辑并记录关键信息:
● 加密所使用的算法(如 MD5);
● 参与加密的参数顺序(如timestamp+keyword+page+密钥);
● 固定密钥(可能是硬编码在 JS 中的字符串,如pdd_123456)。
例如,假设拼多多某接口的sign生成逻辑为:将timestamp、keyword、page和固定密钥pdd_secret按顺序拼接,再进行 MD5 加密得到小写字符串。我们需要将这一逻辑准确还原。
步骤 4:Python 复现加密逻辑
将还原的 JS 加密逻辑用 Python 代码实现,生成对应的sign参数,再构造 HTTP 请求获取数据。
三、代码实现:拼多多商品数据抓取的 JS 逆向案例
前置说明
本文案例中的接口和加密逻辑为拼多多入门级模拟场景(因拼多多真实加密逻辑会持续更新,且涉及平台合规性,此处采用简化的模拟逻辑),核心是演示 JS 逆向的流程。实际场景中,需结合具体抓包结果调整逻辑。
步骤 1:抓包与 JS 加密逻辑分析(模拟)
假设抓包得到的请求参数为:
这段代码的逻辑是:将请求参数按名升序排序,拼接参数名和值,再拼接固定密钥,最后 MD5 加密得到sign。 步骤 2:Python 复现加密逻辑 首先安装所需依赖: 然后编写 Python 代码,实现参数拼接、MD5 加密,并构造请求:{ "keyword": "手机", "page": 1, "timestamp": 1718000000000, "sign": "a1b2c3d4e5f67890abcdef1234567890" } 通过全局搜索和断点调试,找到 JS 加密代码如下(压缩后的简化版): javascript 运行 function generateSign(params, secret) { // 1. 按参数名升序排序 let sortedKeys = Object.keys(params).sort(); let str = ''; // 2. 拼接参数名和值 for (let key of sortedKeys) { str += key + params[key]; } // 3. 拼接固定密钥 str += secret; // 4. MD5加密并转小写 return md5(str).toLowerCase(); } // 调用示例: let params = { keyword: "手机", page: 1, timestamp: 1718000000000 }; let secret = "pdd_2024_secret"; // 固定密钥 let sign = generateSign(params, secret);import requests import hashlib import time
def generate_sign(params, secret): """ 复现JS的sign生成逻辑 :param params: 请求参数字典 :param secret: 固定密钥 :return: 加密后的sign """ # 1. 按参数名升序排序 sorted_keys = sorted(params.keys()) str_temp = '' # 2. 拼接参数名和值 for key in sorted_keys: str_temp += key + str(params[key]) # 3. 拼接固定密钥 str_temp += secret # 4. MD5加密并转小写 md5_obj = hashlib.md5() md5_obj.update(str_temp.encode('utf-8')) sign = md5_obj.hexdigest().lower() return sign
def get_pdd_goods(keyword, page): """ 获取拼多多商品数据 :param keyword: 搜索关键词 :param page: 页码 :return: 商品数据 """ # 固定配置 url = "https://api.pinduoduo.com/api/search/get" # 模拟接口,实际需替换为真实接口 secret = "pdd_2024_secret" # 从JS中提取的固定密钥 # 构造基础参数 timestamp = int(time.time() * 1000) # 生成当前时间戳(毫秒) params = { "keyword": keyword, "page": page, "timestamp": timestamp } # 生成sign参数 sign = generate_sign(params, secret) params["sign"] = sign # 将sign加入参数
# 发送请求
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Referer": "https://www.pinduoduo.com/",
"Cookie": "" # 实际场景中需添加抓包得到的Cookie
}
# 配置代理信息
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"
# 构建代理URL(支持HTTP和HTTPS)
proxy_url = f"http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}"
proxies = {
"http": proxy_url,
"https": proxy_url
}
try:
# 发送请求时添加proxies参数
response = requests.get(url, params=params, headers=headers, proxies=proxies)
if response.status_code == 200:
return response.json()
else:
print(f"请求失败,状态码:{response.status_code}")
return None
except Exception as e:
print(f"请求异常:{e}")
return None主函数调用
if name == "main": goods_data = get_pdd_goods("手机", 1) if goods_data: print("获取的商品数据:") print(goods_data) else: print("未获取到商品数据")
``` 代码说明
- generate_sign 函数:完全复现了 JS 中的加密逻辑,包括参数排序、拼接、MD5 加密;
- get_pdd_goods 函数:构造请求参数,生成sign,发送 HTTP 请求并返回数据;
- 注意事项:实际场景中,url需要替换为抓包得到的真实接口,Cookie需要添加浏览器中的有效 Cookie,secret需要从真实 JS 代码中提取。 四、JS 逆向的进阶与合规性说明
- 进阶挑战 拼多多的真实 JS 代码会采用代码混淆(如变量名混淆、控制流平坦化)、动态密钥(密钥从服务器获取,而非硬编码)、浏览器指纹验证(如验证 User-Agent、Canvas 指纹)等手段,增加逆向难度。此时需要掌握: ● 使用ast模块解析混淆后的 JS 代码; ● 使用execjs库直接执行 JS 代码(避免手动复现); ● 模拟浏览器环境(如使用 Selenium、Playwright)绕过指纹验证。
- 合规性重要提醒 本文的案例仅用于技术学习,抓取拼多多数据需遵守平台的《用户协议》和《robots.txt》规则,不得用于商业用途或恶意攻击。根据《中华人民共和国网络安全法》和《反不正当竞争法》,未经授权的大规模数据抓取可能涉嫌违法违规。 五、总结 本文以拼多多数据抓取为例,讲解了 Python 爬虫中 JS 逆向的基础流程:抓包分析参数→定位加密 JS 代码→还原加密逻辑→Python 代码复现。对于入门者而言,核心是理解 JS 逆向的本质是逻辑还原,而非单纯的代码编写。 在实际应用中,JS 逆向的难度会随着平台反爬虫技术的升级而增加,但基础思路始终不变。同时,必须牢记合规性原则,将技术用于合法的场景中。通过本文的案例,希望能帮助入门者迈出 JS 逆向的第一步,为后续的爬虫开发和数据分析工作打下基础。

