猫抓 Cat-Catch:从资源嗅探到 M3U8 引擎的 6 次架构选型
2026/9/7 19:57:14 网站建设 项目流程

猫抓 Cat-Catch:从资源嗅探到 M3U8 引擎的 6 次架构选型

【免费下载链接】cat-catch猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch

猫抓(Cat-Catch)是一个浏览器资源嗅探扩展,当前版本 2.7.2,运行在 Manifest V3 之上。它要解决的核心痛点是:网页里正在播放或加载的媒体资源(mp4、m3u8、mpd 等),用户往往拿不到直链,或者直链带 Referer 校验无法直接下载。猫抓的能力边界是:被动嗅探 + 主动捕获 + M3U8/MPD 解析合并 + WebRTC 录制,覆盖 Chromium 系和 Firefox,不支持 Safari。

后台为什么不会死:Service Worker 的三条保活路径

MV3 把 background 从常驻页面改成 Service Worker,空闲约 5 分钟即被浏览器终止。对普通扩展这不重要,但对嗅探工具是致命的——webRequest回调注册在 Worker 里,Worker 一死,所有请求就都漏掉了。猫抓在 js/background.js 里做了三件事:

// 心跳保活:popup 打开时建立 Port,Worker 内 4 分 10 秒后主动断开 chrome.runtime.onConnect.addListener(function (Port) { if (chrome.runtime.lastError || Port.name !== "HeartBeat") return; Port.postMessage("HeartBeat"); const interval = setInterval(function () { clearInterval(interval); Port.disconnect(); }, 250000); });

为什么是 250000ms(4 分 10 秒)而不是 300000ms?因为浏览器给的终止窗口约 5 分钟,留 50 秒余量应对系统调度抖动,断开后由 popup 重新连接形成循环。这是第二、三条路径之外的兜底,前两条都更"免费":

保活手段原理触发条件代价
注册webNavigation空监听导航事件本身就是活动信号用户在浏览网页时持续有效
setInterval(getPlatformInfo, 25s)定时调用 API 阻止休眠判定Worker 存活期间每 25 秒一次轻量调用
心跳 Port + 500ms 自唤醒显式通信延长寿命;被杀后首个事件回调里setTimeout重新初始化事件驱动被杀瞬间可能丢一条数据

第三条路径值得单独说:findMedia入口检查全局初始化标志,未完成就 500ms 后重试自身——Worker 被杀后靠下一条网络请求"把自己叫醒"。这等于承认了保活不可能 100% 成功,转而保证"死了也能立刻复活"。保活方案本身不追求精确,追求的是恢复路径足够短。

模块职责:谁负责抓,谁负责下,谁负责存

猫抓没有做微内核那一套,实际是"一个中心 + 几个专用页"的结构。核心判断标准只有一条:数据能不能离开 background。

模块核心职责对外接口依赖谁
js/background.js嗅探主逻辑、请求头缓存、数据持久化webRequest回调、runtime消息全部模块的数据源头
catch-script/catch.js页内主动捕获(代理 MediaSource)、捕获面板 UI注入页面,经runtime回传数据background 的开关与设置
js/m3u8.downloader.js切片并发下载、合并、转码调度m3u8.html 页面内hls.js、mux、m3u8-decrypt(见 lib/)
js/m3u8.js / js/mpd.jsM3U8/DASH 解析页逻辑、参数拼装各自独立 HTML 页面background 的嗅探数据
js/popup.js资源列表、筛选、正则匹配、预览入口popup.html / sidePanelbackground 存储的数据
catch-script/search.js、recorder*.js、webrtc.js深度搜索、视频缓存录制、WebRTC 录制按需注入的独立脚本页面环境

边界的取舍很实际:解析器、下载器、预览器都做成独立 HTML 页面而不是塞进 popup,因为每个页面有自己的第三方库(hls.js、mpd-parser、StreamSaver),独立页面天然隔离内存与脚本生命周期;代价是多几次页面间消息往返。主动捕获脚本放在catch-script/而非js/,区分"注入网页执行的代码"和"扩展自有页面代码",这个目录约定在 review 时比注释更省解释成本。模块划分的第一原则是让重逻辑(解析、下载)远离生命周期最短的上下文(Worker 和 popup)。

图:M3U8 解析器页面,切片列表、自定义请求头、密钥验证与 ffmpeg 参数都集中在这一个独立页面里

性能与稳定性:三个场景的阈值怎么定

并发下载。2.4.7 版本把 m3u8 解析器最大下载线程调整为 6。没有做动态线程池,原因是切片下载是 IO 密集且单任务体量小,固定 6 并发在大多数网络下已接近带宽上限,而动态调度在 Service Worker 被杀的场景下状态难以恢复。稳定性补丁都花在恢复路径上:2.4.8 修"下载失败丢失线程",2.6.2 加录制失败重试,2.7.1 加下载出错自动重试——与其优化正常路径的速度,不如保证异常路径不卡死。

内存。三个阈值各管一层:

场景阈值版本解决的问题
每页面最大储存9999 条2.5.9广告密集的页面把缓存无限撑大
popup 加载超过 500 条可中断2.4.2长列表渲染卡死 popup
资源去重urlMap + 重复资源排除2.6.2 重构同一视频跨页重抓造成内存翻倍

IO。2.5.3 把运行时数据从storage.local迁到storage.session,官方 changelog 的原话是"减少 IO 错误导致扩展无法使用",要求 Chrome 104+。持久化不再每次嗅探都写盘,而是靠chrome.alarms定时把内存里的cacheData快照写一次,代码里就一行回退:

(chrome.storage.session ?? chrome.storage.local).set({ MediaData: cacheData });

??直接覆盖了 Firefox 和旧版本 Chromium 两种不支持的场景。写盘频率从"每个请求"降到"每个 alarm 周期",磁盘写入量降了一到两个数量级。稳定性阈值宁可保守一点(9999 而非 999),因为溢出被丢弃的是一条资源记录,而内存撑爆是整个扩展不可用。

Chrome 与 Firefox:一份代码,两套 manifest

猫抓的 Firefox 适配策略是"能兼容就兼容,不能兼容就换 manifest",而不是做运行时 API 桥接层。两份入口配置对比:

能力ChromiumFirefox降级方案
background 加载MV3 service_workerMV2background.scripts(见 manifest.firefox.json)Firefox 直接脚本加载,background.js开头用typeof G === 'undefined'判断是否重复加载
侧边栏 sidePanel支持(Chromium 114+,2.6.3 修了低版本无法安装的问题)不支持回退到 popup / 弹出新窗口两种模式
storage.session支持(104+)不支持回退storage.local
注入类脚本(深度搜索/录制)全版本128+ 才开放(2.5.7)低版本隐藏入口
blob url 下载(m3u8 切片)正常曾无法下载,2.7.0 修复无,只能修

2.5.7 让 Firefox 也升到 MV3 结构,但保留了 V2 式的 scripts 加载方式——因为 Firefox 的 MV3 background 当时同样受限,与其等 Firefox 补齐,不如自己选更可控的加载路径。Chromium 侧的最低版本 93 写死在 manifest 的minimum_chrome_version,低于 102/114 的功能靠运行时检测隐藏按钮。多端适配的结论是:差异写在构建产物(manifest)层,而不是 if-else 层,这样每个分支的行为可以单独验证。

图:Edge 等 Chromium 系浏览器的安装引导,走同一套 MV3 manifest

安全与隐私:只做了三件低成本的事

猫抓不声称有体系化安全架构,实际投入集中在三个具体问题上:

问题方案位置
注入的 UI 被页面 CSP(Trusted Types)拦截运行时探测:先试写innerHTML,失败再创建catCatchPolicy策略,都不行就跳过catch-script/catch.js
部分网站不希望被嗅探屏蔽列表(可白名单模式),2.6.5 加全局强制屏蔽列表background 的blockUrlSet
扩展页面自身显式声明script-src 'self'; object-src 'self'CSPmanifest

Trusted Types 那段探测逻辑值得看一眼它的姿态:

// 先试探页面是否开启 Trusted Types,未开启则直接透传 try { const fakeDiv = document.createElement('div'); fakeDiv.innerHTML = string; createHTML = (string) => string; } catch (e) { /* 页面开启时创建 policy 拦截 innerHTML 赋值 */ }

这是典型的"探测优先"写法:不预设环境,先试一次再决定路径。隐私侧的边界更简单——数据只存本地 storage,MQTT、aria2 RPC、数据发送这些出站能力全部是用户手动配置的目标地址,扩展不内置任何上报端点。安全投入与嗅探工具的实际风险匹配:页面会杀你的 UI,但不会偷你的数据。

版本演进与选型逻辑:六个关键节点回看

版本关键变化为什么这么选
1.0.24HeartBeat 首次加入MV3 转型期最小代价止血,先让扩展可用
2.0.0Worker 被杀后 500ms 自唤醒;视频主动捕获接受"保活会失败",把重心挪到恢复速度;被动嗅探拿不到的源主动抓
2.2.2解析器换 hls.js,下载器与解析器分离自研解析的 bug 面太大,引入成熟库;分离后两者可独立迭代
2.4.7下载线程固定 6放弃动态调度,换取异常恢复的确定性
2.5.3 / 2.5.9storage.session;9999 条上限 + 屏蔽列表用存储层换 IO 错误率;用硬上限换内存下界
2.6.2 / 2.6.8侧边栏模式;EXT-X-BYTERANGE 支持侧边栏是体验升级但绑定 Chromium 114+,故做成可选;BYTERANGE 是长尾 M3U8 结构,不做就覆盖不了

收束成四条判断:

  • 恢复优先于保活。与其花力气让 Worker 永不休眠,不如让被杀后的复活路径短到 500ms。
  • 阈值是防溢出用的,不是优化用的。9999、6 线程、500 条,这些数字的取值逻辑都是"超过就坏",而非"超过就慢"。
  • 浏览器差异写进 manifest,不写进代码。运行时 if-else 分支会随版本腐烂,双 manifest 则每个分支独立可测。
  • 第三方库只引入不重造。hls.js、mux、mpd-parser 全部走 lib/ 现成方案,自研集中在"扩展特有"的嗅探与调度层。

这套取舍的共同点是:每个决定都优先保证"坏了能恢复、能关掉、能回退",功能扩张始终排在稳定性之后。对于同样要跨浏览器、跨版本长期维护的扩展项目,这个顺序本身比任何单个方案都值得借鉴。

【免费下载链接】cat-catch猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询