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/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 流程中唯一联网/依赖浏览器的环节。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。
- 登录 cookie);取到的 Markdown(含作者/互动/话题元信息 + 图片落地
-
多 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
- 引擎报告(含
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 补全的总结)。
质量门禁与 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)。
Scan to join WeChat group