使用 pdfpecker 制作和读取 PDF
pdfpecker 无需浏览器即可将 HTML 和 CSS(或 Markdown)转换为 PDF,并将 PDF 页面渲染回图像,以便您查看成果。按以下顺序操作:编写 HTML → 转换 → 查看页面 → 修改 → 重新转换。
安装
python3 -c "import pdfpecker" 2>/dev/null || python3 -m pip install --quiet pdfpecker
辅助脚本位于此技能文件夹内的 scripts/pdf.py(在 Claude Code 中为:${CLAUDE_SKILL_DIR}/scripts/pdf.py)。它封装了包,因此您无需自行编写 Python 即可完成常见任务:
python3 scripts/pdf.py html invoice.html invoice.pdf # 图片和 CSS 相对于 HTML 文件所在目录解析
python3 scripts/pdf.py md notes.md notes.pdf --page-size Letter
python3 scripts/pdf.py preview invoice.pdf --dpi 80 # 生成 invoice-page-1.png 等文件,并输出路径
python3 scripts/pdf.py text report.pdf --pages 1-2
python3 scripts/pdf.py markdown report.pdf report.md # 将任何 PDF 转换为 Markdown,保留表格和列表
python3 scripts/pdf.py info report.pdf # 页数
python3 scripts/pdf.py merge all.pdf cover.pdf report.pdf
运行 python3 scripts/pdf.py <command> --help 查看每个命令的选项。在 Python 中,等效调用是:
pdfpecker.html_to_pdf(html, base_dir=...)、html_file_to_pdf(path, out)、markdown_to_pdf(text)、
pdf_to_images(pdf, dpi=80)、pdf_to_text(pdf)、pdf_to_markdown(pdf)、pdf_page_count(pdf)、merge_pdfs([...])
以及 pdf_to_pdfa(pdf, "out.pdf")(将现有 PDF 转换为 PDF/A 格式用于归档)。
编写 HTML
从模板开始(如果适用):templates/invoice.html(一页发票,含清单表格)和
templates/report.html(多页报告,含封面、页码、表头重复的表格以及 SVG 图表)。将其复制到输出文件旁边并编辑。
将页面布局放在 CSS 中,而非选项中:
@page {
size: A4; /* 或 Letter、A5、"A4 landscape"、210mm 99mm */
margin: 18mm 16mm 20mm;
@bottom-center { content: "第 " counter(page) " 页 / 共 " counter(pages) " 页"; font: 9pt sans-serif; color: #666; }
}
@page :first { @bottom-center { content: none; } }
h2 { break-after: avoid; } /* 保持标题与其后内容在同一页 */
tr, figure, .card { break-inside: avoid; }
.new-page { break-before: page; }
thead { display: table-header-group; } /* 每页重复显示表头(<thead> 的默认行为) */
需要了解的知识点(详情见 reference.md):
- 无 JavaScript。 脚本不会执行。将图表绘制为内联 SVG 或 CSS(使用带尺寸的
<div>作为柱状图),并在转换前填写数据。 - 无网络。 图片、样式表和字体从 HTML 文件所在文件夹(
base_dir)或data:URI 加载,绝不会从 http(s) URL 加载。请先下载所需资源,或将其嵌入。 - 字体。 若未使用自定义字体,文本将使用 Helvetica(
sans-serif,Arial)、Times(serif)和 Courier(monospace),并附带后备字体,覆盖拉丁、希腊和西里尔字母。中文、日文、韩文、阿拉伯文、希伯来文、印地文、泰文及其他文字会显示为?,除非您传入包含这些文字的字体:--font NotoSansSC-Regular.otf(或使用--system-fonts来使用机器上安装的字体)。对于特定字体,请使用@font-face并配合相对src。 - 现代 CSS 均可使用:flexbox、grid、表格、浮动、多栏、定位、变换、渐变、阴影、圆角、
object-fit、SVG、web 字体、计数器和 CSS 变量。布局方式与 Chrome 打印预览一致;PdfPecker 遵循 Chrome 的布局规则。 - 单位。 使用
mm、pt或px(每英寸 96 px)。边距为 16 mm 的 A4 内容宽度为 178 mm(约 673 px)。
检查结果
在交付 PDF 之前,始终查看页面:运行 preview 并查看 PNG 图像。检查文本是否被截断或超出页面、表格或标题是否在页面间不恰当拆分、新页上出现孤立的最后一行、空白页、字母显示为 ?(缺少字体)以及图片未加载(路径错误)。使用 text 确认文本内容和顺序。修改 HTML 或 CSS,重新转换,再次查看。
错误
脚本以状态码 1 退出并输出原因。在 Python 中,所有错误均为 pdfpecker.PdfPeckerError 的子类:
PdfPeckerArgumentError(选项错误)、PdfReadError(文件不是可读 PDF)、
PdfPasswordError、PdfLimitError(页数过多)、PdfTimeoutError,以及 PdfFileError(无法读取字体或文件)。