wechat-robot-skills/skills/pdf/SKILL.md
2026-07-25 14:54:21 +08:00

112 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: pdf
description: "处理本地 PDF 文件或远程 HTTPS PDF 链接,包括下载、读取、文本与表格提取、页面渲染与视觉审阅、创建、修改、合并、拆分、旋转、表单处理和最终质量校验。当用户提供 .pdf 文件或 HTTPS PDF 地址,或要求生成、编辑、总结、审阅版式重要的 PDF 时使用。"
---
# PDF 处理
## 核心原则
- 优先进行视觉检查。PDF 的文本提取结果不能代表真实版式,必须把页面渲染为 PNG 后检查。
- 收到远程 HTTPS PDF 链接时,先下载为本地 PDF再执行任何读取、编辑或渲染操作。
- 创建 PDF 时优先使用 `reportlab`;提取文本或表格时使用 `pdfplumber`;读取元数据、合并、拆分、旋转或处理页面结构时使用 `pypdf`
- 每次完成影响内容或版式的修改后,重新渲染并检查最新版本。
- 不覆盖用户提供的源文件。编辑时写入新的输出文件。
## 环境约定
环境已预置 Poppler`pdfinfo`、`pdftoppm`)以及 `reportlab`、`pdfplumber`、`pypdf`。直接使用环境提供的可执行文件和 Python 运行时;不要安装依赖,也不要提示用户安装依赖。如果默认 `python3` 未加载预置模块,先定位并改用环境提供的 Python 运行时。如果 Poppler 报告字体缓存目录不可写,把 `XDG_CACHE_HOME` 临时设置为本次任务目录下的可写缓存目录后重试。
## 标准流程
1. 获取输入:识别本地 PDF 路径或 HTTPS PDF 链接;远程链接先按“远程 PDF 下载”流程保存到本地。
2. 校验文件:确认文件存在、大小大于 0、可被 PDF 工具解析,并用 `pdfinfo` 获取页数、页面尺寸、加密状态等信息。
3. 建立工作目录:把中间文件放在 `tmp/pdfs/<任务名>/`,使用稳定且可读的文件名。
4. 读取和处理:根据任务使用 `pdfplumber`、`pypdf` 或 `reportlab`,但不要仅依赖文本提取判断页面内容。
5. 渲染页面:使用 Poppler 把待审阅的 PDF 转成 PNG。
6. 视觉检查:逐页检查文字、图片、表格、页眉页脚、页码、分页和留白。
7. 输出结果:把最终 PDF 写入 `output/pdf/`,文件名保持稳定且能表达内容。
8. 清理中间文件:交付完成后仅删除本次任务对应的 `tmp/pdfs/<任务名>/`,保留最终产物。
## 远程 PDF 下载
只接受 HTTPS 地址。必须使用本 Skill 自带的 `scripts/download_pdf.py` 下载,不要使用 `curl`、shell 脚本或临时编写的下载逻辑。脚本会自动创建目标目录、流式下载、限制重定向协议、控制文件大小,并使用 `pypdf` 校验下载内容。
```text
python3 scripts/download_pdf.py \
--url 'https://example.com/document.pdf' \
--output 'tmp/pdfs/<任务名>/source.pdf'
```
保留完整 URL包括查询参数并把它作为一个完整参数传入。目标文件已存在时脚本默认拒绝覆盖仅在确认该文件是本次任务生成的下载缓存时使用 `--overwrite`。可选参数:
- `--timeout <秒>`:连接和读取超时,默认 `60`
- `--max-bytes <字节数>`:最大下载大小,默认 `104857600`100 MiB
- `--overwrite`:覆盖已存在的目标文件。
脚本成功时退出码为 `0`,并输出:
```json
{
"ok": true,
"path": "/absolute/path/to/source.pdf",
"size_bytes": 123456,
"page_count": 10,
"encrypted": false
}
```
脚本失败时退出码为非 `0`,并输出 `{"ok": false, "error": "具体错误"}`。只有收到 `ok: true` 后才能继续读取或渲染该文件。
遵守以下规则:
- 跟随 HTTPS 重定向,但不允许降级到 HTTP。
- 不根据 URL 后缀或响应的 `Content-Type` 单独判断文件类型,以实际 PDF 解析结果为准。
- 如果下载结果是 HTML、登录页、错误页或无法解析的内容停止后续处理并明确说明链接需要授权或真实 PDF 下载地址。
- 如果链接包含签名、令牌或其他敏感查询参数,不在最终回复、日志摘要、错误信息或生成的文件名中复述这些参数;下载脚本也不会在结果中回显 URL。
- 如果 PDF 已加密且任务需要密码,先向用户索取密码;不得尝试绕过加密。
## 读取与审阅
- 使用 `pdfplumber` 提取正文、页级文本和表格,用于搜索、总结和结构化分析。
- 使用 `pypdf` 读取元数据、书签、页数和页面对象,或执行合并、拆分、旋转等结构操作。
- 如果提取出的文本很少或为空,将文件视为可能的扫描件,转而检查渲染后的页面;不要把空文本误判为空白 PDF。
- 对表格、图表、公式、双栏排版、批注、印章和扫描内容,以渲染图为主要依据。
- 回答问题或生成摘要时,区分 PDF 中明确写出的内容和根据版式、图表得出的推断。
## 创建与修改
- 使用 `reportlab` 创建新 PDF复杂文档优先使用 Platypus 的文档流、段落、表格和分页组件。
- 使用 `pypdf` 完成合并、拆分、旋转、页面重排、元数据和表单等操作。
- 处理中文或其他非 ASCII 文字时,选择环境中可用且覆盖所需字符的 Unicode 字体,并嵌入 PDF渲染后重点检查缺字、黑方块和字体回退。
- 为正文、标题、表格、图注和页眉页脚建立一致的字号、行距、边距与层级。
- 表格跨页时重复表头,避免行被不自然截断;图片和图表保持清晰、等比缩放并与说明文字对齐。
- 只使用 ASCII 连字符 `-`,避免 U+2011 等 Unicode 横线字符引发字体或换行问题。
## 渲染与视觉检查
使用 `pdftoppm` 将 PDF 渲染到本次任务的工作目录:
```bash
pdftoppm -png -r 150 \
'output/pdf/<最终文件名>.pdf' \
'tmp/pdfs/<任务名>/page'
```
对于文字较小、图表密集或 150 DPI 下无法确认的页面,提高分辨率并重新渲染。创建或修改 PDF 时必须检查全部页面;只读超长文档时可先生成低分辨率预览定位相关页面,再以足够分辨率检查相关页。
逐页确认:
- 没有裁切、重叠、溢出、异常空白页或错误分页。
- 没有黑方块、乱码、缺字或不可读的小字号。
- 标题层级、段落间距、页边距和对齐方式一致。
- 表格、图表和图片清晰、完整、标注正确。
- 页眉、页脚、页码和章节衔接正确。
- 引用和参考文献可读,不含工具令牌、占位符或临时路径。
## 交付要求
- 只有在最新渲染结果不存在可见的内容或格式缺陷后,才交付创建或修改后的 PDF。
- 最终文件必须位于 `output/pdf/`,不得把临时 PNG 或下载缓存当作最终产物。
- 回复时给出最终文件路径,并简要说明完成的处理和验证;失败时说明具体原因,不提供依赖安装提示。