Featured image of post BilibiliContentFetcher 项目复盘:从单条演示到批处理闭环

BilibiliContentFetcher 项目复盘:从单条演示到批处理闭环

一次完整链路落地记录,覆盖质量约束、批处理主链路、同构重构、实跑验收与发布

这次复盘记录的是 BilibiliContentFetcher 一次完整落地过程。

我这次的目标不是做一条能看的演示链路,而是把批量生产链路做稳定,把输出质量做可控,把项目结构做可维护,把最终产物直接落到 Obsidian。

我按真实时间线展开,尽量保留全过程细节。

1. 起点目标

我在会话开始阶段先把目标重新收敛,避免中途跑偏。

当时我给自己定了六个硬条件。

  1. 主目标是批量稳定执行,不是单条效果展示。
  2. 输出格式必须严格贴合根目录 Tempate.md。
  3. 必须使用 DeepSeek 思考模式,不接受本地替代。
  4. 模块结构与链路逻辑要对齐 XHSContentFetcher。
  5. 最终笔记必须可直接出现在 Obsidian。
  6. 最终代码要推送远程,并补全 CLI 命令文档。

这一组条件决定了后续所有取舍。

2. 阶段 A

这个阶段是质量回归和模板约束加固,时间段是 18 点 20 到 18 点 33。

我先执行回归测试,确认基线可跑。

1
pytest -q

结果是 5 passed。

这一步给了我一个清晰信号,当前代码有可用基础,但输出质量不够。

我随后集中处理了四类问题。

  1. 文本里有泛化表达,观点和结论过于笼统。
  2. 有占位风格残留,章节质感不稳定。
  3. 评论区覆盖不足,子评论利用率偏低。
  4. 视频类笔记有明显模板痕迹。

2.1 质量约束改造

我在 src/bili_content_fetcher/ai_writer.py 里加了完整质量栅栏。

关键函数是:

  • _validate_markdown_output
  • _repair_markdown_once
  • _ensure_quality

这三步形成了质量闭环。

  1. 先检查结构完整性。
  2. 再执行自动修订。
  3. 最后做二轮兜底,不通过就回退。

我把检查项写得很细,包含章节顺序、占位词、概念数量、问题数量、评论数量、图片内联要求。

2.2 评论区典型性改造

我同时补了评论评分和代表性筛选。

对应新增逻辑:

  • _comment_score
  • _select_representative_comments
  • _comment_insight

这组改动让评论区从堆数据变成可读观点层。

我要求每条代表评论都要有我的提炼句,不再只贴原文。

2.3 阶段 A 实跑

我用单条链接做了一次实跑。

1
bili-note run https://www.bilibili.com/opus/1195483269038080034

结果是新笔记目录生成成功,结构可用,基础质量明显提升。

3. 阶段 B

这个阶段是切到 DeepSeek 真链路,时间段是 18 点 33 到 18 点 36。

问题不是代码逻辑,而是配置状态。

3.1 DeepSeek Key 缺失

我检查后确认当前项目没有可用 Key。

  1. 项目 .env 缺失。
  2. 环境变量 DEEPSEEK_API_KEY 为空。

我的处理方式是从 XHSContentFetcher 读取可用配置,再写入当前项目 .env。

3.2 Vault 路径空值误解析

我还遇到了一个配置细节问题。

OBSIDIAN_VAULT_PATH= 空值被解析为当前目录,bili-note check 显示默认 Vault 指向点目录。

我删除了空值行,恢复为未配置状态,避免误写路径。

3.3 DeepSeek 真链路验证

我重新执行带 DeepSeek 配置的运行命令。

结果是模型链路跑通,真实生成成功。

这个节点很关键,说明我已经从本地降级模式切回目标模式。

4. 阶段 C

这个阶段是方向纠偏,时间段是 18 点 36 到 18 点 56。

核心变化只有一句话,批量优先替代单条打磨。

我在这个阶段做了三件大事。

  1. 新增批处理子命令。
  2. 处理 Windows 编码崩溃。
  3. 落地批处理汇总产物。

4.1 批处理子命令落地

我在 src/bili_content_fetcher/cli.py 加了 batch 子命令体系。

支持参数包含:

  • --max-items
  • --fail-fast

并新增批处理汇总文件机制,输出 batch_summary_*.json。

我同时同步改了 README.md,保证命令文档可直接执行。

4.2 Windows 编码崩溃修复

这一步是阶段 C 的关键故障。

我当时遇到错误:

1
UnicodeEncodeError: 'gbk' codec can't encode character '\ufeff'

触发点是批量输入文件首行 BOM 加上控制台输出编码冲突。

我按三步修复。

  1. _load_batch_inputs 改成 utf-8-sig 读取。
  2. 输入行统一剥离 \ufeff 前缀。
  3. 控制台输出前做安全预览过滤,剔除不可编码字符。

修完后我马上复跑批量命令。

1
bili-note batch batch_links.txt --max-items 2

结果是 2/2 成功。

并产出汇总文件:

output/batch_summary_20260506_185559.json

5. 阶段 D

这个阶段是视频笔记质量二次修复,时间段是 18 点 56 到 19 点 02。

5.1 英文噪声词进入概念区

我发现视频类笔记的概念区混入了 and the add no 这类词。

这是明显质量缺陷。

我做了三项补丁。

  1. 增加英文停用词 EN_STOPWORDS。
  2. 增加英文术语白名单 EN_TERM_ALLOWLIST。
  3. 非股票场景的问题标题改成稳定框架,避免弱标题漂移。

5.2 模型结果被回退过度覆盖

我还发现质量修订链有副作用。

多轮修订后,较好的模型版本有时会被过度回退。

我在 _ensure_quality 里加了保留策略。

当结构可用且占位残留已清空时,优先保留最后模型版本。

这一步直接改善了成文自然度。

5.3 阶段 D 复跑

我用视频批处理单条做复验。

1
bili-note batch batch_video_only.txt --max-items 1

结果是视频学习报告稳定生成,英文噪声问题消失。

6. 阶段 E

这个阶段是大改造,时间段是 19 点 02 到 19 点 28。

目标很明确,把 Bili 项目和 XHS 项目做同构对齐。

6.1 同构基线

我先对齐目标模块清单:

  • cli
  • config
  • workflow
  • fetcher
  • media
  • video_tools
  • deepseek
  • markdown_writer
  • obsidian
  • url_parser
  • ocr_engine

6.2 新增模块

我新增了以下文件。

  1. src/bili_content_fetcher/url_parser.py
  2. src/bili_content_fetcher/fetcher.py
  3. src/bili_content_fetcher/media.py
  4. src/bili_content_fetcher/video_tools.py
  5. src/bili_content_fetcher/ocr_engine.py
  6. src/bili_content_fetcher/deepseek.py
  7. src/bili_content_fetcher/markdown_writer.py
  8. src/bili_content_fetcher/obsidian.py
  9. src/bili_content_fetcher/workflow.py

6.3 重构模块

我重点重构了两个文件。

  1. config.py
    • 增加本地配置文件 ~/.bili-content-fetcher/config.json
    • 保留 .env 兼容链路,兼容历史配置
  2. cli.py
    • 从 Typer 切到 argparse
    • 统一成与 XHS 对齐的 run config batch 命令体系

6.4 文档和入口

我同步重写:

  1. README.md
  2. pyproject.toml 脚本入口,改为 bili_content_fetcher.cli:main

6.5 阶段 E 验收

我执行整套验收。

1
2
3
4
pytest -q
python -m bili_content_fetcher.cli --help
python -m bili_content_fetcher.cli run --help
python -m bili_content_fetcher.cli batch --help

结果:

  1. pytest -q 变为 8 passed
  2. CLI 帮助命令全部可用

随后我提交并推送。

  • commit 03ac851
  • message feat: align bili workflow with xhs architecture and add full batch CLI
  • push origin/main 成功

7. 阶段 F

这个阶段是最终验收,时间点约 20 点 02。

目标只有一个,Obsidian 可见。

我执行命令:

1
python -m bili_content_fetcher.cli run "<opus链接>" --vault-dir "C:\Users\yourp\Documents\Obsidian Vault" --notes-folder "BiliNotes" --open-obsidian

验收结果:

  1. DeepSeek 生成成功
  2. 图片 7
  3. 评论 18
  4. OCR 7
  5. 笔记写入 Vault 成功
  6. Obsidian 可直接查看

本次验收产物路径:

C:\Users\yourp\Documents\Obsidian Vault\BiliNotes\ru-he-zai-5000jia-gu-piao-zhong-shai-xuan-chu-long-tou-gu-bi-li-bi-li\ru-he-zai-5000jia-gu-piao-zhong-shai-xuan-chu-long-tou-gu-bi-li-bi-li.md

8. 问题清单汇总

我把全过程问题收敛成七类。

  1. 笔记里有占位和模板痕迹。
  2. 评论区代表性不足,回复利用不足。
  3. 项目缺 DeepSeek 配置。
  4. 批处理不是主链路。
  5. Windows BOM 和编码导致批处理崩溃。
  6. 视频笔记出现英文噪声概念。
  7. 项目结构和 XHS 不一致。

对应修复策略分别是:

  1. 质量校验加自动重写加密度约束。
  2. 评论评分筛选加逐条提炼。
  3. .env 补齐加 CLI 缺 Key 明确报错。
  4. batch 子命令加失败续跑和汇总。
  5. utf-8-sig 加 BOM 剥离加安全输出。
  6. 停用词加白名单加标题稳态框架。
  7. 同构重构模块加统一 CLI 和配置体系。

9. 关键命令流水

9.1 质量回归

1
pytest -q

9.2 单条链路

1
2
bili-note run "<链接>"
python -m bili_content_fetcher.cli run "<链接>" ...

9.3 批量链路

1
2
bili-note batch links.txt --max-items 2
python -m bili_content_fetcher.cli batch links.txt --max-items 1

9.4 配置检查

1
2
bili-note check
python -m bili_content_fetcher.cli config show

9.5 版本管理

1
2
git commit -m "..."
git push origin main

10. 最终状态

我在导出时间点确认的状态如下。

  1. 代码已提交并推送到远程主分支。
  2. CLI 的 run batch config 全量可用。
  3. DeepSeek 真链路实跑通过。
  4. Obsidian 实跑可见笔记。
  5. 测试状态 8 passed。

11. 我这次最关键的决策

第一,先把批处理链路立成主线,单条只做回归样本。

第二,把输出质量做成程序约束,不靠模型临场发挥。

第三,把项目结构和 XHS 同构,换来后续维护和迁移的确定性。

12. 下一步计划

下一步我会继续补三组能力。

  1. 断点续跑,降低长任务重跑成本。
  2. OCR 和 LLM 缓存,降低重复计算成本。
  3. 结构化日志,细化阶段耗时和错误分类。

这次项目的核心结果不是某一条笔记写得好看。

真正的结果是我把一条从抓取到笔记落地的链路做成了可批量执行、可定位故障、可重复验收的工程系统。

comments powered by Disqus