Communitygithub.com

V4TIME/V4SKILL

PDF 文件创建、读取、合并、填写、OCR 和文本编辑等全套操作。

V4SKILL 是什么?

该技能(V4TIME/V4SKILL)为 AI 智能体(如 Claude Code、Cursor 等)提供了一个全面的 PDF 操作工具箱。它基于 Python 的 pypdf、reportlab 和 pdfplumber 库,能够处理从创建结构化 PDF、构建可填写 AcroForm 表单(含布局 lint 和视觉叠加层)、提取文本/表格/元数据,到合并、拆分、旋转、添加水印/图章、导出页面图像、管理元数据和附件、以及加密/解密等一系列任务。此技能还涵盖两个高级功能:扫描/纯图像 PDF 的 OCR 提取(通过 pymupdf 或 marker-pdf 路线)和通过自然语言提示编辑现有 PDF 中的文本(使用 nano-pdf CLI),这两个功能的详细说明位于 `references/` 目录下。用户可以通过 `scripts/` 目录下的命令行脚本与 AI 交互,这些脚本输出严格的 JSON 结果,便于程序化处理。此外,该技能还包含了“验证(Verification)”流程和“陷阱(Pitfalls)”说明,用于指导如何检查处理结果并避免常见错误,例如扫描 PDF、扁平化限制、表格提取启发式以及 PDF/A 兼容性问题。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/V4TIME/V4SKILL/tree/HEAD/productivity/pdf

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

PDF 技能

根据结构化的规格创建 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,将 JSON 结果打印到 stdout,并在失败时以非零退出。

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 platypuspdf_create.py spec.json -o out.pdf
构建可填写表单reportlab acroFormpdf_make_form.py formspec.json -o form.pdf
Lint 表单布局 / 叠加图像pure python + PILpdf_form_layout.py formspec.json [--render-overlay o.png]
每页文本pdfplumberpdf_read.py f.pdf --text
表格 → JSON/CSVpdfplumberpdf_read.py f.pdf --tables
元数据 / 尺寸 / 加密 / 扫描pypdf + pdfplumberpdf_read.py f.pdf --meta
合并(+ 大纲)pypdfpdf_merge.py a.pdf b.pdf -o m.pdf
拆分 / 提取 / 旋转pypdfpdf_split.py f.pdf --pages 2-5 --rotate 90
列出 / 填写 / 扁平化表单pypdfpdf_read.py --fields、pdf_fill_form.py
加密 / 解密(AES-256)pypdfpdf_secure.py --encrypt/--decrypt
水印 / 加盖 PDF 页面pypdfpdf_watermark.py f.pdf --stamp w.pdf
在坐标处加盖文本/图像reportlab + pypdfpdf_stamp.py f.pdf --text "Sign here" --x 400 --y 60
页面 → PNG(审查 / OCR 交接)pypdfium2 或 pdftoppmpdf_page_image.py f.pdf --pages 1-3 --out-dir imgs/
设置/清除元数据、附件pypdfpdf_meta.py --set-meta / --attach / --extract-attachments
压缩内容流pypdfpdf_split.py f.pdf --pages 1-N --compress

流程

  1. 检查。 运行 pdf_read.py file.pdf --meta。检查 encrypted(如果为真,先用 pdf_secure.py --decrypt 解密)和 likely_scanned_pages。如果页面是纯图像的,先用 pdf_page_image.py --pages <scanned> --dpi 300 --out-dir imgs/ 导出,然后将 PNG 交给 references/ocr-extraction.md 技能——不要将空文本报告为“无内容”。
  2. 创建。 用 write_file 编写 JSON 规格(元素:heading、paragraph、table、image、pagebreak;可选的 title/author 元数据;页码会自动添加),然后运行 pdf_create.py。如果布局很重要,用 vision_analyze 在渲染的页面图像上直观验证。
  3. 提取。 --text 输出每页字符串的 JSON 列表;--tables 输出每页的行数组,并且也可以生成 CSV 文件。用 read_file 读取结果;绝不要直接查看二进制 PDF。
  4. 操作。 pdf_merge.py 连接文件,可以为每个源文件添加一个书签;pdf_split.py 处理页面范围(从 1 开始,例如 1-3,5,9-)、以 90° 为步长的旋转以及 --compress。通过准备单页图章 PDF(例如通过 pdf_create.py)并用 pdf_watermark.py 叠加来添加水印;对于单行图章(“在此签名”、对角线 DRAFT、角落标签),使用 pdf_stamp.py 在明确坐标处添加文本或图像。
  5. 构建表单。 编写一个表单规格 JSON(字段包含以 PDF 点为单位的 label_box/entry_box——参见 references/forms.md),用 pdf_form_layout.py 进行 lint 并修复所有报告的问题,可选择用 vision_analyze 审查 --render-overlay PNG,然后用 pdf_make_form.py 构建,并用 pdf_read.py --fields 确认。
  6. 填写表单。 列出字段(--fields)以了解确切的名称和类型,用 write_file 编写 UTF-8 JSON 格式的 {"FieldName": "value"}(复选框接受 true/false;单选/选择值必须匹配字段的导出选项),然后运行 pdf_fill_form.py。重新用 --fields 读取以确认值已正确填写。
  7. 元数据和附件。 pdf_meta.py --set-meta 写入标题/作者/主题/关键词(DocInfo);--clear-meta 清除它们;--attach/--list-attachments/--extract-attachments 处理嵌入文件的往返。
  8. 安全。 使用不同的用户/所有者密码和 AES-256 加密。要移除已知密码,--decrypt 会写入未加密的副本。
  9. 验证(见下文)再报告成功。

陷阱

  • 扫描 PDF:空的 extract_text() 加上页面图像意味着没有文本层。转到 references/ocr-extraction.md;不要编造文本。
  • 扁平化限制:pdf_fill_form.py --flatten 使用 pypdf 的扁平化支持,将小部件外观转换为页面内容。对于纯文本字段和复选框是可靠的,但可能会丢弃或错误渲染特殊的小部件(富文本、自定义外观流、某些单选组)。用 vision_analyze 直观验证扁平化输出;对于要求严格的扁平化,使用外部渲染器(例如 Ghostscript 或 pdftoppm+ 重组)作为后备方案。
  • NeedAppearances:填写后,查看器仅在存在外观流时才渲染值。填充脚本会设置 AcroForm 的 NeedAppearances 标志,以便合规的查看器重新生成它们;一些最小查看器会忽略它——如果显示保真度重要,请扁平化。
  • 非拉丁表单值:值被正确存储(UTF-16),但字段的默认字体可能缺少字形,因此查看器可能显示空白,即使数据往返正常。用 --fields 验证,而不仅仅是视觉验证。
  • 压缩预期:--compress 仅对内容流进行 deflate 操作。通常节省 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 配置文件)并使用 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 列出每个规格字段,并具有正确的类型和选项。
  • 填写表单后: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 检查。

Individual skills in this repo

This repo contains 12 individual skills — each has its own dedicated page.

相关技能