Online Doc Convert
Overview
将任意在线文档系统化地转换为目标格式的可复用模块。管道为
输入适配(取正文)→ 结构化解析 → 格式转换 → 质量校验与输出。
引擎 scripts/convert.py 仅依赖 Python 标准库(可选增强:若环境已装
trafilatura,HTML 正文抽取质量更佳),可在任意环境直接运行;目标格式新增
html(自包含静态 HTML)。另外提供多个输入适配器脚本,覆盖登录墙/二进制/合集场景:
scripts/feishu_fetch.py:飞书云文档经lark-cli连接器取正文(单篇 / 整空间批量)。scripts/feishu_img_localize.py:飞书文档图片本地化——重抓全文抽取file_token并下载到
assets/{idx}_{n}.png(命名与 build 对齐),是「图片永不失效」合集的前半段。scripts/pdf_to_md.py:本地文本型 PDF → 结构化 Markdown(PyMuPDF 字号分层 + bullet 优先)。scripts/geektime_pdf.py:JS 渲染 PDF 预览页(极客时间/微伴)→ 真实 PDF 逆向下载。scripts/xiaohongshu_fetch.py:小红书笔记 → Markdown(混合抓取:SSR 零依赖解析__INITIAL_STATE__
的.note/.noteCard优先,遇登录墙/空内容回退 Playwright 浏览器渲染;支持--ocr调系统
tesseract识读图中文字、或--mode ocr-local对本地图目录 OCR;图片下载超时 180s 容错慢 CDN)。scripts/build_static_html.py:多篇 Markdown → 类飞书风格静态 HTML 合集(带分章导航);
配--assets-dir+--embed-images可将本地图片 base64 内嵌,生成永不失效的单文件。scripts/wiki_export.py:一键把整个飞书 wiki 空间(递归全部节点)→ 静态 HTML 合集;
内部串起「遍历节点树 → 逐篇取 Markdown → 逐篇落地图片 → 合成整树导航 HTML」,可断点续跑。scripts/lark_kb_crawl.py/lark_kb_download.py/lark_kb_receiver.py/lark_kb_build.py:
Lark/Feishu 知识库整库导出(含附件下载) 四件套(内容驱动 BFS,tenant-agnostic):
从根 token 递归抓全量页面 → 浏览器转发下载全部附件(PDF/PPTX/MD,落files/,
绕过drive:file:downloadscope 缺失)→ 合并为带导航的自包含静态 HTML。
排版要点(lark_kb_build.py v3):① 页面标题取正文首行 H1(crawl 常把 title 错存为 token 尾),
并剥离正文首行重复 H1;② 正文内其余 H1 降级为 H2(飞书文档常以#当小节标题,直接渲染成
巨型标题会破坏层级,已验证 idx003 一页 13 个 H1 全降级);③ 标题首尾多余角括号/空白清理
(飞书横幅文本如< X >);④ 飞书语义组件中和——<chat_card>(群聊卡片)转可见卡片、
裸<select>/<input>等文档提及的控件标签转义为字面文本(避免被当真实空控件渲染);
⑤ 飞书 callout(blockquote)高亮卡片样式;⑥ inline 图破图→「🖼️ 图片(飞书在线图·点击在线查看)」
占位卡片(保留原链可点开,真正离线看图须重 crawl 取新 authcode);⑦ 表格横向滚动、附件卡片显示大小、
左侧导航当前章节高亮(IntersectionObserver)、返回顶部按钮、打印样式(离线 PDF)、移动端自适应。详见下方
「Lark/Feishu 知识库整库导出(含附件下载)子管道」章节。scripts/video_to_md.py:在线视频(抖音等反爬站点)→ 结构化简体中文 Markdown 一体化流水线:
Playwright 渲染拿直链 + 导出 cookie → curl 下载 → ffmpeg 抽音频 → faster-whisper 转写
→ opencc 繁转简 → 按章节分组生成 MD(含「观点 / 论述 / 建议」三段式总结占位,由 agent
基于转写稿提炼)。详见下方「视频 → Markdown 子管道」章节。scripts/x_to_md.py:X(Twitter)长文 → Markdown。经 browser-skill(bskCLI 驱动已登录
浏览器)渲染文章 DOM,剔除嵌套的引用卡/回复(只保留文章本体,不含评论区),用convert.py
结构化后清理作者信息噪声、升级章节标题,并把正文里的pbs.twimg.com图片真实下载到
assets/NN.jpg(CN 沙箱直连被代理 502 时,改走浏览器内fetch→base64落盘)。本步骤需要
browser-skill,是 X 流程中唯一联网/依赖浏览器的环节。
兼容 X Article 内嵌图(v1.8.3 修复):X Article 长文(URL 形如x.com/i/status/...或
x.com/<handle>/article/...)的内嵌图采用相对媒体路由/<handle>/article/<id>/media/<mid>,
旧逻辑只匹配pbs.twimg.com/media/直链,导致这类图既不下传、又残留空链接。现已用<mid>
直接构造pbs.twimg.com/media/<mid>?format=jpg&name=large真链下载,并把相对路由与空链接
[](rel)改写为可见的本地图片;作者 handle 也可从相对路由反推(不再显示「X 用户」)。
(v1.8.4 修复)媒体懒加载稳定性 + 双惊叹号兜底 + 视频链接:① X 双向懒加载改为「逐个媒体滚入视口- DOM probe 探测 pbs 直链,最多 6 轮重试,main 层再兜底重试 1 次」,避免偶发抓到 0 图;② 浏览器内把
媒体<a>(CSS background-image 的真链)就地替换为<img>以保持原文位置一致,并把convert.py
偶发产出的!双惊叹号在collect_and_download_images末道兜底折叠为单!;③ 纯数字<mid>
的视频媒体保留<a href>并改写为「📹 媒体·点击在 X 查看」可点击链接(位置不变)。 scripts/x_md_to_html.py:X 文章 Markdown → 自包含离线 HTML(article-magazine 风格,
图片 base64 内嵌,零外部依赖)。输入是上一步(或任意现成)的本地 MD + 其assets/目录,
不调用 browser-skill、不联网,可反复重跑、随处分享。详见下方「X(Twitter)长文 → Markdown →
离线 HTML 子管道」章节。
接受标准化输入参数,返回标准化输出:
source_url(必填):源文档 URL 或文档链接;若已用其他工具/脚本取到正文,则走 stdin 管道模式。target_format(必填):markdown|json|concise-text|html。filter_rules(可选):JSON 字符串或 JSON 文件路径,用于裁剪章节/元素。
Input Contract
| 参数 | 必填 | 说明 |
|---|---|---|
source_url |
是 | 源 URL;若已用其他工具取到正文,则走 stdin 管道模式,此参数留空 |
target_format |
是 | markdown / json / concise-text / html |
filter_rules |
否 | 见 references/format-specs.md 第 4 节(章节排除、元素开关等) |
输出:转换后的内容(stdout 或 --output 文件)+ 校验/摘要报告(stderr JSON,或 --report 文件)。
Workflow
按四个模块顺序执行。模块 1(输入适配)在 agent 层路由;模块 2–4 由引擎统一处理。
模块 1 — 输入适配层:识别源类型并提取正文
依据 references/source-adapters.md 的决策树识别源类型,取得干净正文:
- HTML 页面(静态):直接用引擎 URL 模式
python3 scripts/convert.py --url URL --format FORMAT。 - HTML 页面(JS 渲染/SPA)或 PDF / 连接器文档:用网页抓取工具或对应
连接器(如腾讯文档连接器,file_id取
URL 末段)取到正文,写入临时文件后以 stdin 管道交给引擎:
cat raw.md | python3 scripts/convert.py --format FORMAT。 - Markdown 源 / API 参考:用命令行或读取原文取得内容后,管道传入引擎。
- 飞书云文档(wiki / docx):登录墙,必须走
lark-cli连接器
(见references/source-adapters.mdF 节): - 单篇:
python3 scripts/feishu_fetch.py doc --url <wiki_url> [--output x.md] - 整空间:
python3 scripts/feishu_fetch.py space --url <wiki_url> --out-dir ./feishu_md - 取到的 Markdown 即正文,可直接管道给
convert.py或交给build_static_html.py。 - 本地文本型 PDF:
python3 scripts/pdf_to_md.py in.pdf --output out.md [--validate]
(PyMuPDF 字号分层,bullet 优先于标题;详见 source-adapters G 节)。 - JS 渲染的 PDF 预览页(极客时间/微伴):
python3 scripts/geektime_pdf.py "<预览URL>" --output x.pdf
逆向真实 PDF(参数直推 + Headless Chrome 回退;详见 source-adapters H 节),
下载后再用pdf_to_md.py转 MD。 - 小红书笔记(登录墙 + 签名接口):
python3 scripts/xiaohongshu_fetch.py --url <url> [--cookies cookies.json] [--output x.md] [--assets-dir ./assets]
(详见 source-adapters J 节)。混合策略:先 SSR 解析window.__INITIAL_STATE__(零依赖),
登录墙/空内容自动回退 Playwright 无头渲染(需pip install playwright && playwright install chromium - 登录 cookie);取到的 Markdown(含作者/互动/话题元信息 + 图片落地
./assets)即正文,
可直接管道给convert.py校验或转 JSON/HTML。 -
多 Markdown 合集 → 静态 HTML 书:
python3 scripts/build_static_html.py --input-dir ./md --output 合集.html
(类飞书排版、分章导航;source-adapters I 节)。若 MD 来自飞书且图片链接已带时效令牌,
先feishu_img_localize.py把图落地到./assets,再build_static_html.py --assets-dir ./assets --embed-images生成图片内嵌、永不失效的单文件(见 I 节与下方速查)。 -
在线视频(抖音 / B站 等反爬站点):
python3 scripts/video_to_md.py --url <视频页URL> --out-dir ./video_md [--model base]
(详见下方「视频 → Markdown 子管道」章节 K 节)。该脚本内部完成「渲染拿直链 → 下载 → 抽音频 →
转写 → 繁转简 → 生成 MD」,并预留三段式总结占位;agent 须基于转写稿填写「观点 / 论述 / 建议」,
且保留原始视频链接溯源。
判定要点:若 --url 模式返回仅外壳或空内容,立即切换到网页抓取工具/连接器路径,
不要反复重试同一失败方式。始终保留原始 source_url 用于溯源。
模块 2 — 内容结构化解析
引擎自动完成,无需 agent 干预:
- HTML 经内置
HTMLToMarkdown转为 Markdown(剔除nav/header/footer/aside/ script/style,保留标题层级、代码块语言、表格对齐、列表、引用、图片、链接)。 - Markdown 经
parse_markdown解析为层级节点树,并抽取扁平索引:
headings / code_blocks / tables / lists / images / links。 - 标题按层级嵌套;列表按
ul/ol与缩进分组;表格捕获列对齐(:---/---:/:---:)。
模块 3 — 格式转换引擎
按 target_format 选择输出(详见 references/format-specs.md 第 1–2 节):
markdown:层级连续的结构化 Markdown,末尾附 CONVERSION SUMMARY 注释块。json:含meta/nodes层级树 /structure扁平索引 /content_markdown/
validation的结构化 JSON(schema 见references/format-specs.md第 2 节)。concise-text:面向 LLM 上下文的精简纯文本(去图、压表、代码截断、保留主干)。
filter_rules 在解析后、转换前作用于节点树(剔除指定章节/元素),
validation.stats 在过滤后重新统计,反映最终输出。
模块 4 — 质量校验与输出
引擎自动校验并写入 validation:
- 标题层级连续性(不允许 H1 直接跳 H3);
- 代码块围栏完整性(奇偶检查);
- 表格有效性(列数 > 0);
- 链接/图片/代码/表格计数统计。
validation.passed=true 表示无阻断问题;issues 列出发现项。
转换摘要含 source_url / source_type / fetched_at / title / 字符数 / 各元素计数 / 校验结论。
最终动作:将输出内容写入文件(用 --output),并以文件形式呈现给用户;
同时口头汇总源类型、目标格式、校验结论与内容规模。
Engine Usage(速查)
# URL 模式:抓取 + 抽取 + 转换
python3 scripts/convert.py --url URL --format markdown --output out.md
# 管道模式:已取正文(HTML/MD)经 stdin 结构化
cat raw.md | python3 scripts/convert.py --format json --report report.json
# 单文档转自包含静态 HTML
python3 scripts/convert.py --format html --output page.html < raw.md
# 精简文本 + 过滤
cat raw.html | python3 scripts/convert.py --format concise-text \
--filter '{"exclude_sections":["References"],"include_images":false}'
# 飞书 wiki 整空间批量转 MD(需 lark-cli 授权)
python3 scripts/feishu_fetch.py space --url <wiki_url> --out-dir ./feishu_md --structured
# 本地 PDF 解析为结构化 MD(再经引擎校验)
python3 scripts/pdf_to_md.py in.pdf --output out.md --validate
# 极客时间预览 PDF 逆向下载(再用 pdf_to_md 转 MD)
python3 scripts/geektime_pdf.py "<预览URL>" --output course.pdf
# 小红书笔记 → Markdown(混合抓取;取到的 MD 再交引擎校验/转格式)
python3 scripts/xiaohongshu_fetch.py --url "https://www.xiaohongshu.com/explore/<id>" \
--cookies cookies.json --output note.md --assets-dir ./assets
# 分享链接(带 xsec_token)匿名即可取全文,无需 cookie:
# python3 scripts/xiaohongshu_fetch.py --url "https://www.xiaohongshu.com/discovery/item/<id>?source=webshare&xsec_token=..." --output note.md
# 仅 SSR(零依赖)+ 内嵌远程图片 URL(不下载,联网环境可看图):
# python3 scripts/xiaohongshu_fetch.py --url URL --mode ssr --no-download-images --output note.md
# 下载图片并把图中文字 OCR 进 MD(需先装 tesseract:brew install tesseract tesseract-lang):
# python3 scripts/xiaohongshu_fetch.py --url URL --output note.md --assets-dir ./assets --ocr
# 图片已下到本地目录时,直接对本地图 OCR 并组装 MD(不联网):
# python3 scripts/xiaohongshu_fetch.py --mode ocr-local --images-dir ./assets --title "标题" --author "作者" --output note.md --ocr
# 再经引擎校验/转 JSON 或 HTML:
# cat note.md | python3 scripts/convert.py --format json --report r.json
# 一键封装(本机下载图片到 ./assets + 可选 OCR,图片可正常加载):
# bash scripts/xhs2md.sh "<分享链接>" --ocr
# 多 MD 合集 -> 类飞书静态 HTML 书
python3 scripts/build_static_html.py --input-dir ./feishu_md --output 合集.html \
--title "企业级 AI 编程实战营 · 飞书云文档合集"
# 飞书文档图片本地化(重抓全文、下载到 ./assets,命名与 build 对齐)
python3 scripts/feishu_img_localize.py --space-url "<wiki_url>" \
--md-dir ./feishu_md --assets-dir ./assets
# 或显式给定令牌(与 MD 排序一一对应,最稳):
# python3 scripts/feishu_img_localize.py --doc-tokens AAAA,BBBB,CCCC \
# --md-dir ./feishu_md --assets-dir ./assets
# ★ 整个飞书 wiki 空间 -> 静态 HTML 合集(一键递归导出,可断点续跑)
python3 scripts/wiki_export.py --space-url "<wiki_url>" --out-dir ./赋范空间-wiki
# 图片总体积 < 150MB 时自动额外生成 index.embedded.html(base64 单文件);
# 强制内嵌:加 --embed;仅用已有节点树:--tree ./wiki_tree.json(跳过遍历)
# 在线视频 → 结构化简体中文 Markdown(抖音等反爬站点;agent 再补三段式总结)
python3 scripts/video_to_md.py --url "https://www.douyin.com/video/7658674342846287146" \
--out-dir ./video_md --model base
# 长音频若内存充足可换 small;转写前务必确保环境变量:
# HF_ENDPOINT=https://hf-mirror.com HF_HUB_DISABLE_XET=1
# 依赖缺失时加 --install 自动装(playwright + faster-whisper + opencc + chromium)
# 脚本会自动生成 <标题>-转写.md(含元信息 + 章节 + 三段式总结占位 + 完整转写稿)
# ===== X(Twitter)长文 → Markdown → 离线 HTML =====
# 前置:browser-skill 已安装配置(bsk doctor 全 ok);X 文章转 MD 必须走已登录浏览器
# 步骤 1:X 文章 DOM -> 干净 MD(自动落地 12 张图到 ./assets,剔除评论区)
python3 scripts/x_to_md.py --url "https://x.com/<handle>/status/<id>" \
--output article.md --assets-dir ./assets
# 步骤 2:现成 MD -> 自包含离线 HTML(图片 base64 内嵌,**无需 browser-skill/联网**)
python3 scripts/x_md_to_html.py --md article.md --assets ./assets --out article.html
# --title / --author / --date 可覆盖自动解析的元信息;不传则尝试从 MD 顶部来源块解析
# 图片 base64 内嵌 -> 永不失效的单文件 HTML(需先跑上一步落地图片)
python3 scripts/build_static_html.py --input-dir ./feishu_md --output 合集.html \
--assets-dir ./assets --embed-images
# ===== Lark/Feishu 知识库整库导出(含附件下载)=====
# 1) 爬取(内容驱动 BFS,落 md/raw + pages/attachments/bitables.json)
python3 scripts/lark_kb_crawl.py --root-token <ROOT_TOKEN> \
--wiki-base https://bytedance.larkoffice.com/wiki --out-dir ./kb
# 飞书中国租户:--wiki-base https://<租户>.feishu.cn/wiki
# 2) 下载附件(自动拉起接收服务;需 bsk 已登录浏览器;飞书中国加 --endpoint)
python3 scripts/lark_kb_download.py --out-dir ./kb --port 8891
# 3) 构建静态 HTML(--embed 额外生成图片内嵌单文件)
python3 scripts/lark_kb_build.py --out-dir ./kb --title "知识库静态归档" --embed
- 引擎报告(含
validation)始终写入 stderr,stdout 保持纯净内容,便于分别读取。 --no-trafi:强制使用内置抽取器(禁用可选依赖 trafilatura)。- 详细 schema 与过滤字段见
references/format-specs.md;源类型路由见
references/source-adapters.md。
X(Twitter)长文 → Markdown → 离线 HTML 子管道
X/Twitter 是 JS 渲染 + 登录墙 SPA,沙箱 curl/WebFetch 只能拿到空壳预览;正文与图片必须靠
已登录浏览器渲染。流程拆成两段、职责解耦——只有第一段需要 browser-skill,第二段纯本地。
这样当你已经有一份抓好的 MD 时,第二段可无限次重跑、无需再碰浏览器。
关键设计决策(务必遵守)
- MD 是中间产物,且是「只含文章本体」的 MD:
x_to_md.py在抽取 DOM 时即剔除嵌套的
引用卡 / 回复(只保留article主节点内的正文),绝不收录评论区。 - 两段解耦:X→MD 与 MD→HTML 相互独立。MD 一旦落地,MD→HTML 不需 browser-skill、不需联网,
适合反复调样式 / 批量重渲染 / 断点续跑。 - 图片真实落地:正文里的
pbs.twimg.com图在 X→MD 阶段就下载到assets/NN.jpg;
MD→HTML 阶段再 base64 内嵌,最终 HTML 零外部图片依赖、可离线打开。
前置:browser-skill 预检(仅 X→MD 需要)
X→MD 必须能驱动已登录浏览器。跑 x_to_md.py 前先确认 browser-skill 已安装配置:
- 安装/配置说明见 https://raw.githubusercontent.com/Tencent/BrowserSkill/main/AGENT_INSTALL.md
- 预检命令:command -v bsk 存在且 bsk doctor 全部 ok;否则 x_to_md.py 会打印安装指引并退出。
- bsk 连接不稳定(常短暂显示 0 browsers),脚本会轮询 bsk status 等待重连后重试。
- CN 沙箱直连 pbs.twimg.com 会被代理返回 502;此时脚本自动改走浏览器内
fetch → FileReader.readAsDataURL → base64 解码落盘,无需手动处理。
两段流水线
步骤 1 — X 文章 → Markdown(x_to_md.py,需 browser-skill)
python3 scripts/x_to_md.py --url "https://x.com/<handle>/status/<id>" \
--output article.md --assets-dir ./assets
脚本行为:启动 bsk 会话 → 导航到帖子 → 轮询等待文章 DOM 与图片加载 →
取 document.querySelector('article').outerHTML(剔除嵌套 article 排除回复)→ convert.py
--format markdown 结构化 → 清理作者信息噪声(@handle / 浏览量等,锚定首个封面 figure 切割)
→ 升级「一、二、」等章节标题为 ## → 下载 pbs.twimg.com 图片到 assets/NN.jpg
→ 改写 MD 图片引用为本地相对路径 → 输出带溯源块与 CONVERSION SUMMARY 的 MD。
步骤 2 — Markdown → 离线 HTML(x_md_to_html.py,无需 browser-skill / 联网)
python3 scripts/x_md_to_html.py --md article.md --assets ./assets --out article.html
# 可选:--title / --author / --date 覆盖自动解析的元信息
脚本行为:读 MD → 去掉 CONVERSION SUMMARY 注释 → 按行解析标题/章节/图片/代码块/引用/列表
→ 12 张本地图 base64 内嵌 → 套用 article-magazine 模板(hero + 单栏 + 深色代码块 + 文末卡片)
→ 输出零外部依赖的单文件 HTML。已用现有成品 MD 验证:12 图全内嵌、0 个外部 pbs.twimg 引用、
11 个 h2 + 4 个 h3 + 16 个代码块、来源卡片保留。
断点续跑与复用
- 已有现成 MD(如本 skill 历史上已抓好的
x_post_*.md):直接跑步骤 2 即可,不要重抓。 - 图片缺失:步骤 2 对找不到的
assets/NN.jpg会静默跳过(该图位置留空),不影响其余渲染。 - 样式调整:只改
x_md_to_html.py内CSS常量,重跑步骤 2 即时生效,与抓取无关。
> 注:早期「直接 DOM → HTML」适配器已被本两段流程(x_to_md.py + x_md_to_html.py)取代并已移除,新任务请勿使用。
视频 → Markdown 子管道(抖音等反爬站点)
把在线视频(尤其是抖音这类 SSR 空壳 + 视频直链带签名限时的站点)转为带时间戳、按章节分组、
含「观点 / 论述 / 建议」三段式总结的简体中文 Markdown。统一入口是
scripts/video_to_md.py(六步流水线,全程断点续跑)。
适用边界
- 目标站点需 JS 渲染(抖音 SSR 是空壳),或视频直链带签名/限时(
yt-dlp直连报
Fresh cookies needed)。 - 本地需
ffmpeg;可装playwright+faster-whisper+opencc(无 GPU 也能跑,CPU + int8)。 - 转写为机器识别,可能存在同音错别字,须标注「仅供参考」。
六步流水线(脚本已封装)
- 预检/安装:
command -v ffmpeg、pip install playwright faster-whisper opencc-python-reimplemented && playwright install chromium;脚本--install可自动装。 - 渲染拿直链 + cookie + 元数据:Playwright 渲染页面,监听网络截获
v*.douyinvod.com/.../__vid=<id>的 mp4 直链,导出 cookie(Netscape);渲染后从 DOM 抽
作者/文案/章节要点/标签/发布时间。注意:抖音 SSR HTML 无 og 元信息、#RENDER_DATA
递归解析易失败,元数据必须在渲染后用document.body.innerText解析;章节要点形如
00:00\n引言交替行。 - 立刻下载(直链限时!抓到马上下):
curl -b cookie -e "https://www.douyin.com/" -A <UA> -o video.mp4 <直链>;下完用ffprobe取时长。 - 抽音频:
ffmpeg -i video.mp4 -vn -ac 1 -ar 16000 -f wav audio.wav。 - 转写:
faster-whisper,语言zh、beam_size=1、vad_filter=True;默认base
模型(见下方 CN 沙箱坑 4)。 - 繁→简:
base模型默认输出繁体,经opencc(t2s) 转简体(调用方无条件执行,
不要等抽样发现繁体才补)。 - 生成 MD:脚本按章节时间点把分段归组,输出
<标题>-转写.md,结构为
# 标题→## 一、视频文案→## 二、章节要点→## 三、内容总结(观点/论述/建议)
→## 四、完整转写稿(每章### MM:SS 名称,段内- \[start-end]` 文本`)。
三段式总结(观点 / 论述 / 建议)— agent 必做
脚本生成 MD 时只写入占位(### ▍观点/论述/建议 下留「待填写」),agent 必须基于
transcript.json + 章节要点推理提炼,不可照抄,并保留原始视频链接溯源:
## 三、内容总结(观点 / 论述 / 建议)
> **原始视频**:[<视频URL>](<视频URL>)(点击溯源至原片,下文各论点均出自该视频转写稿)
### ▍观点:视频表达的核心主张
- 提炼 3–5 条视频最核心的主张/结论(去细节、只留论点和判断)。
### ▍论述:支撑观点的关键论据与逻辑脉络
- 按视频自有顺序(如「拆→仿→练→创→循环」)梳理论据链条;每条尽量对应转写稿具体章节。
### ▍建议:基于视频内容的可操作实践
- 给出 4–6 条可直接落地的动作建议,每条简短可执行。
> 说明:以上总结由本视频转写稿提炼,遵循「观点 / 论述 / 建议」框架;细节以原始视频及完整转写稿为准。
原始视频链接必须与顶部元信息块的「来源」一致,确保内容可溯源。
CN 沙箱坑(已统一说明)
CN 沙箱相关坑(抖音登录墙、HF_ENDPOINT 代理 502、HF_Xet 401、转写 OOM(137) 等)已固化进脚本注释,并在上文「质量门禁与 CN 沙箱 pre-flight」统一列出,此处不重复。执行视频转写前务必先读该节并满足 pre-flight。
产出清单
video.mp4 · audio.wav · transcript.json · <标题>-转写.md(最终交付,含 agent 补全的总结)。
Lark/Feishu 知识库整库导出(含附件下载)子管道
把整个 Lark/Feishu wiki 知识库(含全部子页面与内嵌附件:PDF / PPTX / Markdown / 图片)
递归导出为自包含、可离线浏览的静态 HTML 合集,附件以本地文件形式落地到 files/,
图片落地到 assets/。与 wiki_export.py(飞书中国租户、节点树遍历、仅落地图片)互补:
本模块用内容驱动 BFS(从 <cite> 发现子页、从 <source> 收集附件),且一并下载非图片附件
(drive:file:download scope 缺失时,用浏览器 fetch 转发方案绕过)。
适用边界
- 正文抓取走
lark-cli docs +fetch,对 bytedance.larkoffice.com(Lark 国际) 与
*.feishu.cn(飞书中国) 两租户均可用(user token 自动 refresh)。 - 附件下载:Lark 国际租户
drive:file:downloadscope 常缺失(403 missing_scope),
bot 身份也看不到用户 drive 文件 → 不能用 lark-cli 下载附件,必须走浏览器转发
(见下方「关键设计」)。飞书中国租户若已授权drive:file:download可直接用 lark-cli,
否则同样回退浏览器转发(--endpoint换成internal-api-drive-stream.feishu.cn)。
四步流程(脚本已分工)
- 爬取(lark_kb_crawl.py):内容驱动 BFS,从根 token 出发,逐页取原始 XML +
规整 Markdown,提取<cite doc-id>(子页)、<source mime token>(附件)、<bitable>;
落盘OUT/md/ OUT/raw/,产出pages.json attachments.json bitables.json。 - 起本地接收服务(lark_kb_receiver.py):监听
127.0.0.1:PORT,接收浏览器转发的
Lark 文件原始字节,写盘到OUT/files/或OUT/assets/(二进制直写,免 base64 膨胀)。
下载脚本会自动拉起本服务,无需手动启动;如需手动:python3 lark_kb_receiver.py 8891 ./kb。 - 下载附件(lark_kb_download.py):遍历
attachments.json,对每个 token 用bsk
(browser-skill)驱动已登录浏览器fetchLark drive-stream 端点(带凭据)→ Blob POST 到
本地接收服务落盘。断点续跑(已存在且>0 跳过),会话失效自动重建。 - 构建静态 HTML(lark_kb_build.py):后处理各页 MD(
<source>→本地文件卡片 /<img>、
站内cite→#page-XXX锚点、图片→assets/),合并为带左侧导航的index.html;
--embed额外生成index.embedded.html(图片 base64 内嵌)。
关键设计决策(务必遵守)
- 附件走浏览器转发,非 lark-cli:
document.cookie仅有 343B(无 HttpOnly 鉴权 cookie),
curl -b cookie直连返回 401 → 必须由已登录浏览器fetch(..., {credentials:"include"})取字节,
再经 localhost(豁免 mixed-content)POST 落盘。localhostContent-Type:text/plain为简单请求免预检。 - 大文件用 Blob 转发:单 PPTX 可达 59MB,base64 会膨胀且压内存 → 全程二进制直写。
- 原生
<table>内 Markdown 链接不被 Python-Markdown 转换 →<source>替换为原生
<a href="files/...">/<img src="assets/...">,绝不输出[..](..)Markdown 语法(复盘已验证)。 - 飞书原始
<table>保留:normalize_feishu_content不处理<table>/<source>/<figure>/<bitable>,
表格以原生 HTML 保留,故附件卡片必须原生<a>/<img>。 - 站内 cite 用锚点:单文件 HTML 内,库内
wiki/<token>链接改#page-%03d锚点(非html#...)。 - bitable 仅占位:不深抓多维表格,渲染为
[📊 数据表/Bitable:原文在线查看]提示。 - 多租户兼容:
<cite>/<img>的 host 不限 larkoffice/feishu,按 token 是否在库内判定改写。
前置
lark-cli已授权(user):lark-cli auth login ...(详见 feishu_fetch.py 提示)。browser-skill已安装配置、bsk doctor全 ok(仅下载附件阶段需要;爬取与构建纯本地)。- Python 依赖:
markdown(构建阶段pip install markdown,已在 requirements.txt)。
用法
# 1) 爬取(Lark 国际示例;飞书中国把 --wiki-base 换成 https://<租户>.feishu.cn/wiki)
python3 lark_kb_crawl.py --root-token Io1Ewq0l0iLsMckBOhBcZPaVn3d \
--wiki-base https://bytedance.larkoffice.com/wiki --out-dir ./kb
# 或直接从根链接推导 wiki-base + root-token:
# python3 lark_kb_crawl.py --root-url "https://bytedance.larkoffice.com/wiki/Io1E...?from=from_copylink" --out-dir ./kb
# 2) 下载附件(自动拉起 lark_kb_receiver.py;需 bsk 已登录浏览器)
python3 lark_kb_download.py --out-dir ./kb --port 8891
# 飞书中国租户加:--endpoint "https://internal-api-drive-stream.feishu.cn/space/api/box/stream/download/preview/%s/?preview_type=16"
# 3) 构建静态 HTML(默认 index.html + 可选 --embed 内嵌单文件)
python3 lark_kb_build.py --out-dir ./kb --title "我的知识库静态归档" --embed
产出清单
./kb/md/(各页 MD)· ./kb/raw/(各页原始 XML)· ./kb/files/(PDF/PPTX/MD 等附件)·
./kb/assets/(图片)· ./kb/index.html(本地引用)· ./kb/index.embedded.html(图片内嵌)。
质量门禁与 CN 沙箱 pre-flight(必读,对应复盘 N1–N6)
质量门禁(每次改完 skill 必跑)
python3 scripts/validate_skill.py:校验 frontmatter(name/version 格式/
disable=false/agent_created)+ SKILL.md 引用的脚本全部存在 + 每个脚本 py_compile。python3 scripts/self_test.py:在 validate 基础上,用真实交付物断言「build 非内嵌
模式产出本地assets/引用、无过期飞书 URL 残留」——以产物验证文档声称的能力,
杜绝「声称即正确」(复盘 S3/N5)。- 任何改动后必须两脚本均 PASS 才交付;失败即阻断(复盘 M7)。
CN 沙箱 pre-flight(视频/转写/大模型下载通用)
- 登录墙:抖音/B站/小红书等
yt-dlp直连报Fresh cookies needed→ 用
Playwright 渲染 + 网络监听拿签名直链 + 导出 cookie 下载(M2)。 - HF 代理 502:直连 HuggingFace 报 502 → 设
HF_ENDPOINT=https://hf-mirror.com。 - HF Xet 401:镜像后仍
CAS Client Error 401 (cas-server.xethub.hf.co)→ 加
HF_HUB_DISABLE_XET=1回退普通 HTTP。 - 转写 OOM(137):
small+beam=5在长音频被 SIGKILL → 默认MODEL=base+
beam_size=1;转写前pkill chrome/playwright释放内存(空闲页从 ~6k 升到 ~75k 才稳)。 - 依赖纪律:全装受管 venv,HF 等用镜像环境变量,绝不污染全局(M10)。
版本与备份纪律(N2/N6)
- 每次实质变更必须 bump
version(格式x.y.z),并同步更新 SKILL.mddescription
以反映真实脚本/能力;禁止版本号滞后。 - 每次 bump 必须同步生成桌面备份
online-doc-convert-vX.Y.Z-YYYYMMDD.zip;
版本号 / 备份 / SKILL.md 三者须对齐。
Edge Cases & Notes
- 腾讯文档/金山/飞书等连接器 PDF:网页抓取工具只返回 viewer 外壳,必须用对应
MCP 连接器取正文再管道转换(已在references/source-adapters.md说明)。 - 飞书 wiki / docx(登录墙):匿名网页抓取工具 /
--url必然 302 登录拦截;必须走
lark-cli连接器(scripts/feishu_fetch.py,需先lark-cli auth login授权)。
取到的 Markdown 即干净正文,可直接管道给引擎或交给build_static_html.py。 feishu_fetch.doc返回结构易错点(已修):lark-cli docs +fetch --doc-format markdown
的 stdout 总是 JSON,正文在data.data.document.content(document 嵌在 data 内,两级嵌套),
且为「混合 Markdown + 飞书 XML」(<title>/<callout>/<grid>/<column>/<button>/<cite>/<h1-4>/<p>/<b>/<code>)。
fetch_doc_markdown已修正:正确下钻data.data.document.content,并normalize_feishu_content()
把上述块转成纯 Markdown(callout→引用、grid/column→平铺、button OpenLink→链接、h1-4→#)。
注意标题正则必须写<h%d>(漏写h会变<4>永不匹配)。- 本地 / 预览 PDF:文本型 PDF 用
scripts/pdf_to_md.py(PyMuPDF 字号分层,
正文基准字号取非列表行 mode以避免列表符号抬高基准、bullet 优先于标题);
JS 渲染的预览 PDF(极客时间/微伴)用scripts/geektime_pdf.py逆向下载真实 PDF。 - 多文档合集静态 HTML:
scripts/build_static_html.py会给每篇标题 ID 加命名空间前缀,
保证跨文件同名词(如agent/31)不冲突、目录锚点零失效。 - 不内嵌模式(默认):图片
src指向本地assets/相对路径(命名与
feishu_img_localize对齐assets/{idx}_{k}.{ext}),文件夹可移植、永不失效;
图片缺失时onerror自动隐藏、图说仍可读。(旧文档曾误称“保留过期飞书 URL”,
已在复盘 S3/N5 中纠正——实际实现早已改为本地引用。) - 内嵌模式(
--assets-dir ./assets --embed-images):把assets/{idx}_{n}.{ext}编码为
base64 data URI 内联,图片永不失效、单文件可移植。需先用feishu_img_localize.py把图落地。 - 关键坑:飞书导出的 Markdown 常有
```Plain Text(语言标注带空格)的代码围栏,
Python-Markdown 不认带空格的 info-string 会令围栏错配、把中间图片整段吞进代码块导致丢图;
build 在转换前自动规整为```text。 - 图片解析顺序:内嵌模式在 markdown 转换前先把
抽出占位符、转换后还原,
规避超长 alt 触发解析器丢图;保证图片数量/顺序与assets/命名精确对齐。 - 本地化实现三处易错点(已修):
feishu_fetch.ensure_auth()须读lark-cli auth status --json的
identities.{user,bot}.status=="ready"(旧版误查authed/authorized键而误判未授权)。feishu_img_localize.fetch_doc_img_tokens()的输出是 JSON,图片 token 在
data.document.content(XML 字符串,引号被 JSON 转义为\");必须解析 JSON 取
content再用src="([^"]+)"抽取,直接正则原始转义输出会 0 命中。feishu_img_localize调用ff._run()时不要再传timeout=(_run内部已固定
timeout=TIMEOUT,重复传参会multiple values for keyword argument 'timeout'报错)。
- MIME 嗅探:
build_static_html.img_data_uri()按文件魔数判定真实 MIME,而非扩展名——
飞书media-download有时把 PNG 存成.jpg,按扩展名会渲染失败。 - html 输出:单文档
--format html产出自包含单文件(内联 CSS,零硬依赖;代码高亮用可选
pygments)。与build_static_html.py区别:前者转单篇,后者整合多篇。 - 分页 / 懒加载:多次抽取后拼接,再统一传入引擎。
- 无法抽取:明确告知用户限制,仍输出已获文本并在
validation.issues标注。 - 特殊图表:源文档中的可视化图表多为连接器内部图片,无法直接访问时以
[图:…]占位或尽量还原文本,不臆测重绘。 - 小红书笔记:详情页对匿名访问强制登录墙,正文经签名接口(
x-s/x-t/x-bogus)
返回,全文必须依赖登录态 cookie(--cookies);无 cookie 时 SSR 仅能拿标题/残文,
脚本会自动回退浏览器渲染仍需 cookie。图片走图床 CDN 带防盗链与时效,默认下载到
./assets并改写本地相对路径(对齐飞书图片本地化范式),可后续经build_static_html.py --embed-imagesbase64 内嵌为单文件;视频笔记以封面图 + 提示占位。正文文字常嵌于图片内,
OCR 识别不在本期范围。 - X(Twitter)长文:X→MD 必须走已登录浏览器(browser-skill),沙箱
curl/WebFetch仅得空壳;
抓前务必bsk doctor全 ok,且bsk连接不稳定需轮询重试。图片 CDNpbs.twimg.com在 CN 沙箱
直连被代理 502 拦截,改用浏览器内fetch→base64落盘(脚本已内置)。MD 一旦落地,MD→HTML
不再需要 browser-skill 也不联网——已有现成 MD 时切勿重抓,直接用x_md_to_html.py渲染。
务必只收录文章本体、剔除评论/回复(DOM 阶段即剔除嵌套article)。 - Lark/Feishu 知识库整库导出(含附件下载):
lark_kb_*四件套走「内容驱动 BFS 爬取 →
浏览器转发下载附件 → 合并静态 HTML」。关键约束(已验证):① Lark 国际租户
drive:file:downloadscope 常缺失(403 missing_scope)且document.cookie仅 343B(无
HttpOnly 鉴权 cookie,curl直连 401),附件必须由已登录浏览器fetch转发落盘,不能走
lark-cli;② 大文件(单 PPTX 达 59MB)用 Blob POST 到 localhost 接收服务二进制直写,免 base64
膨胀;③ 飞书原生<table>内 Markdown 链接不被 Python-Markdown 转换,故<source>必须输出原生
<a href="files/...">/<img src="assets/...">;④ 库内wiki/<token>链接改#page-%03d
锚点。两租户(bytedance.larkoffice.com / *.feishu.cn)通用,仅--wiki-base与下载
--endpoint需按租户切换。