PDF 批量体检与文本提取
批量摸清一批 PDF「是什么、有多少页、能不能取文字」,并对能取文字的把内容抽出来。
触发规则
| 用户意图 | 处理 |
|---|---|
| 这批 PDF 都是什么 / 多少页 | 只做结构体检(可加 --no-text) |
| 把这些 PDF 的文字提取出来 | 做体检 + 提取,--out 输出 .txt |
| 这份 PDF 能复制文字吗 / 是不是扫描件 | 重点看「文本层」判定与说明 |
| 中文提取出来是乱码 | 先看是否报告了「缺少 ToUnicode 映射」,据此如实说明 |
| 只是问本技能能干嘛 | 仅介绍,不执行任何操作 |
依赖
| 依赖 | 用途 |
|---|---|
| Python 3.8+ | 仅标准库(zlib / re / json / pathlib) |
不需要 PyPDF2、pypdf、pdfminer、pdfplumber 等任何第三方包,无需联网。
快速开始
# 批量体检
python3 scripts/pdf_inspect.py ./合同
# 体检 + 提取文本到 ./txt
python3 scripts/pdf_inspect.py ./合同 --out ./txt
# 只体检不提取
python3 scripts/pdf_inspect.py a.pdf b.pdf --no-text
# 结构化报告,便于下游消费
python3 scripts/pdf_inspect.py ./合同 --json report.json
# 只看每个文件前 100 字符
python3 scripts/pdf_inspect.py ./合同 --preview 100
参数
| 参数 | 说明 | 默认 |
|---|---|---|
--out DIR |
每个 PDF 的提取文本写为同名 .txt |
不写 |
--json PATH |
输出结构化 JSON 报告 | 不输出 |
--preview N |
终端预览每个文件前 N 个字符 | 300 |
--max-chars N |
JSON 报告中每文件保留的正文长度 | 2000 |
--no-text |
只做结构体检 | 关 |
文本提取可还原性判定
| 情况 | 表现 | 结论 |
|---|---|---|
| 标准单字节编码(Type1/TrueType 简单字体) | 输出可读文本 | 可提取 |
| CID 字体 + 有 ToUnicode 映射 | 按映射还原,含中文 | 可提取 |
| CID 字体 + 无 ToUnicode 映射 | 报告「无法可靠还原」 | 不可提取,需 OCR 或原始文档 |
| 内容流无文本显示操作符 | 报告「疑似扫描件」 | 不可提取,需 OCR |
| 文件已加密 | 报告「已加密」 | 只给结构,不给文本 |
Agent 执行要求
- 不把乱码当成功:若报告「无法可靠还原」或「疑似扫描件」,如实告知用户,
不要说「已提取文本」;也不要自行推测内容。 - 加密文件不尝试破解:检测到
/Encrypt只报告,不尝试解密。 - 只读源文件:本技能不修改源 PDF,只写用户指定的输出目录。
- 页数与文本层要分开报:页数多不代表能提取文字(扫描件常见 100 页 0 文本)。
- 元数据可能是空或被伪造:向用户展示元数据时说明它来自文档自述字段,不可作为事实依据。
- 输出编码统一 UTF-8:写出的 .txt 固定 UTF-8 与 LF 换行,便于跨平台比对。
输出模板
## PDF 体检结果
### 合同A.pdf
- 版本 1.7 大小 248.3 KB 页数 12 对象 186 流 24
- 文本层:有 ToUnicode 映射 1024 条
- 元数据:Producer=Microsoft Word;CreationDate=2026-08-14
文本预览(4820 字符):
合同编号:HT-2026-0814
...
已写出:./txt/合同A.txt(4820 字符)
### 扫描件B.pdf
- 版本 1.4 大小 1820.5 KB 页数 8 对象 42 流 9
- 文本层:无
- 说明:未发现文本层,疑似扫描件/纯图片 PDF,需要 OCR 才能取文本
(未输出文本)
汇总:2 个 PDF,含文本层 1 个,疑似扫描件 1 个,加密 0 个
注意事项
- 禁止修改、删除源 PDF;不做 PDF 编辑(合并、拆分、页序调整、加水印、压缩)。
- 提取结果为纯文本,不含版面坐标与样式,表格会被拉直为顺序文本,需按此口径向用户说明。
- 不实现 OCR;扫描件请配合 OCR 工具处理。
- 超大 PDF(数百 MB)解码后会占用较多内存,建议先只做结构体检。