112 lines
6.7 KiB
Markdown
112 lines
6.7 KiB
Markdown
---
|
||
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 或下载缓存当作最终产物。
|
||
- 回复时给出最终文件路径,并简要说明完成的处理和验证;失败时说明具体原因,不提供依赖安装提示。
|