Files
MediaCrawler/UPSTREAM.md
T
butubb 4e60524f37
Deploy VitePress site to Pages / build (push) Canceled after 0s
Deploy VitePress site to Pages / Deploy (push) Canceled after 0s
feat: 监控面板 / 登录鉴权 / 多平台切换 / MySQL
在上游 MediaCrawler 之上新增一层:

- 监控层 api/monitor/ —— 多博主/多笔记的定时采集、指标快照差分、报表、
  企业微信通知。每轮采集写入独立目录,差分才成立。
- WebUI 登录鉴权 api/auth.py —— PBKDF2 口令 + 服务端会话,/api 全接口防护。
  WebSocket 单独加依赖:BaseHTTPMiddleware 对 ws 作用域直接放行,覆盖不到。
- 全局平台切换 + 能力矩阵 —— 如实区分「爬虫模块支持」与「监控层已接线」,
  未接通的平台直接拒绝建任务,而不是静默跑空。
- 监控库改用 MySQL 5.7(可回退 SQLite 供测试):逐表强制 utf8mb4
  (服务端与库默认都是 latin1),启动校验所连 schema 以防写错库,
  连接池 recycle + pre_ping 应对 MySQL 的 8 小时空闲断连。

修复上游缺陷:

- xhs/core.py: 主页抓取失败会跳掉整个博主,导致一条作品都抓不到,
  而那份资料只喂给一个空函数。改为尽力而为,失败不中断。
- xhs/login.py: cookie 登录只注入 web_session,冷启动签名会失败。
  新增 INJECT_ALL_COOKIES 开关(默认关闭,原有行为不变)。
- requirements.txt: 补上 websockets。它在上游 pyproject.toml 里有声明、
  这里漏了,导致 uvicorn 没有 WebSocket 能力,实时日志流从未工作。

改动过的上游文件清单及合并方式见 UPSTREAM.md。

测试:492 passed(另有 1 个既有的 Windows/gbk 上游测试失败,与本改动无关)
2026-10-07 09:58:40 +08:00

5.8 KiB
Raw Blame History

与上游的差异管理

本仓库在 NanmiCoder/MediaCrawler 之上加了一层 监控/鉴权/多平台面板。这份文档记录改了上游哪些文件、为什么,以及上游更新时怎么合并。


一、改动分三类

冲突风险从低到高:

1. 纯新增文件(零冲突)

上游怎么改都不会碰到它们:

api/auth.py                          WebUI 登录鉴权
api/monitor/*                        监控层整体(含 platforms.py 能力矩阵)
api/monitor/db.py                    MySQL 连接层(可回退 SQLite 供测试用)
api/monitor/migrate_from_sqlite.py   SQLite → MySQL 一次性迁移脚本
api/routers/{auth,monitor,settings}.py
api/schemas/{auth,monitor,settings}.py
api/services/interpreter.py          解释器探测(uv / .venv / 当前解释器)
webui/src/components/{monitor,settings,auth}/    新视图
webui/src/components/layout/{PlatformSwitcher,UnwiredPlatformNotice}.tsx
webui/src/{hooks/useMonitor.ts,hooks/usePlatform.ts,store/platformStore.ts,lib/monitorFormat.ts,types/monitor.ts}
docs/监控功能使用说明.md
tests/test_{auth,settings,platforms,monitor_*}.py

2. 加法改动(低冲突)

只在既有文件里新增内容,不改动原有行:

文件 加了什么
cmd_arg/arg.py typer 选项:--enable_cdp_mode、--inject_all_cookies、--save_login_state、--cookies_file、--crawler_max_sleep_sec,以及对应的 config.* 回写
api/schemas/crawler.py CrawlerStartRequest 的若干可选字段(默认 None,不传则不加对应 CLI 参数)
config/base_config.py INJECT_ALL_COOKIES = False
api/routers/__init__.py 导出新增的 router
requirements.txt 补上 websockets(上游 pyproject.toml 里有、requirements.txt 里漏了)
tests/conftest.py 新增 _bypass_auth_for_non_auth_suites fixture

3. 接线改动(中冲突,需要人看)

文件 改了什么 上游若在此处变动
api/main.py 注册 4 个 router 并加 Depends(require_auth);lifespan 里初始化监控库、启动调度器、跑设置键迁移;load_dotenv;CORS 可配;docs/redoc/openapi 关闭;监听地址改 env 最需要人工合并的文件。留意 router 注册块、lifespan、__main__
api/routers/websocket.py 两个 WS 路由加 dependencies=[Depends(require_ws_auth)] 上游若新增 WS 路由,必须同样加上,否则那条流是裸奔的
api/services/crawler_manager.py 解释器探测替换硬编码 uv run;_build_command 转发新增参数;新增 is_busy() / run_and_wait() 与完成事件 留意 _build_command 的参数拼装
media_platform/xhs/login.py login_by_cookies 在 INJECT_ALL_COOKIES 打开时注入全部 cookie(默认关闭,行为不变) 小改动,好合并

4. 上游 bug 修复(建议回馈上游)

文件 修的问题
media_platform/xhs/core.py 见下节
media_platform/xhs/login.py 同上(cookie 加固)

二、应该给上游提 PR 的两个修复

这两处是上游自身的缺陷,提上去以后就不用自己背着:

1. 博主主页抓取失败会跳掉整个博主(xhs/core.py)

get_creator_info() 抓主页 HTML 解析 window.__INITIAL_STATE__,解析失败抛 JSONDecodeError—— 它是 ValueError 的子类,被 except ValueError 误捕获,日志报成 "Failed to parse creator URL"(误导,URL 根本没解析错),然后 continue 跳过整个博主。

而那份资料只喂给 save_creator(),它在教学版里是空函数。也就是说: 一个喂给空函数的抓取失败,让真正要抓的作品一条都没抓到,表现为"0 篇作品", 和"登录失效"长得一模一样。

修复:把资料抓取改成尽力而为,失败只警告、继续抓作品。

a1 / webId 等签名所需 cookie 只能靠持久化 profile 补,冷启动时签名会失败。 默认行为保持不变,用 INJECT_ALL_COOKIES 开关控制。


三、上游更新时怎么操作

日常流程

git stash                      # 或先 commit 到自己的分支(推荐)
git fetch origin main
git rebase origin/main         # 冲突只会出现在上表第 3、4 类文件里
./.venv/Scripts/python.exe -m pytest tests/ -q     # 486 个测试就是回归网

强烈建议:先把改动提交掉

当前状态是未提交的(25 个上游文件被改 + 31 个新文件)。在 main 分支上裸着工作区, 一次 git checkout . 就全没了,而且没法 rebase。

git checkout -b local/monitor-panel
git add -A && git commit -m "监控面板 / 鉴权 / 多平台"

如果改动持续增长:fork

把本仓库 fork 到自己名下,上游设为 remote:

git remote rename origin upstream
git remote add origin <你的 fork>
git push -u origin local/monitor-panel

之后同步上游用 git fetch upstream && git rebase upstream/main。


四、合并时最容易忘的三件事

  1. 新增的 /api 路由必须带鉴权。跑一下 tests/test_auth.py—— 里面有个测试会遍历 app.routes,断言除豁免集外每个 /api 路由无凭据都返回 401。 上游新增接口忘了加鉴权,这个测试会直接失败。
  2. 新增的 WebSocket 路由必须加 require_ws_auth。 BaseHTTPMiddleware 对 WS 完全不生效(scope["type"] != "http" 直接放行), 只靠中间件会漏。同样有测试守着。
  3. 上游若改动 AsyncFileWriter 的输出路径规则,api/monitor/ingest.py::find_run_files 会跟着失效——它靠 glob {out_dir}/{platform}/jsonl/*_contents_*.jsonl 定位每轮的产物。