Shopee商品详情页反爬实战:手把手逆向x-sap-Ri和x-sap-Sec参数(附完整调试过程)
Shopee商品详情页反爬实战逆向x-sap-Ri与x-sap-Sec参数全解析在电商数据采集领域Shopee作为东南亚头部平台其反爬机制一直以动态加密著称。最近更新的x-sap-Ri和x-sap-Sec参数组合通过浏览器环境检测与请求特征加密的双重防护给爬虫开发者带来了新的挑战。本文将带您深入Shopee的JS加密核心从内存漫游技巧到AST还原算法完整拆解这两个关键参数的生成逻辑。1. 逆向环境准备与加密定位逆向Shopee的加密参数需要配置专业的调试环境。推荐使用Chromium内核浏览器版本≥102配合开发者工具同时禁用所有浏览器扩展以避免干扰。在控制台执行以下命令确保环境纯净// 清除浏览器缓存和存储 await Promise.all([ caches.keys().then(keys Promise.all(keys.map(key caches.delete(key)))), indexedDB.databases().then(dbs Promise.all(dbs.map(db indexedDB.deleteDatabase(db.name)))), localStorage.clear(), sessionStorage.clear() ]);通过XHR断点定位加密入口时建议优先拦截包含sap关键字的请求头。在Chrome DevTools的Sources面板添加以下断点条件url.includes(/api/v) (requestHeaders[x-sap-ri] || requestHeaders[x-sap-sec])内存漫游(Memory Travel)是另一种高效定位方式。在控制台执行window.__sapHook或搜索getGlobalFetch关键字通常会跳转到名为sap-hook.prod.js的加密入口文件。这个约3MB的混淆JS文件包含了核心加密逻辑。2. x-sap-Ri参数逆向分析x-sap-Ri参数实质上是浏览器环境特征的加密摘要其生成过程涉及多个关键步骤环境数据采集包括但不限于Canvas指纹通过toDataURL提取WebGL渲染器特征AudioContext频率分析屏幕分辨率与色深时区与语言设置数据归一化处理采集的原始数据会经过如下转换function normalize(data) { const encoder new TextEncoder(); return encoder.encode( JSON.stringify(data) .replace(/\s/g, ) .toLowerCase() ); }多层哈希运算采用SHA-256与自定义混淆算法组合# Python模拟计算过程 import hashlib def generate_ri(env_data): first_hash hashlib.sha256(env_data).digest() second_hash hashlib.sha256(first_hash bshopee_salt).digest() return second_hash.hex()[:32]实际逆向时会发现Shopee在Web Worker中执行了额外的混淆操作包括数组元素随机置换浮点数精度干扰时间戳熵值混合3. x-sap-Sec参数生成机制x-sap-Sec是动态请求签名参数与请求内容和时间戳强相关。其核心生成逻辑包含三个部分组件数据来源加密方式时间因子当前UTC时间戳AES-128-CBC请求特征URL路径查询参数HMAC-SHA384设备指纹浏览器硬件ID自定义XOR完整的生成流程如下提取请求关键特征const requestSig { method: GET, path: /api/v4/pdp/get_pc, query: shop_id959486238item_id24061417711, body: null };时间戳加密处理from Crypto.Cipher import AES from Crypto.Util.Padding import pad def encrypt_timestamp(ts): key bfixed_key_16bytes iv ts[-16:].encode() cipher AES.new(key, AES.MODE_CBC, iv) return cipher.encrypt(pad(ts.encode(), 16))最终签名合成function finalSign(timestampEnc, requestHash, deviceId) { const buffer new Uint8Array(64); // 前16字节存放时间加密结果 buffer.set(timestampEnc.slice(0, 16), 0); // 中间32字节存放请求特征哈希 buffer.set(requestHash, 16); // 最后16字节设备指纹异或结果 buffer.set(xor(deviceId, timestampEnc.slice(16)), 48); return btoa(String.fromCharCode(...buffer)); }4. 反反爬实战技巧面对Shopee的动态检测机制需要特别注意以下防护点内存陷阱检测Shopee会验证关键函数是否被Hookconst isHooked (fn) fn.toString() ! Function.prototype.toString.call(fn);调试器检测通过debugger语句和性能差判断function checkDebugger() { const start performance.now(); (function(){})(); return performance.now() - start 100; }环境一致性验证包括但不限于navigator.webdriver属性Chrome运行时标志插件列表特征推荐使用以下规避方案使用Object.defineProperty重定义关键属性Object.defineProperty(navigator, webdriver, { get: () false, configurable: true });注入合法的时间抖动import random import time def random_delay(): time.sleep(random.uniform(0.8, 1.2))模拟真实用户操作轨迹// 模拟鼠标移动轨迹 const moveMouse async (el) { const { x, y } el.getBoundingClientRect(); const steps 10; for (let i 0; i steps; i) { window.dispatchEvent(new MouseEvent(mousemove, { clientX: x * (i/steps), clientY: y * (i/steps), bubbles: true })); await new Promise(r setTimeout(r, 50)); } };5. 完整参数生成方案实现基于Node.js的实现参考需安装crypto-js和puppeteerconst CryptoJS require(crypto-js); const puppeteer require(puppeteer-extra); const StealthPlugin require(puppeteer-extra-plugin-stealth); puppeteer.use(StealthPlugin()); async function generateShopeeParams(itemUrl) { const browser await puppeteer.launch({ headless: false }); const page await browser.newPage(); // 环境伪装设置 await page.setViewport({ width: 1366, height: 768 }); await page.setUserAgent(Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...); // 注入加密Hook监听 await page.exposeFunction(getEncryptedParams, (ri, sec) ({ ri, sec })); await page.goto(itemUrl, { waitUntil: networkidle2 }); // 获取加密参数 const params await page.evaluate(async () { return new Promise(resolve { const observer new PerformanceObserver(list { const entries list.getEntries(); for (const entry of entries) { if (entry.name.includes(/api/v4/pdp)) { window.getEncryptedParams( entry.requestHeaders[x-sap-ri], entry.requestHeaders[x-sap-sec] ).then(resolve); } } }); observer.observe({ type: resource, buffered: true }); }); }); await browser.close(); return params; } // 使用示例 generateShopeeParams(https://shopee.co.id/product/959486238/24061417711) .then(console.log);对于大规模采集需求建议采用分布式浏览器集群方案每个实例配置不同的硬件指纹和网络环境。以下是指纹配置表示例{ fingerprint: { os: windows, browser: chrome, device: desktop, screen: 1366x768, fonts: [Arial, Times New Roman], canvas: { noise: 0.5, entropy: 120 }, webgl: { vendor: Google Inc., renderer: ANGLE (NVIDIA GeForce GTX 1060) } }, network: { proxy: residential, latency: 150, jitter: 50 } }在实际项目中我们发现Shopee的加密参数每4-6小时会更新算法细节特别是盐值(salt)和密钥轮换机制。维护一个可持续的采集系统需要建立算法版本检测和自动适配机制这通常需要结合AST解析和动态规则引擎来实现。