docs: README 对齐 v1.1.3 并补实战验收与 2 条踩坑
- 文件表标注脚本版本,成品视频由 gitignore 挡在库外 - 实现要点补 @connect 全白名单与网络容错三层防线 - 验收结果补 2026-10-08 实战全集下载成功 - 新增踩坑 11: @connect 漏域名被油猴静默拦截的特征与解法 - 新增踩坑 12: 代理节点瞬断指纹(remote.ip 为空 + 对齐重启时间)
This commit is contained in:
@@ -21,8 +21,9 @@ uv sync # 自动建 .venv 并装依赖(pycryptodome)
|
|||||||
|---|---|
|
|---|---|
|
||||||
| `hls_dl.py` | 通用 HLS 下载器:拉 m3u8 → 并发下分片 → AES-128 解密 → ffmpeg 合并 |
|
| `hls_dl.py` | 通用 HLS 下载器:拉 m3u8 → 并发下分片 → AES-128 解密 → ffmpeg 合并 |
|
||||||
| `reqable_mcp.py` | Reqable MCP 客户端:命令行翻抓包记录、调用 Reqable 的 50+ 个工具 |
|
| `reqable_mcp.py` | Reqable MCP 客户端:命令行翻抓包记录、调用 Reqable 的 50+ 个工具 |
|
||||||
| `huangguo_video_dl.user.js` | **油猴脚本**:详情页一键全集下载,打包 ZIP 存到 ~/Downloads |
|
| `huangguo_video_dl.user.js` | **油猴脚本 v1.1.3**:详情页一键全集下载,打包 ZIP 存到 ~/Downloads |
|
||||||
| `陪玩假女友_1.mp4` | 成品:123s / 720×1280 / H.264+AAC / 21.93 MB |
|
|
||||||
|
> 成品视频(`*.mp4`/`*.zip`)由 `.gitignore` 挡在库外,不入库。
|
||||||
|
|
||||||
## 用法一:HLS 直接下载
|
## 用法一:HLS 直接下载
|
||||||
|
|
||||||
@@ -91,7 +92,8 @@ d = json.loads(c.call('capture_live_get_by_id', {'id': 4289})['content'][0]['tex
|
|||||||
|
|
||||||
| 环节 | 方案 |
|
| 环节 | 方案 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 跨域请求 | `GM_xmlhttpRequest`(`@connect huangguo.me` + `*.rlkfus.cn`) |
|
| 跨域请求 | `GM_xmlhttpRequest`(`@connect huangguo.me` + `*.rlkfus.cn` + `*.cloudfront.net` + `*` 兜底) |
|
||||||
|
| 网络容错 | 失败重试 2 次(1s)→ 降级原生 `fetch`(CDN 带 `ACAO: *`)→ 完整错误显示到面板 |
|
||||||
| 剧名/集数 | `[data-drama-title]` / `data-total-episode` / `a.detail-episode[data-ep]` |
|
| 剧名/集数 | `[data-drama-title]` / `data-total-episode` / `a.detail-episode[data-ep]` |
|
||||||
| m3u8 地址 | play 页 `.dplayer-video` 的 `data-url`,**拼 `/h5/m3u8/` 前缀** |
|
| m3u8 地址 | play 页 `.dplayer-video` 的 `data-url`,**拼 `/h5/m3u8/` 前缀** |
|
||||||
| AES-128 解密 | WebCrypto `subtle.decrypt`,IV = media sequence 大端 |
|
| AES-128 解密 | WebCrypto `subtle.decrypt`,IV = media sequence 大端 |
|
||||||
@@ -99,9 +101,9 @@ d = json.loads(c.call('capture_live_get_by_id', {'id': 4289})['content'][0]['tex
|
|||||||
| 打包 | **手写 STORE ZIP**(每集 CRC32 后转 `Blob` 卸到堆外,只拼头尾字节) |
|
| 打包 | **手写 STORE ZIP**(每集 CRC32 后转 `Blob` 卸到堆外,只拼头尾字节) |
|
||||||
| 付费集 | 识别 `data-coin-dialog-open`,自动跳过并在完成提示里列出 |
|
| 付费集 | 识别 `data-coin-dialog-open`,自动跳过并在完成提示里列出 |
|
||||||
|
|
||||||
**已验证**(Node 仿真真实管线):
|
**已验证**:
|
||||||
- 下载解密转封装:第 1 集 21.9MB/3.7s、第 2 集 14.5MB/2.4s,解压后文件名与时长均正确
|
- Node 仿真管线:下载解密转封装 21.9MB/3.7s;200MB 打包 **1 秒**,`testzip()` CRC 全过,RSS 294MB
|
||||||
- 打包:10 集 × 20MB = 200MB 压测,**1 秒内完成**,Python `testzip()` CRC 逐字节全过,内存 RSS 294MB
|
- **实战验收**(2026-10-08):《高三爱情故事》全集一键下载成功,ZIP 落入 ~/Downloads ✅
|
||||||
|
|
||||||
## 踩坑记录
|
## 踩坑记录
|
||||||
|
|
||||||
@@ -115,3 +117,5 @@ d = json.loads(c.call('capture_live_get_by_id', {'id': 4289})['content'][0]['tex
|
|||||||
8. **m3u8 单次即全集**:每次请求返回的就是该集完整列表(如第 1 集 18 段);之前遇到的"3 段广告"是另一个轮换位,别混淆。
|
8. **m3u8 单次即全集**:每次请求返回的就是该集完整列表(如第 1 集 18 段);之前遇到的"3 段广告"是另一个轮换位,别混淆。
|
||||||
9. **`mux.js` 全局名**:浏览器 UMD 分支挂的是 **`muxjs`**(不是 `mux`,vm 实测),脚本里写 `window.muxjs || window.mux` 兼容;Node 加载需 `npm i global` 提供 shim,入口 `mux.mp4.Transmuxer`。
|
9. **`mux.js` 全局名**:浏览器 UMD 分支挂的是 **`muxjs`**(不是 `mux`,vm 实测),脚本里写 `window.muxjs || window.mux` 兼容;Node 加载需 `npm i global` 提供 shim,入口 `mux.mp4.Transmuxer`。
|
||||||
10. **JSZip `generateAsync` 卡 90%**:Firefox 下多集大文件(每集 ~20MB×N)会永久挂死——所有 `Uint8Array` 压在 JS 堆上引发 GC 风暴。解法是弃用 JSZip,每集算完 CRC 立即 `new Blob([bytes])` 卸到堆外,ZIP 组装只拼 local header/central dir/EOCD 字节 + Blob 引用,200MB 1 秒完成。
|
10. **JSZip `generateAsync` 卡 90%**:Firefox 下多集大文件(每集 ~20MB×N)会永久挂死——所有 `Uint8Array` 压在 JS 堆上引发 GC 风暴。解法是弃用 JSZip,每集算完 CRC 立即 `new Blob([bytes])` 卸到堆外,ZIP 组装只拼 local header/central dir/EOCD 字节 + Blob 引用,200MB 1 秒完成。
|
||||||
|
11. **`@connect` 漏域名 = 油猴静默拦截**:同一站点不同剧集可能走不同 CDN(《陪玩假女友》→ `rlkfus.cn`,《高三爱情故事》→ `cloudfront.net`),白名单没盖住时请求**不发也不报权限错**,只是 GM `onerror` 网络错误。特征:Reqable 里 key 请求有、分片零记录。解法:`@connect *` 兜底。
|
||||||
|
12. **代理节点瞬断的指纹**:Reqable 记录 `connection.remote.ip` **为空** = 请求进了代理但上游没建连(网络层问题,不是脚本问题);拿记录时间戳对 `ps -o lstart -p <mihomo_pid>` 看重启时间即可破案。此时段国内域名 200、国外 CDN 全挂,正是分流节点故障的典型特征。
|
||||||
|
|||||||
Reference in New Issue
Block a user