猫抓Cat-Catch浏览器媒体嗅探扩展的底层原理与架构深度解析
【免费下载链接】cat-catch猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch
某个深夜,你想把一集综艺下载到本地慢慢看,浏览器里却没有原生下载按钮;某个网课平台的视频只允许在线播放,右键菜单一片空白。这时候,一款名为**猫抓(Cat-Catch)**的浏览器资源嗅探扩展成了救命稻草——它能在不破坏页面功能的前提下,把散落在网络请求、视频缓冲区和加密流里的媒体资源一一"捞"出来,并交给本地下载工具或转码服务处理。本文不打算罗列它的功能清单,而是沿着一条"资源从浏览器里被发现、被捕获、被组装成文件"的完整链路,拆解它的底层架构,并回答一个更本质的问题:在浏览器这个严格受限的沙盒里,一个开源扩展是如何把"嗅探"这件小事做成一套专业媒体处理系统的?
在没有嗅探工具的日子里:被动等待与主动出击的方案对比
绝大多数视频网站并不会把真实媒体地址直接暴露给用户。传统做法是打开开发者工具、翻找 Network 面板、手动复制请求 URL,再挂上 Referer 重新请求——繁琐、易错,而且面对加密的 HLS 流或动态生成的"一次性 URL"时基本束手无策。市面上能下载视频的方案,大致可以分为四类:
| 方案 | 工作原理 | 对动态加载内容的覆盖 | 对加密内容覆盖 | 对普通用户的门槛 | 生态与维护 |
|---|---|---|---|---|---|
| 手动抓包 + 下载器 | 人工分析请求头与地址 | 低,需逐条甄别 | 几乎为零 | 极高 | 无 |
| 通用下载器(IDM 等) | 监听浏览器下载事件 | 中,依赖站点兼容 | 低 | 中 | 商业闭源 |
| 专用站点下载脚本 | 针对单个站点定制 | 高但仅限该站 | 中 | 中 | 易随站点改版失效 |
| 通用嗅探扩展(如猫抓) | 网络层拦截 + 页面脚本注入 + 流媒体 API 代理 | 高,多通道互补 | 高,支持 AES-128 解密 | 低 | 开源社区持续迭代 |
猫抓的特别之处在于它不押注单一技术路线,而是把四条嗅探通道组合起来:webRequest网络拦截、内容脚本对页面环境的主动注入、对MediaSource等流媒体 API 的代理改写,以及基于declarativeNetRequest的请求头修改。这套组合决定了它处理问题的边界——凡是浏览器能"看见"的数据,它都有机会拿到,而这条能力边界恰好覆盖了普通用户 95% 的真实下载诉求。
设计哲学:从源码和版本记录里读出的三条原则
翻看仓库的更新日志(CHANGELOG.md)和核心代码,能清晰归纳出这个项目贯穿始终的三条设计原则,它们也是后文所有架构决策的锚点。
原则一:被动嗅探是地基,主动捕获是补充,一切以页面可用性为底线。项目对webRequest的使用非常克制——在js/background.js中,资源匹配只在onSendHeaders与onResponseStarted两个时机执行,前者能拿到完整请求头(便于提取 Referer、Cookie、鉴权 Token),后者能拿到响应头(便于判断 Content-Type 与文件大小),但二者都刻意避免读取请求体,把对性能的干扰降到最低。而页面脚本(catch-script/下的catch.js、search.js)被设计成按需注入、可随时关闭,并在代码中反复处理"深度搜索导致网页无法正常使用"这类回归问题(2.6.6、2.6.5 均有对应修复记录),可见"别把网页搞坏"是绝对的优先级。
原则二:浏览器限制不是敌人,而是需要被理解并绕过的物理规律。Manifest V3 的 Service Worker 会在闲置约 5 分钟后被浏览器强制终止,项目在js/background.js顶部就写明了这条 Chromium 行为,并用webNavigation事件监听 + 定时调用chrome.runtime.getPlatformInfo的方式维持心跳;存储方面,2.5.3 版本将数据从storage.local迁移到storage.session,明确原因就是为了"减少 IO 错误导致扩展无法使用"。这些决策的共同特征,是先承认平台规则,再想办法在规则内争取生存空间,而不是与之对抗。
原则三:把专业能力留给专业工具,扩展只做"搬运与编排"。猫抓从不试图在扩展内部实现完整的转码引擎,而是提供了与在线 ffmpeg 网页端、Aria2 RPC、本地 m3u8DL 命令行工具的对接通道。这种"不重复造轮子、专注打通链路"的思路,让一个浏览器扩展能以极小的体积获得桌面级工具的能力。
核心能力拆解:一条媒体资源从浏览器到硬盘的完整旅程
与其按模块平铺,不如跟随一条媒体资源,看它如何经历"触发 → 捕获 → 解析 → 处理 → 输出"五个环节。这条链路在架构上被刻意设计为松耦合的流水线,每一站都可以独立升级或替换。
触发与捕获:三张网兜住所有流量
资源进入猫抓视野有三条途径,对应三种不同的"狩猎"方式:
资源进入猫抓的三条通道 ├── 通道一:网络层(被动嗅探) │ ├── webRequest 监听请求头/响应头 │ ├── 正则匹配 URL、类型、大小过滤 │ └── 命中后入库 → popup 列表 │ ├── 通道二:页面层(主动注入脚本) │ ├── catch.js:代理 MediaSource.addSourceBuffer │ ├── search.js:劫持 JSON.parse 与 Worker │ └── recorder*.js:录制 webRTC / 视频元素 │ └── 通道三:控制层(请求改写) ├── declarativeNetRequest 改写 User-Agent 模拟手机端 └── 为"一次性 URL"资源自动补全 Referer网络层拦截是默认开启的"守株待兔",核心逻辑在js/background.js的findMedia函数中:先判断全局开关与站点屏蔽列表,再依次检查文件扩展名、Content-Type与Content-Disposition附件头,任何一项命中配置的抓取规则即生成一条资源记录。值得一提的是查重与节流设计——同一 URL 在 500 条记录内用Set指纹去重防止 CPU 空转,写入存储则采用防抖策略:资源间隔小于 500 毫秒时延迟 2 秒批量落盘,单标签资源超过 100 条时再累积 10 条写一次,避免高频请求击穿storage.session的写入瓶颈:
// js/background.js — 防抖落盘:高频捕获时合并写入 if (Date.now() - debounceTime <= 500) { clearTimeout(debounce); debounceTime = Date.now(); debounce = setTimeout(function () { save(info.tabId); }, 2000); return; } save(info.tabId);网络层拦不住的场景(动态加载、加密流、WebRTC 点对点传输),则由注入页面主世界的脚本接手。catch.js的做法堪称"钓鱼执法":它代理了MediaSource.prototype.addSourceBuffer,当页面播放器向缓冲区追加视频分片时,脚本同步把分片二进制数据复制一份:
// catch-script/catch.js — 代理 addSourceBuffer 捕获缓冲数据 window.MediaSource.prototype.addSourceBuffer = new Proxy( window.MediaSource.prototype.addSourceBuffer, { apply: (target, thisArg, argumentsList) => { const result = Reflect.apply(target, thisArg, argumentsList); this.catchMedia.push({ mimeType: argumentsList[0], bufferList: [] }); const index = this.catchMedia.length - 1; // 继续代理 appendBuffer,把分片写入本地列表 result.appendBuffer = new Proxy(result.appendBuffer, { apply: (target, thisArg, argumentsList) => { Reflect.apply(target, thisArg, argumentsList); this.catchMedia[index].bufferList.push(argumentsList[0]); return argumentsList[0]; } }); return result; } });search.js则更进一步,劫持了页面的JSON.parse与Worker构造器——当页面脚本解析包含媒体地址或 16 字节密钥数组的 JSON 时,脚本同步完成"深度搜索",把疑似密钥与资源地址上报给后台。这种"寄生"式采集需要在页面安全策略(Trusted Types、CSP)下小心翼翼地存活,catch.js中专门实现了 Trusted Types 策略创建与 iframesandbox属性清理,正是为穿透这些限制所做的工程铺垫。
解析与处理:从 URL 到可下载文件的"装配车间"
拿到资源地址后,真正的考验才开始。HLS 流媒体的播放清单.m3u8本质是一份"分片索引",猫抓的解析器(js/m3u8.js)直接内嵌 hls.js 作为解析内核,并在此基础上扩展了多层能力:识别EXT-X-KEY标签完成 AES-128 解密、处理EXT-X-MAP的初始化段、支持EXT-X-BYTERANGE的字节范围分片合并(2.6.8 加入)、从页面深度搜索中收集"疑似密钥"用于手动验密。
处理阶段的核心设计是多种输出形态并存,用户可以在一个页面里自由切换:
| 处理模式 | 适用场景 | 技术实现 | 边界与依赖 |
|---|---|---|---|
| 直接合并下载 | 常规 TS 分片 | 分片并行拉取 + Blob 拼装 | 大文件受浏览器内存限制 |
| 边下边存(流式) | 直播、超大文件 | StreamSaver 流式写盘 | 需要 Chromium 104+ |
| MP4 转码 | 需要单一封装格式 | mux.js 在浏览器端转封装 | 耗时随文件增大 |
| 在线 ffmpeg | 音视频合并、多段拼接 | 与 ffmpeg 网页端消息通信 | 需联网访问转码服务 |
| 发送到本地工具 | 专业用户 | Aria2 RPC / m3u8dl:// 协议 / 本地调用 | 需额外安装工具 |
解析器还内置了"下载范围"的高级控制:既可填写数字范围,也可填写HH:MM:SS时间范围,甚至可以逐条点击分片地址单独挑选(2.6.8 起支持),下载出错时自动重试以提升成功率(2.7.1)。这些细节共同指向一个事实:解析器不是简单地"下完拉倒",而是一个面向专业用户的分片装配车间。
输出:让专业工具各司其职
最后一个环节是"交棒"。猫抓对下载结果的去向不做垄断:可以交给浏览器原生下载器,可以推送给 Aria2 后台队列,可以唤起本地 m3u8DL 命令行,也可以把捕获到的媒体数据打包发送给在线 ffmpeg 做音视频合并。background.js中维护了一份ffmpegConfig,负责与 ffmpeg 标签页建立消息通道、缓存待发送数据、在页面加载完成后补齐投递——这种"注册回调式"的编排,保证了多任务并发时数据不会串台(2.5.3 曾专门优化过这一点)。
工程化细节:并发、存储与心跳的三组取舍
架构的成色往往体现在"看不见的工程细节"里。这里选取三组有据可查的取舍案例,说明项目如何在约束下权衡。
取舍一:并发线程数——6 不是拍脑袋的数字。2.4.7 版本将 M3U8 解析器的最大下载线程调整为 6,这个配置沉淀在js/init.js的默认值M3u8Thread: 6中。线程越多下载越快,但每个并发连接都会占用浏览器连接池配额,过高的并发反而会触发站点限流、拖垮同一域名的其他请求。6 是项目在"下载速度"与"网络生态友好度"之间找到的经验平衡点,并且这个值被做成了可配置项,允许用户在设置页按自己的网络环境调整——把权衡的最终决定权交还给用户,这是贯穿项目始终的产品姿态。
取舍二:存储介质——稳定优先于持久。Manifest V3 下,扩展数据主要落在storage.local与storage.session之间。前者持久但存在 IO 写入失败的风险(曾有版本因storage.local异常导致扩展整体失效),后者会话级、性能稳定但刷新即失。2.5.3 的迁移日志直白地写着"减少 IO 错误导致扩展无法使用",代码里则到处是chrome.storage.session ?? chrome.storage.local这种降级写法——高版本浏览器优先使用 session,低版本自动回退。这是"稳定性优先于数据持久性"的典型取舍,因为对嗅探扩展而言,扩展活着比配置活着更重要。
取舍三:Service Worker 心跳——用"脏手段"对抗平台规则。Manifest V3 规定 Service Worker 不可常驻,闲置约 5 分钟后会被回收。后台脚本在文件头部就引用了 Chromium 的相关 issue 链接,随后采取组合拳:监听webNavigation.onBeforeNavigate等事件保持唤醒、响应内容脚本发来的HeartBeat命名端口消息、每 25 秒定时调用chrome.runtime.getPlatformInfo制造活动。2.0.0 版本的更新日志甚至自我调侃"继续用肮脏的手段对抗 Manifest V3"——这种坦诚说明了一个事实:在平台约束下做长期运行的扩展,工程上需要一点"游击战"智慧。
生态与演进:社区驱动的国际化与版本节奏
猫抓的国际化架构是开源协作的范本。_locales/目录下按语言分目录存放messages.json,内容脚本通过catch-script/i18n.js按需加载翻译,普通用户只需翻译字符串即可贡献语言——从 2.5.0 引入多语言支持至今,已积累英、中(简/繁)、日、韩、西、俄、葡、土、越共 10 个语言包,且多数由社区成员在更新日志中署名完成。
_locales/ ├── en/messages.json # 基线语言(英语) ├── zh_CN/ zh_TW/ # 简繁中文 ├── es/ ja/ ko/ ru/ # 西日韩俄 ├── pt_BR/ tr/ vi/ # 葡土越 └── tools/sync-locales.js # 以 en 为基准同步各语言键位tools/sync-locales.js承担了关键的一体化工作:以英文文件为基准,自动向各语言文件补充缺失键、移除废弃键、保持键序一致,让社区翻译者永远只需关注"翻译"本身,而不用关心键位维护。项目版本节奏严格遵循语义化规范,从变更日志能清晰看到稳定的演进模式:
| 版本段 | 演进主题 | 代表性变更 |
|---|---|---|
| 1.x | 从零到一的嗅探底座 | Manifest V3 迁移、正则匹配、Heart Beat |
| 2.0–2.3 | 从"抓链接"到"抓内容" | 视频捕获/录制、m3u8 在线合并、mpd 解析 |
| 2.4–2.6 | 工程化与平台化 | 多语言、session 存储、MQTT、Aria2、屏蔽列表 |
| 2.7 | 打磨与兼容 | 右键菜单、韩语、firefox 修复、下载重试 |
结语:这款开源嗅探扩展适合谁,又会走向哪里
猫抓 Cat-Catch 的架构核心可以浓缩为一句话:用三张互补的"网"覆盖浏览器的全部数据通路,再用一条松耦合的流水线把数据交给最合适的下游工具。它适合三类人:被"在线播放不提供下载"困扰的普通用户、需要批量采集媒体素材的内容从业者,以及想研究浏览器扩展如何在 Manifest V3 限制下存活的开发者——后两者甚至可以直接把js/background.js的防抖存储、catch-script/catch.js的 API 代理、tools/sync-locales.js的国际化流水线当作现成的架构范本。
关于未来,2.6.4 版本引入的 MQTT 支持暗示了一条值得关注的路径:当浏览器端完成"捕获"后,把媒体数据推送到自建的本地服务或云端队列,就能让扩展与边缘计算、远程转码集群完成协作——嗅探的终点,或许不再只是硬盘。作为一款 GPL-3.0 许可的开源项目,它已经证明了一件事:真正的平台限制,从来只淘汰那些不肯研究规则的人,而不是那些在规则之内把事情做到极致的人。
【免费下载链接】cat-catch猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考