十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

樱花动漫反爬实战:JS逆向动态Cookie与字体加密拆解

樱花动漫反爬实战:JS逆向动态Cookie与字体加密拆解 干了5年逆向头一回被樱花动漫反爬恶心到一次 JS 反爬实战拆解这次说的不是某个开源项目也不是某个新模型而是很多爬虫工程师和逆向爱好者都会遇到的一个真实场景网页反爬。最近有朋友在练习 JS 逆向时连续几天卡在一个动漫站点的反爬机制上用他的原话是“干了5年逆向头一回被樱花动漫反爬恶心到”。这里的“樱花动漫”不是指某个具体公司而是某类套壳动漫资源站的统称技术上最有代表性的是一个叫chameleon的反爬 JS 文件。先说结论这类站点反爬不是靠 IP 封禁也不是靠简单 UA 校验而是把 Cookie 生成逻辑、字体映射、行为检测全部塞进一段加密混淆的 JS 里。你直接请求页面拿不到真实数据必须先把这段 JS 跑起来生成正确的动态 Cookie再带上去请求数据接口。这个思路在 JS 逆向里非常典型值得用一篇文章完整拆解。这篇文章会分成几个部分先看这个反爬的核心能力点和硬件环境要求再给出一套本地调试的完整流程包括如何定位关键 JS 文件、如何用 Node.js 补环境、如何验证 Cookie 有效性最后是一份常见问题排查清单和合规提醒。文章适合以下读者正在学 JS 逆向、想搞懂动态 Cookie 生成逻辑的爬虫工程师需要和反爬对抗做数据采集的安全测试人员以及准备做反爬研究和授权范围内风险验证的同学。1. 核心能力速览先把这次逆向分析涉及的关键信息整理成表格方便快速判断这个靶场值不值得花时间。能力项说明靶场类型JS 反爬 动态 Cookie 字体加密核心反爬文件chameleon系列 JS 文件关键机制动态 Cookie 生成、字体映射替换、行为轨迹校验调试工具Chrome DevTools、Fiddler/Charles、Node.js语言环境Python 3.8、Node.js 14数据库支持无强制要求必选 Node.js 运行时启动方式本地调试脚本 浏览器开发者工具联动是否支持 API本质是网页数据接口可直接构造请求是否支持批量任务支持需解决 Cookie 批量刷新和并发控制适合场景JS 逆向学习、接口数据采集、反爬机制研究从材料看这类反爬技术栈并不复杂但恶心之处在于混淆程度高、动态变化频繁。你需要花大量时间在补环境、调试签名、验证 Cookie 上而不是业务逻辑本身。2. 适用场景与使用边界2.1 这是什么场景这类反爬主要出现在资源型站点比如动漫站、影视站、图库站。它们通常使用一套通用源码比如苹果CMS、海洋CMS等然后再叠加一层自定义的 JS 反爬。chameleon就是典型的自定义层。它的防御逻辑通常分三层首次访问页面时服务端返回一段加密 JS 和一道验证逻辑。浏览器执行这段 JS生成一个动态 Cookie 字段。后续所有数据接口请求都必须携带这个 Cookie否则返回假数据或直接拒绝。2.2 适合谁想练习 JS 逆向的爬虫工程师尤其是动态 Cookie 生成和补环境方向。已经能处理一般字体反爬想进阶到行为检测和混淆对抗的开发者。做授权范围内的站点风险评估、安全审计的技术人员。2.3 不适合谁对 JavaScript 完全零基础的读者建议先补 JS 基础。想要现成“秒杀”脚本的读者这类反爬变化很快今天能用的脚本明天就可能失效更重要的是理解原理。试图爬取受版权保护内容并用于商用的场景这个必须明确拒绝。2.4 合规边界这里必须强调一条红线任何反爬分析和数据采集都必须在网站授权范围内进行。你只能对自己拥有、或已获得测试许可的站点做分析。不要用这套方法去爬文字、图片、动漫、影视等版权内容更不要批量抓取后二次分发。技术本身是中性的但使用边界决定了它是否合规。本文所有示例均为靶场环境实际应用时请确认授权。3. 环境准备与前置条件开始逆向之前先把环境准备好。3.1 操作系统Windows 10/11、macOS、Linux 均可以。后面所有调试主要依赖浏览器和 Node.js跨平台没有障碍。3.2 软件依赖工具用途建议版本Chrome 或 Chromium 内核浏览器抓包、断点调试、观察请求最新稳定版Fiddler Classic 或 Charles移动端或自定义协议抓包建议 Fiddler 5.xNode.js运行补环境脚本14 或 16Python 3.8写请求调度和批量验证脚本3.8任意文本编辑器JS 格式化、对比分析VS Code 最佳3.3 浏览器调试能力这个环节最关键建议先确认自己的 Chrome DevTools 熟练度能看懂 Network 面板的请求列表和响应预览。会使用 Source 面板打断点、单步执行。知道如何在 Console 里执行 JS 函数并查看变量。如果这些还不太熟先花半小时熟悉 DevTools再往下看。3.4 磁盘和内存这个场景不涉及模型文件磁盘占用很小。主要内存消耗在浏览器 DevTools 和 Node.js 进程上建议内存 8GB 以上避免调试时卡顿。4. 定位与启动找到chameleon反爬 JS这里说的“启动”不是启动某个服务而是启动一段调试链路浏览器加载页面 - 定位反爬 JS - 提取逻辑 - 本地运行。4.1 第一步打开浏览器开发者工具观察网络请求访问靶场页面后先不要滚动页面直接按 F12 打开 DevTools切到 Network 面板勾选 Preserve log保留请求日志再刷新页面。观察重点首个 HTML 请求的响应内容。响应体里是否包含内联 JS 或外部 JS 文件引用。有没有出现多个 Cookie Set 标志。材料里提到chameleon这个反爬 JS通常会在 HTML 中直接引用或者由一个外层 JS 动态加载。按文件名搜索chameleon或按 JS 文件类型过滤应能快速定位。4.2 第二步格式化混淆 JS定位到 JS 文件后点击文件进入 Source 面板然后点击左下角的{}按钮格式化代码。格式化后可以看到大结构。一般来说chameleon型反爬 JS 的主要模块包括// 伪代码示例实际文件高度混淆 var chameleon { _0x4b2c: function(key, data) { // 加密/混淆逻辑 }, _0x9f7e: function() { // Cookie 生成逻辑 } };这类代码乱码很正常不要试图逐行读懂先找关键输出点。4.3 第三步搜索 Cookie 字段名如何快速定位关键位置在格式化后的代码里搜索 Cookie 的关键标识。常见操作// 在 DevTools Console 中执行 document.cookie如果页面已经通过反爬验证此时能看到类似如下的 Cookie 字段v_codeabc123def456; path/; expires...然后在 Sources 里用 CtrlShiftF 全局搜索v_code就能找到赋值入口。这个赋值语句附近就是核心加密逻辑。4.4 第四步打断点观察执行过程在赋值语句行号上点击打断点然后刷新页面。代码执行到断点时会暂停此时可以在 Scope 面板里查看所有局部变量和参数。这一步可以直观看到加密前的原始数据是什么。加密函数接收了哪些参数。返回结果和 Cookie 值的关系。5. JS 逆向分析与补环境让脚本在 Node.js 中跑起来定位到反爬逻辑后下一步就是把它搬到本地环境运行。这一步通常是新手最痛苦的环节因为浏览器环境里有window、document、navigator等对象而 Node.js 里没有。5.1 先区分纯算法和浏览器环境观察提取出来的代码。如果只是数学运算、字符串拼接、数组操作这类逻辑在 Node.js 里直接能跑。但只要是引用了windowdocumentnavigatorlocationcanvasWebAssembly就必须补环境。很多chameleon型反爬会借用浏览器指纹信息比如navigator.userAgent、navigator.webdriver、canvas指纹。这些值在浏览器里能拿到Node.js 里拿不到需要手动定义。5.2 最小补环境方案不建议一开始就上 puppeteer 之类的自动化浏览器太重了。先用最小补环境方案// env.js - 最小浏览器环境模拟 const fs require(fs); // 模拟 window global.window global; // 模拟 navigator global.navigator { userAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36, platform: Win32, language: zh-CN, languages: [zh-CN, zh] }; // 模拟 document global.document { cookie: , getElementById: function() { return { innerText: , innerHTML: }; }, querySelector: function() { return { getAttribute: function() { return ; } }; }, createElement: function() { return { getContext: function() { return null; }, style: {} }; } }; // 模拟 location global.location { href: https://example-protected.com/, hostname: example-protected.com, origin: https://example-protected.com };这里用example-protected.com代指靶场域名实际分析时替换为授权靶场的真实地址。保存为env.js然后用 Node.js 加载。5.3 把提取的算法放入 Node.js 执行假设格式化后的核心代码是一个独立的函数本地布置如下// solve_cookie.js require(./env.js); const fs require(fs); // 将浏览器里提取的算法文件粘贴到同目录 const chameleonCode fs.readFileSync(./chameleon_extracted.js, utf-8); eval(chameleonCode); // 执行生成 Cookie 的函数函数名需要根据实际反混淆结果调整 const result global.getCookie global.getCookie(); console.log(Cookie 结果:, result);注意有些反爬 JS 会用 eval 或 Function 动态执行代码在 Node.js 里也不受影响。关键是保证window、document等对象不报错。如果报变量未定义就回到浏览器里看这个变量从哪里来然后继续补。5.4 验证 Cookie 是否有效生成的 Cookie 最终要放到请求中验证。import requests url https://example-protected.com/api/catalog headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36, Cookie: v_code这里替换成生成的Cookie值 } response requests.get(url, headersheaders, timeout15) # 状态码 200 且内容包含正常数据说明 Cookie 已通过校验 print(response.status_code) print(response.text[:500])判断标准返回 JSON 数据且字段完整说明动态 Cookie 已生效。返回空内容、跳转、或错误提示说明 Cookie 生成逻辑还有问题。返回 HTML 而不是 JSON可能没有请求到正确的数据接口。6. 字体加密与字符映射分析chameleon类反爬的另一个恶心点在于字体加密。站点会把数字或关键字映射成自定义字体浏览器加载字体文件后正常显示但直接拿接口返回的文本是乱码。这就需要第二层处理字体文件解析和字符映射还原。6.1 识别字体加密正常请求数据接口后如果返回内容是类似这样的文本欢迎来到 煻果动漫 站其中“煻”“果”是自定义字体字符需要建立映射表才能还原真实文本。常见的字体文件类型是 woff/woff2。在 Network 面板中筛选font类型的请求即可定位。6.2 解析字体文件字体文件下载后可以通过fonttools库提取字体中的 glyph 到 unicode 的映射。pip install fonttoolsfrom fontTools.ttLib import TTFont font TTFont(./toolbox_font.woff) cmap font.getBestCmap() for key, value in list(cmap.items())[:10]: unicode_char chr(key) print(funicode: {key}, char: {unicode_char}, glyph_name: {value})然后使用可信的对照样本比如从页面直接复制的字符和其真实值推断映射关系生成替换字典。在实际分析中建议准备多组对照样本提高映射精度。6.3 接入数据清洗字体映射表生成后在 Python 解析接口数据时做一层字符替换font_map { 煻: 樱, 果: 花 } def replace_font_chars(text): for source, target in font_map.items(): text text.replace(source, target) return text这套方案在动漫、影视、小说类站点里很通用逻辑不难难点在动态字体会定期更换映射表需要重复提取。7. 接口批量任务与反爬压力测试动态 Cookie 和字体加密都解决后批量任务才能真正跑起来。7.1 Cookie 过期与批量刷新策略动态 Cookie 往往有时效性可能是几分钟、几十分钟甚至单次有效。批量任务时先做一次完整反爬获取 Cookie然后在任务中轮询import time import requests class ChameleonClient: def __init__(self, base_url): self.base_url base_url self.session requests.Session() self.cookie_expired_at 0 self.refresh_cookie() def refresh_cookie(self): # 这里调用 Node.js 生成的 cookie 值 cookie_value self._gen_cookie_via_node() self.session.cookies.set(v_code, cookie_value) self.cookie_expired_at time.time() 600 def get(self, path): if time.time() self.cookie_expired_at: self.refresh_cookie() return self.session.get(self.base_url path, timeout15) client ChameleonClient(https://example-protected.com) for page in range(1, 11): response client.get(f/api/catalog?page{page}) data response.json() # 处理数据 time.sleep(1)核心逻辑是维护一个过期时间直到任务完成前都不需要再手动干预 Cookie。7.2 并发控制批量任务不要一上来就开几十个线程。先测试单个请求的耗时和 Cookie 有效期再逐步增加并发数。推荐控制策略初始化阶段使用单线程获取 Cookie。数据抓取阶段使用 3 到 5 个线程每个线程复用同一个 Session。遇到限流、验证码、空数据时暂停任务并刷新 Cookie。7.3 失败重试每个请求增加重试机制def fetch_with_retry(client, path, retries3): for i in range(retries): try: resp client.get(path) if resp.status_code 200 and error not in resp.text: return resp.json() except Exception: pass time.sleep(2) return None8. 资源占用与性能观察这个环节是很多视频演示会重点讲的这里转换成工程化观察方式。8.1 CPU 和内存观察JS 逆向分析时主要资源消耗在浏览器和 Node.js 上。浏览器 DevTools 如果一直打开内存占用可能到 1GB 以上。Node.js 跑混淆 JS 时CPU 占用通常在 10% 到 50% 之间取决于脚本复杂度。如果脚本里包含大量循环或递归CPU 可能瞬间飙到 100%属正常现象不需要接管等输出即可。8.2 接口请求延迟批量任务时建议在请求代码里记录耗时start time.time() resp client.get(f/api/catalog?page{page}) cost time.time() - start print(fpage {page} cost {cost:.2f}s)动态 Cookie 类反爬的接口延迟一般在 0.3 到 2 秒之间。如果超过 5 秒优先检查网络情况而不是继续加并发。8.3 降低资源消耗如果本地调试时资源占用过高可以使用 Chrome DevTools 的 Network 面板时不要一直开着性能监视。Node.js 脚本运行完成及时退出。批量请求使用requests.Session复用 TCP 连接。不要每次请求都刷新 Cookie维护过期时间即可。9. 常见问题与排查方法下面是 JS 反爬调试过程中最常见的 7 个问题及排查思路。问题现象可能原因排查方式解决方案补环境后 Node.js 报window is not defined没有定义全局 window检查 env.js 是否在算法代码之前加载在 env.js 中执行global.window global生成 Cookie 后请求仍被拒绝Cookie 生成时间或字段不对对比浏览器生成的 Cookie 字段名和值调整字段名确认包含所有必要属性请求返回假数据或空数据字体加密未处理检查返回内容中是否存在自定义 unicode 字符提取字体文件并建立映射表反爬 JS 无法格式化代码使用控制流平坦化手动搜索关键字符如cookie、set使用反混淆工具或二分定位法字体映射表动态变化字体文件定期更换观察字体文件名是否带时间戳建立字体指纹到映射表的缓存批量任务频繁超时并发过高或 Cookie 过期查看日志区分限流和超时降低并发增加随机等待时间页面能访问但接口不能访问数据接口有单独校验在 Network 面板对比页面请求和接口请求头差异补齐 Referer、Origin、Content-Type 等请求头10. 最佳实践与使用建议10.1 调试阶段先不追求全流程通跑。分阶段验证第一步浏览器里手动完成反爬验证确认请求能返回正常数据。第二步把页面上生成的 Cookie 直接拷贝到 Python requests 中验证。第三步在 Node.js 中运行提取出的 JS对比输出和浏览器是否一致。第四步再整合成完整脚本。每完成一步都做一次记录。JS 逆向最怕的是“不知道什么时候改了什么代码”把每一步的命令、改动、报错信息都存下来能大幅减少回头排查成本。10.2 工程化阶段把反爬逻辑单独封装成类不要和业务解析代码混在一起。Cookie 刷新逻辑独立成服务可以用定时任务维护。请求任务要记录日志至少包含时间、URL、状态码、耗时、重试次数。所有输出数据落库或落文件时加上采集时间戳和来源 URL。使用代理时不要使用国外的代理池访问国内资源站延迟太高且容易被封。10.3 合规提醒再强调一次这些技术只适用于你自己拥有、或有充分授权进行测试的站点。涉及版权内容动漫、影视、小说、图片、音乐等的数据采集尤其要谨慎。批量下载和再分发可能涉及版权侵权请务必避免。11. 总结与下一步这次拆解的核心是chameleon型反爬的完整链路动态 Cookie 生成、字体加密、行为校验。这类反爬在资源型站点里很普遍看懂了这套逻辑以后遇到类似机制都能快速入手。值得先做的验证顺序是用浏览器开发者工具定位反爬 JS 文件。搜索 Cookie 字段名的赋值入口。提取核心加密逻辑在 Node.js 中补环境运行。用生成的 Cookie 发起一次 Python 请求验证。如果返回乱码再提取字体文件并建立映射表。最容易踩的坑是补环境。很多人一上来就想着用 puppeteer 模拟浏览器没必要。大部分情况下最小环境模拟就够了。下一步可以扩展的方向控制流平坦化还原、AST 反混淆、WebAssembly 反爬对抗、验证码识别集成、分布式代理池调度。这些都是 JS 逆向进阶路上值得投入的方向搞明白一个再往下走比什么都想抓要有效得多。
返回列表