在当今的网络爬虫领域JS加密已经成为网站最常用的反爬手段之一。从简单的MD5哈希到复杂的AES对称加密再到高度混淆的自定义算法网站开发者们不断升级加密技术来保护数据安全。对于爬虫工程师而言掌握JS加密的破解方法已经成为一项必备技能。本文将带你从原理到实战系统地学习如何分析、破解JS参数加密并实现稳定的请求模拟。一、JS加密反爬的核心原理与常见类型1.1 为什么网站使用JS加密反爬传统的反爬手段如User-Agent检测、IP限制、Cookie验证等已经被爬虫工程师们研究得非常透彻很容易被绕过。而JS加密反爬则将关键的参数生成逻辑放在客户端执行服务器只验证加密后的结果这大大增加了爬虫的难度。具体来说JS加密反爬的优势在于加密逻辑动态变化难以一次性破解每个请求都需要生成唯一的加密参数可以结合时间戳、随机数等防止重放攻击混淆后的JS代码可读性极差增加分析成本1.2 常见的JS加密类型目前主流的JS加密可以分为以下几类加密类型代表算法特点常见应用场景哈希加密MD5、SHA1、SHA256单向不可逆相同输入产生相同输出生成签名、校验数据完整性对称加密AES、DES、3DES加密解密使用相同密钥速度快加密请求体、响应体非对称加密RSA公钥加密私钥解密安全性高传输对称密钥、登录密码加密自定义加密网站自行实现的算法无标准可循破解难度最大生成关键请求参数如sign、token二、JS参数加密破解的完整流程破解JS参数加密是一个系统性的过程需要遵循一定的步骤和方法。下面是我总结的通用破解流程抓包分析请求识别加密参数搜索关键词定位JS文件断点调试找到加密函数分析加密逻辑提取加密代码测试加密函数复现加密逻辑构造请求参数模拟请求获取数据2.1 抓包分析与参数识别破解的第一步是使用抓包工具分析网站的请求。推荐使用Chrome浏览器自带的开发者工具F12它功能强大且使用方便。具体操作步骤打开Chrome开发者工具切换到Network面板勾选Preserve log选项防止页面刷新时日志丢失刷新页面或触发目标操作找到对应的API请求查看Request Headers和Form Data识别出哪些参数是加密的通常命名为sign、token、signature、_sign等关键技巧对比多次请求的参数找出变化的参数。不变的参数通常不需要处理而变化的参数就是我们需要破解的目标。2.2 定位加密函数位置找到加密参数后下一步就是定位生成这些参数的JS函数。常用的方法有方法一全局搜索关键词在Chrome开发者工具的Sources面板中使用快捷键CtrlShiftF打开全局搜索搜索加密参数的名称。例如如果加密参数是sign就搜索sign、“sign:”、sign(等。方法二XHR断点如果加密参数是在AJAX请求中发送的可以使用XHR断点来定位。在Sources面板的XHR/fetch Breakpoints中添加断点输入API请求的部分URL。当请求发送时代码会在发送前中断此时可以查看调用栈找到加密函数的位置。方法三事件断点如果加密参数是在点击按钮等事件触发时生成的可以使用事件断点。在Sources面板的Event Listener Breakpoints中展开Mouse勾选click。当点击按钮时代码会中断然后逐步调试找到加密函数。2.3 分析加密逻辑与提取代码找到加密函数后就需要分析它的逻辑。这是整个破解过程中最困难的部分尤其是当JS代码被混淆时。常用的调试技巧在加密函数的入口处设置断点逐步执行代码F10观察变量的变化使用Watch面板监控关键变量的值使用Call Stack面板查看函数调用关系使用Scope面板查看当前作用域的变量如果JS代码被混淆了可以使用一些工具进行反混淆比如js-beautify、deobfuscator等。但需要注意的是有些混淆技术非常复杂反混淆工具可能无法完全还原代码这时候就需要耐心地手动分析。2.4 复现加密逻辑分析完加密逻辑后就需要在我们的爬虫代码中复现这个过程。有两种常用的方法方法一使用Python直接复现如果加密逻辑比较简单比如只是MD5哈希或者简单的字符串拼接可以直接用Python代码复现。这种方法执行速度快不需要依赖外部环境。方法二使用Node.js调用原JS代码如果加密逻辑比较复杂或者使用了一些JS特有的函数直接用Python复现会非常困难。这时候可以使用Node.js来执行原JS代码然后通过Python调用Node.js获取加密结果。三、实战案例破解某电商网站的sign参数为了让大家更好地理解整个过程下面我将以一个实际的电商网站为例详细演示如何破解sign参数加密。3.1 抓包分析首先我们打开目标网站使用Chrome开发者工具抓包。找到商品列表的API请求查看请求参数https://api.example.com/goods/list ?page1 size20 timestamp1650000000000 nonceabcdef123456 sign7b2c8a9d0e1f3b5c7e9a2b4d6f8c0a1e可以看到请求参数中有timestamp时间戳、nonce随机数和sign签名三个动态参数。我们的目标就是破解sign参数的生成逻辑。3.2 定位加密函数我们使用全局搜索功能搜索sign很快就找到了相关的JS代码functiongenerateSign(params){varkeysObject.keys(params).sort();varstr;for(vari0;ikeys.length;i){strkeys[i]params[keys[i]];}strstr.substring(0,str.length-1);strsecret_keyabcdefghijklmnopqrstuvwxyz123456;returnmd5(str).toUpperCase();}3.3 分析加密逻辑通过分析代码我们可以看出sign参数的生成逻辑是将所有请求参数按键名排序按照keyvalue的格式拼接成字符串在字符串末尾拼接上固定的密钥secret_keyabcdefghijklmnopqrstuvwxyz123456对拼接后的字符串进行MD5哈希将结果转换为大写3.4 Python复现加密逻辑现在我们可以用Python代码来复现这个加密逻辑importhashlibimporttimeimportrandomimportstringdefgenerate_sign(params,secret_key):# 按键名排序sorted_keyssorted(params.keys())# 拼接参数str_list[]forkeyinsorted_keys:str_list.append(f{key}{params[key]})sign_str.join(str_list)# 拼接密钥sign_strfsecret_key{secret_key}# MD5哈希并转大写md5hashlib.md5()md5.update(sign_str.encode(utf-8))returnmd5.hexdigest().upper()# 生成随机noncedefgenerate_nonce(length12):return.join(random.choices(string.ascii_lettersstring.digits,klength))# 生成时间戳defgenerate_timestamp():returnstr(int(time.time()*1000))# 测试if__name____main__:params{page:1,size:20,timestamp:generate_timestamp(),nonce:generate_nonce()}secret_keyabcdefghijklmnopqrstuvwxyz123456signgenerate_sign(params,secret_key)params[sign]signprint(params)3.5 模拟请求有了加密参数的生成方法我们就可以模拟请求获取数据了importrequestsdefget_goods_list(page1,size20):base_urlhttps://api.example.com/goods/listparams{page:str(page),size:str(size),timestamp:generate_timestamp(),nonce:generate_nonce()}secret_keyabcdefghijklmnopqrstuvwxyz123456params[sign]generate_sign(params,secret_key)headers{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36,Referer:https://www.example.com/,Accept:application/json, text/plain, */*}responserequests.get(base_url,paramsparams,headersheaders)ifresponse.status_code200:returnresponse.json()else:print(f请求失败状态码{response.status_code})returnNone# 测试if__name____main__:goods_listget_goods_list(page1,size20)ifgoods_list:print(goods_list)四、高级技巧与常见问题解决4.1 处理混淆的JS代码很多网站会对JS代码进行混淆使其变得难以阅读。常见的混淆技术包括变量名和函数名替换为无意义的字符字符串加密控制流扁平化死代码注入对于混淆的JS代码我们可以使用以下方法处理使用反混淆工具进行初步处理逐步调试理解关键部分的逻辑提取核心加密函数忽略无关的混淆代码使用AST抽象语法树分析工具辅助分析4.2 处理动态生成的JS代码有些网站会动态生成JS代码每次请求都会返回不同的代码。这时候我们需要每次请求都获取最新的JS代码分析JS代码的生成规律找出不变的部分使用正则表达式提取关键的加密逻辑使用Node.js的vm模块动态执行JS代码4.3 处理反调试技术为了防止开发者调试JS代码很多网站会加入反调试技术比如检测开发者工具是否打开无限debugger检测断点应对方法使用浏览器插件禁用反调试在代码中找到反调试的部分手动删除或修改使用无头浏览器如Puppeteer、Playwright来绕过反调试4.4 处理RSA非对称加密如果网站使用RSA非对称加密我们需要找到网站使用的公钥使用Python的rsa库或pycryptodome库进行加密注意公钥的格式通常是PEM格式或PKCS#8格式五、注意事项与法律风险在进行爬虫开发时我们必须遵守法律法规和道德规范不要爬取敏感信息和个人隐私数据遵守网站的robots.txt协议控制爬取频率避免对服务器造成过大压力不要将爬取的数据用于商业用途如果网站明确禁止爬虫就不要强行爬取六、总结JS加密反爬是爬虫领域的一个重要课题需要我们不断学习和实践。本文介绍了JS加密的常见类型、破解流程和实战案例希望能帮助大家掌握这项技能。需要注意的是网站的反爬技术也在不断升级没有一劳永逸的破解方法。作为爬虫工程师我们需要保持学习的热情不断提升自己的技术水平同时也要遵守法律法规做一个负责任的开发者。 点击我的头像进入主页关注专栏第一时间收到更新提醒有问题评论区交流看到都会回。