{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
PDF 文件:创建、读取、合并、填表、OCR、编辑文本。
Skill 元数据
| 来源 | 内置(默认安装) |
| 路径 | skills/productivity/pdf |
| 版本 | 1.1.0 |
| 作者 | Nous Research |
| 许可证 | MIT |
| 平台 | linux, macos, windows |
| 标签 | pdf, documents, forms, ocr, text-extraction, reportlab, pypdf, pdfplumber, pymupdf, marker |
| 相关 skill | docx、xlsx、powerpoint |
参考:完整 SKILL.md
INFO
以下是 Hermes 在触发该 skill 时加载的完整 skill 定义。这是 agent 在 skill 激活时所看到的指令内容。
PDF Skill
从结构化规格创建 PDF,构建并填写 AcroForm 表单(带布局 lint 和视觉叠加),提取文本/表/元数据,合并/拆分/旋转/加水印/盖戳页面,导出页面图像,管理元数据和附件,以及加密/解密——使用 pypdf、reportlab 和 pdfplumber。两项吸收来的能力位于 references/(做这些任务前先读对应文件):
- 扫描/纯图像 PDF 与 OCR(pymupdf 快速路径、marker-pdf 质量路径、scripts/extract_pymupdf.py + scripts/extract_marker.py):
references/ocr-extraction.md - 通过自然语言提示编辑既有 PDF 内文本(nano-pdf CLI):
references/nano-pdf-editing.md
何时使用
- 生成报告、发票或多页文档为 PDF。
- 从 JSON 规格构建可填 AcroForm(文本/复选框/单选/下拉),先 lint 布局。
- 从 PDF 提取文本、表(JSON/CSV)、元数据或表单字段值。
- 合并、拆分、旋转、提取页面子集、加水印、按坐标盖文本/图像戳、加书签或压缩 PDF。
- 导出页面为 PNG 供视觉审阅或 OCR 交接;设置/清除文档元数据;添加/提取文件附件。
- 填写或压平 AcroForm;用密码加密或解密。
- 不用于扫描/纯图像 PDF(用
references/ocr-extraction.md),不用于像素级 HTML 转 PDF 渲染(用无头浏览器)。
前置条件
- Python 3.10+,带
pypdf、reportlab、pdfplumber:python -m pip install pypdf reportlab pdfplumber - 可选,用于页面光栅化(
pdf_page_image.py、叠加渲染):python -m pip install pypdfium2,或 PATH 上 poppler 的pdftoppm。脚本回退顺序 pypdfium2 → pdftoppm,两者都无时报告{"rendered": false, "missing": [...]}(退出码 0)。 - 每个辅助脚本惰性检查导入,依赖缺失时打印安装提示。
运行方式
所有辅助脚本位于 scripts/,是 argparse CLI——用 terminal 工具运行;每个都支持 --help。它们严格以 UTF-8 读写 JSON,向 stdout 打印 JSON 结果,失败时非零退出。
python scripts/pdf_create.py spec.json -o out.pdf # 从 JSON 规格构建 PDF
python scripts/pdf_make_form.py formspec.json -o form.pdf # 从 JSON 规格构建可填 AcroForm
python scripts/pdf_form_layout.py formspec.json # 构建前 lint 表单布局
python scripts/pdf_form_layout.py formspec.json --render-overlay boxes.png [--pdf form.pdf]
python scripts/pdf_read.py doc.pdf --text # 逐页文本(JSON)
python scripts/pdf_read.py doc.pdf --tables --csv-dir t/ # 表导出为 JSON + CSV 文件
python scripts/pdf_read.py doc.pdf --meta # 元数据、页面尺寸、加密/扫描标志
python scripts/pdf_read.py form.pdf --fields # 表单字段:名、类型、值
python scripts/pdf_merge.py a.pdf b.pdf -o merged.pdf [--bookmarks]
python scripts/pdf_split.py doc.pdf --pages 1-3,7 -o part.pdf [--rotate 90]
python scripts/pdf_fill_form.py form.pdf --fields-json values.json -o filled.pdf [--flatten]
python scripts/pdf_secure.py doc.pdf --encrypt -o enc.pdf --user-password your-password
python scripts/pdf_secure.py enc.pdf --decrypt -o dec.pdf --password your-password
python scripts/pdf_watermark.py doc.pdf --stamp mark.pdf -o stamped.pdf [--under]
python scripts/pdf_stamp.py doc.pdf -o out.pdf --text "DRAFT" --x 150 --y 400 \
--font-size 60 --rotation 45 --opacity 0.3 --color "#cc0000" [--pages 1-3]
python scripts/pdf_stamp.py doc.pdf -o out.pdf --image sig.png --x 400 --y 60 --width 120
python scripts/pdf_page_image.py doc.pdf --pages 1-3 --dpi 150 --out-dir imgs/
python scripts/pdf_meta.py doc.pdf --set-meta --title "T" --author "A" -o out.pdf
python scripts/pdf_meta.py doc.pdf --attach data.csv -o out.pdf
python scripts/pdf_meta.py doc.pdf --list-attachments | --extract-attachments dir/
快速参考
| 任务 | 工具 | 命令 / API |
|---|---|---|
| 创建文档(标题、表、图) | reportlab platypus | pdf_create.py spec.json -o out.pdf |
| 构建可填表单 | reportlab acroForm | pdf_make_form.py formspec.json -o form.pdf |
| lint 表单布局 / 叠加图 | pure python + PIL | pdf_form_layout.py formspec.json [--render-overlay o.png] |
| 逐页文本 | pdfplumber | pdf_read.py f.pdf --text |
| 表 → JSON/CSV | pdfplumber | pdf_read.py f.pdf --tables |
| 元数据 / 尺寸 / 加密 / 扫描 | pypdf + pdfplumber | pdf_read.py f.pdf --meta |
| 合并(+ 大纲) | pypdf | pdf_merge.py a.pdf b.pdf -o m.pdf |
| 拆分 / 提取 / 旋转 | pypdf | pdf_split.py f.pdf --pages 2-5 --rotate 90 |
| 列出 / 填写 / 压平表单 | pypdf | pdf_read.py --fields、pdf_fill_form.py |
| 加密 / 解密(AES-256) | pypdf | pdf_secure.py --encrypt/--decrypt |
| 水印 / 盖 PDF 页戳 | pypdf | pdf_watermark.py f.pdf --stamp w.pdf |
| 按坐标盖文本/图像戳 | reportlab + pypdf | pdf_stamp.py f.pdf --text "Sign here" --x 400 --y 60 |
| 页面 → PNG(审阅 / OCR 交接) | pypdfium2 或 pdftoppm | pdf_page_image.py f.pdf --pages 1-3 --out-dir imgs/ |
| 设置/清除元数据、附件 | pypdf | pdf_meta.py --set-meta / --attach / --extract-attachments |
| 压缩内容流 | pypdf | pdf_split.py f.pdf --pages 1-N --compress |
流程
- 先检查。 运行
pdf_read.py file.pdf --meta。检查encrypted(若为 true,先用pdf_secure.py --decrypt解密)和likely_scanned_pages。若页面为纯图像,用pdf_page_image.py --pages <scanned> --dpi 300 --out-dir imgs/导出,把 PNG 交给references/ocr-extraction.mdskill——不要把空文本报为"无内容"。 - 创建。 用
write_file写 JSON 规格(元素:heading、paragraph、table、image、pagebreak;可选title/author元数据;页码自动加),然后运行pdf_create.py。布局重要时用vision_analyze在渲染页图上视觉验证。 - 提取。
--text给出逐页字符串的 JSON 列表;--tables给出每页行数组,还可发 CSV 文件。用read_file读结果;绝不要直接肉眼看二进制 PDF。 - 操作。
pdf_merge.py拼接并可为每个源文件加一个书签;pdf_split.py处理页范围(从 1 起,如1-3,5,9-)、90° 步进旋转和--compress。加水印先准备单页戳记 PDF(如经pdf_create.py)再用pdf_watermark.py叠加;单行戳记("sign here"、斜 DRAFT、角落标签)用pdf_stamp.py按显式坐标盖文本或图像。 - 构建表单。 写一份 form-spec JSON(字段带 PDF 点单位的
label_box/entry_box——见references/forms.md),用pdf_form_layout.pylint 并修复每个报告问题,可选地用vision_analyze审阅--render-overlayPNG,然后用pdf_make_form.py构建并用pdf_read.py --fields确认。 - 填写表单。 列字段(
--fields)了解确切名和类型,用write_file写 UTF-8 JSON{"FieldName": "value"}(复选框接受true/false;单选/选择值须匹配字段导出选项),然后pdf_fill_form.py。用--fields重读确认值已落位。 - 元数据与附件。
pdf_meta.py --set-meta写 Title/Author/Subject/Keywords(DocInfo);--clear-meta丢弃它们;--attach/--list-attachments/--extract-attachments往返嵌入式文件。 - 安全。 用不同的用户/所有者密码和 AES-256 加密。移除你知道的密码时,
--decrypt写一份未加密副本。 - 验证(见下)后再报成功。
常见陷阱
- 扫描 PDF:空
extract_text()加页面图像意味着无文本层。路由到references/ocr-extraction.md;不要编造文本。 - 压平限制:
pdf_fill_form.py --flatten用 pypdf 的压平支持,把小部件外观转为页面内容。对纯文本字段和复选框可靠,但可能丢弃或误渲染 exotic 小部件(富文本、自定义外观流、某些单选组)。用vision_analyze视觉验证压平输出;要万无一失的压平,用外部渲染器(如 Ghostscript 或pdftoppm+重组)作回退。 - NeedAppearances:填写后,查看器只在外观流存在时渲染值。填写脚本设 AcroForm
NeedAppearances标志,使合规查看器重新生成;某些极简查看器忽略它——显示保真重要时压平。 - 非拉丁表单值:值存储正确(UTF-16),但字段默认字体可能缺字形,因此即使数据往返成功,查看器也可能显示空白。用
--fields验证,而非仅视觉。 - 压缩预期:
--compress只放气内容流。典型节省 0–20%;对以图像或已压缩流为主的 PDF 无效。它不替代图像降采样(Ghostscript 的领域)。 - 权限标志不强制执行:所有者密码权限位(禁打印、禁复制)是礼貌请求,查看器可能遵守;任何库(含 pypdf)都能读取并剥离它们。只有用户密码真正通过加密门控内容。绝不把权限标志当安全呈现。
- 表提取是启发式的:pdfplumber 从线条/词对齐检测表;无边框或合并单元格的表可能需调
table_settings或手动清理。 - 页面索引:辅助 CLI 从 1 起计页;pypdf API 从 0 起。脚本会转换——不要重复转换。
- 旋转戳记文本提取:pdfplumber 的行分组打乱旋转字形(45° 的 "DRAFT" 提取为零散字母);改用 pypdf 的
extract_text()或渲染图验证旋转戳记。 - 单选组:reportlab 每组需 ≥2 个
radio()小部件,填写需带斜杠的导出值("/red"),压平保真对单选最差——见references/forms.md。 - 元数据范围:
pdf_meta.py只写经典 DocInfo 字典;嵌入式 XMP 元数据(若有)不动,在某些查看器中可能显示不同值。 - PDF/A 超出范围:pypdf/reportlab 无法生成或校验合规 PDF/A。若需归档一致性,经
terminal工具运行 Ghostscript(如gs -dPDFA=2 -dPDFACompatibilityPolicy=1 -sColorConversionStrategy=UseDeviceIndependentColor -sDEVICE=pdfwrite -o out.pdf in.pdf配合合适 ICC profile),并用 veraPDF 校验——两者都是外部安装,结果仍需校验而非假设。 - 旋转须为 90 的倍数;加密输入须在任何其他操作前解密。
验证
- 创建/合并/拆分后:
pdf_read.py out.pdf --meta——确认page_count,旋转过则确认逐页rotation。 - 提取后:检查 JSON 非空,抽查一个已知字符串或单元格。
- 表单设计循环:
pdf_form_layout.py spec.json须退出 0;然后--render-overlay boxes.png --pdf form.pdf,用vision_analyze审阅 PNG(红 = 带字段名的输入框,蓝 = 标签框),询问重叠、错位和标签与字段分离。迭代 规格 → lint → 叠加 直到干净。 - 构建表单后:
pdf_read.py form.pdf --fields列出每个 spec 字段,类型和选项正确。 - 填表后:
pdf_read.py filled.pdf --fields并比较值(精确匹配,含非 ASCII)。 - 盖戳后:重新提取文本(旋转戳记用 pypdf)或用
pdf_page_image.py渲染页面并用vision_analyze检查。 - 元数据/附件编辑后:
pdf_read.py --meta/pdf_meta.py --list-attachments,并重新提取一个附件做字节比较。 - 加密后:
--meta显示"encrypted": true,无密码打开失败;解密后文本提取与原始一致。 - 任何视觉内容(水印、压平表单),渲染并用
vision_analyze检查。