用途
pdf-to-html 用于将 PDF 转换为一个自包含、可读的 HTML 文件,保留图片、表格、图表和阅读顺序,并可选地翻译成另一种语言,同时保持每个图表位置不变。
适用场景:
- 将 PDF 作为 HTML/网页阅读
- 将 PDF 转换为带样式的 HTML 文档
- 在保留图表和表格的前提下将 PDF 翻译成另一种语言
不适用场景:
- 需要纯 Markdown 文本(无样式,图表可选)时,应使用 doc-to-markdown
- 需要反向转换(Markdown → PDF)时,应使用 pdf-creator
主要能力
处理流程为:提取 → 查看 →(翻译)→ 构建 → 验证。中间的“查看”和最终“验证”步骤是保证还原度的关键:PDF 是版面而非纯文本流,因此需要在构建前阅读渲染后的页面,在交付前阅读渲染后的 HTML。
该技能以内联方式运行(无 context: fork):翻译环节会编排一个动态工作流,而子代理无法生成动态工作流。
使用方式
依赖
- uv(用于运行带内联依赖的 Python)
- Google Chrome 或 Chromium(用于视觉验证)
- Python 包通过
uv run --with获取:PyMuPDF、Pillow、numpy - 除 Chrome 和 uv 外无需预安装其他内容
工作流
- 提取结构并渲染页面(extract_pdf.py)
- 阅读 pages/*.png——查看版面,区分内容图片与装饰图片
- (仅在翻译时)运行翻译工作流
- 构建单文件 HTML(build_html.py)
- 视觉验证(verify_render.py → 阅读每个分段)
- 交付 .html
1. 提取
uv run --with pymupdf python scripts/extract_pdf.py input.pdf
生成 input-build/ 目录,包含 structure.json(带字体大小的文本块和标记为装饰性的图片块)、images/ 和 pages/(每页一个 PNG)。
2. 构建前先查看
阅读 input-build/pages/*.png。这一步不可省略:需要查看真实版面,确认哪些图片是内容、哪些是装饰,并识别表格/图表。长 PDF 需阅读每一页;短 PDF 则很快。这也是理解文档以便更好地翻译的环节。
3. 翻译(可选)
仅在用户要求另一种语言时进行。阅读 references/translation_workflow.md 并遵循其指引:动态工作流并行翻译页面、为数据图表添加说明,并统一术语。它生成两个覆盖文件(units.json、caps.json)供第 4 步使用。对于超过一页的内容,不要手动内联翻译——工作流能保持术语一致且快得多。
4. 构建
原语言 HTML:
uv run --with Pillow python scripts/build_html.py input-build/structure.json --out output.html
翻译后 HTML(使用第 3 步的覆盖文件):
uv run --with Pillow python scripts/build_html.py input-build/structure.json --out output.html \
--translation input-build/units.json --captions input-build/caps.json --lang zh-CN
build_html.py 是数据驱动的:根据字体大小推断标题层级(最常见字号为正文;更大的字号逐级升为 h3/h2/h1),丢弃装饰性图片,并将内容图片以内联压缩 base64 形式嵌入 → 生成一个可移植文件。它不针对任何特定文档手工调优。如果某个 PDF 结构特殊(如多栏、侧边栏、尺寸启发式误判的图表),可阅读脚本并调整——脚本很短,设计上允许按文档编辑。
5. 视觉验证(强制)
uv run --with Pillow --with numpy python scripts/verify_render.py output.html
然后阅读每个 seg-*.png 并检查:字体渲染正常(无豆腐块)、表格/图表未被裁剪、标题/列表显示正确、所有预期图片均存在。文本正确不代表渲染正确(failure_cases #7)。修复并重新验证直至干净。
也可进行快速结构交叉检查,但计数方式要正确:
grep -o '<figure>' output.html | wc -l
而非 grep -c(failure_cases #1)。
6. 交付
交付单个 .html 文件。它是自包含的(图片已内联),双击即可打开,不会丢失任何内容。
脚本
| 脚本 | 运行方式 | 用途 |
|---|---|---|
| scripts/extract_pdf.py | uv run --with pymupdf | PDF → structure.json + images/ + 页面渲染 |
| scripts/build_html.py | uv run --with Pillow | structure.json(+ 可选翻译/说明)→ 单文件 HTML |
| scripts/verify_render.py | uv run --with Pillow --with numpy | 无头 Chrome 渲染 → 可读 PNG 分段 |
限制
- 扫描/纯图片 PDF(无文本层):需先 OCR(如 ocrmypdf),再使用本技能。
- 复杂多列表格:单元格文本会保留且可读,但列对齐可能扁平化为文本流——PyMuPDF 将表格读取为文本块而非网格,因此网格线会丢失。PDF 中作为图片的表格会以图片形式保留。如果表格的网格结构至关重要,请使用 doc-to-markdown(pandoc 可重建真实表格)或单独转换该页。
- 像素级完美复刻:输出是保留图片和阅读顺序的干净重排,而非原始页面版面的 1:1 复制。
- 改写:它只翻译和重新排版;不进行摘要、不添加 TL;DR、不做编辑评论。忠实还原是核心目标。
忠实度(翻译前必读)
交付物看起来权威,因此错误内容比丑陋内容更糟。不可协商的规则——以及此前具体出错的方式——见 references/failure_cases.md。最严重的一条:绝不要给真实人物使用推断出的译名,并逐字复制每个数字/专有名词(failure_cases #6)。任何翻译运行前阅读该文件;任何运行前浏览一遍。
后续步骤
生成 HTML 后,可建议自然的后续操作:
转换完成:output.html(单个自包含文件)。
选项: A) 将其制作为 PDF——如需打印/分享副本,运行 /daymade-docs:pdf-creator(推荐,如果需要发送) B) 改为提取文本为 Markdown——运行 /daymade-docs:doc-to-markdown(如果需要可编辑文本而非阅读页面) C) 不用了——HTML 就是想要的