收到一份 PDF 后,能选中文字,不代表抽取结果一定可靠;不能选中文字,也不代表整份文件都要用同一种识别方式。企业资料经常混有电子正文、扫描附件和盖章页,处理之前先看清各页情况,可以减少无效工作。
pdf-inspector 提供 PDF 分类、位置感知的文字抽取和 Markdown 转换。按 2026 年 9 月 23 日当前仓库与 Python 文档,它也已经提供选择性 OCR 接口,因此不能继续把它概括为“完全不做 OCR”。原生抽取与可选 OCR 有不同依赖,接入时要分开理解。项目仓库
从两页小样本看本地抽取
本次在 macOS 26.6.2 arm64、Python 3.12.14 的独立环境中安装 pdf-inspector==1.24.0。测试文件是自行生成的两页英文电子 PDF,包含页标题和六行短文本,没有表格、扫描图或复杂字体。
先调用普通处理接口:
import pdf_inspector
result = pdf_inspector.process_pdf("native-sample.pdf")
print(result.pdf_type)
print(result.page_count)
print(result.markdown)
结果类型为 text_based,页数为 2,Markdown 包含两页标题与正文。这证明该环境下最小原生抽取流程可运行,不能据此推断中文扫描件或复杂报告也能正确处理。
样本中每一行在视觉上单独排列,抽取后正文合并成段落。这个细节说明“字都抽出来了”和“格式与原页一致”是两种验收目标。若下游依赖原来的行边界,还需要位置数据或自己的分段策略。
页码从零还是从一,要看具体接口
同一包里的接口未必采用相同页码约定。当前 Python 文档说明,extract_pages_markdown 的选择参数使用从零开始的页索引。
pages = pdf_inspector.extract_pages_markdown(
"native-sample.pdf", pages=[1]
)
for page in pages.pages:
print(page.page, page.markdown, page.needs_ocr)
本次运行只返回第二页内容,结果中的 page 为 1。相比之下,选择性 OCR 接口的 page_numbers 使用从一开始的 PDF 页码。若直接把前一个接口的数字交给后一个,可能处理错页。Python 接口说明
可以在应用内部统一一种页码表示,在调用库时转换,并为第一页、最后一页和跳页选择各写一个小测试。数据库里保存页码时,也记录它是原始 PDF 页序还是文档印刷页码;封面和目录会让两者不同。
分类适合决定下一步,不宜直接判断内容合格
分类结果与置信度可以帮助选择处理路径,但文字层存在仍可能伴随乱码、缺字或阅读顺序问题。扫描 PDF 也可能叠加一层旧 OCR 文字,视觉页面与隐藏文字未必一致。
因此,分类之后再做几项针对用途的检查。正文是否接近空白,关键数字是否可读,标题与内容是否对应,页数是否齐全。出现异常时保留原文件和页序,进入 OCR 或人工复核。
混合文档应按页处理。电子正文能直接抽取,就保留其原生结果;扫描附件再进入识别。不要因为最后一页是图片,就把前面几十页已经可用的文字重新识别一遍。
合并结果时保存每页的处理来源。以后有人指出某页数字错误,你能知道它来自原生解析、OCR 还是后处理,而不是只剩一份无法追查的 Markdown。
当前的可选 OCR 需要什么
Python 目前提供 process_pdf_with_ocr,支持自动选择、强制识别和关闭 OCR 等模式。自动模式只对需要的页安排识别;真正进入 OCR 时,仍需兼容的 PDFium、ONNX Runtime 与模型文件。OCR 运行环境说明
安装 Python wheel 不等于这些外部组件已经全部准备好。当前运行环境文档还区分了已完成端到端验证的平台与预览路径。部署前应固定版本,按目标机器核对,不要只看包能导入就启动批量任务。
对前面的纯文字样本,本次还执行了:
result = pdf_inspector.process_pdf_with_ocr(
"native-sample.pdf", mode="auto", offline=True
)
for page in result.pages:
print(page.page_number, page.provenance.source)
两页来源均为 native。测试没有安装 OCR 运行库或下载模型,验证的是干净原生文档可以直接返回的路径,没有验证扫描件识别质量。
离线部署若确实需要 OCR,应提前准备运行库和模型缓存,并在断网条件下测试需要识别的样本。只拿电子 PDF 测试离线成功,会漏掉首次触发 OCR 时的依赖问题。
表格和双栏,需要看关系是否保留下来
一个表格中的数值都存在,但列归属错了,对业务可能比漏掉整页更危险。检查时至少确认表头、单位、行列关系和跨页延续,而不只比较字符总数。
可以选一份你熟悉的规格表,人工写出几道有标准答案的问题:某型号的额定值是多少,某列是否使用相同单位,脚注限制适用于哪几行。用抽取结果回答,再回到页面核对。
双栏论文则检查段落顺序。左栏末尾与右栏开头是否连接正确,脚注有没有插到正文中,图注有没有被并入下一段。标题识别看起来漂亮,也不能补救顺序混乱。
若某类版式持续失败,可以为它单独选择处理方式,不必让整个资料库改走更重的模型。路由规则最好以真实失败样本为依据,并保留固定样本供升级后回归。
错误与低质量结果要分开记录
缺少运行库、模型文件损坏或 PDF 无法打开,属于执行失败;处理完成但正文为空、置信度低或结构不完整,属于结果质量问题。二者的恢复方式不同。
执行失败先检查依赖与文件,不应把它记成“该页没有文字”。结果质量差则可以进入其他解析路线或人工检查。下游如果有托管服务,也应明确是否允许上传文件,不能把任何错误都自动转成外部请求。
任务记录中可以保存文件摘要、页数、选中的页、处理方式、版本和失败类别。原始输出与清理后的输出分别保留,避免去页眉或去重规则误删内容后无从追查。
重复运行时,确认输入是否改变。文件名相同不代表内容相同,旧缓存若没有按内容版本区分,可能让新上传的文件得到旧结果。
怎样测性能才与自己的任务有关
官方基准有特定语料、硬件和评测方法,不能把整套语料的统计值改写成单份文件的处理时间。也不能拿关闭 OCR 的结果,估算扫描文档的全流程耗时。
自己的测试可以分为电子文档、扫描文档与混合文档,再记录页数、文件大小、处理方式和总耗时。首次模型准备与后续运行分开统计,避免缓存状态造成误解。
批量服务还要看峰值内存、并发和失败重试。单份文件运行很快,不代表同时处理几十份不会争抢资源。先限制并发,观察队列和内存,再决定是否扩容。
浏览器端或桌面端也需避免长任务阻塞交互。用户应能看见处理范围和失败页,而不是只看到一个一直转动的图标。
为中文和坏文件各留一组样本
英文电子样本容易跑通,中文资料还可能涉及字体映射、缺字和不同的排版方式。可以加入一份中文说明书、一份中英混排报告和一份已经知道存在乱码的文件,检查关键名称、数字及标点。不能只看输出长度接近原文,就认定文字没有损坏。
对于加密或损坏文件,任务应该保留清晰失败状态。需要密码的文件与空白文件不同,解析异常也不表示内容不存在。若系统接受用户上传,前端应能说明哪些文件没有完成,而不是把它们悄悄从结果列表中移除。
升级库以后,重新运行固定样本并比较差异。标题层级或表格形式的变化可能影响后面的切块和索引,即使新版解析质量更好,也需要确认下游仍然接受输出格式。先在独立索引中试运行,比直接覆盖全部旧结果更容易发现问题。
对带隐藏 OCR 层的扫描件,还可以挑几处原页上清晰可见的字与抽取结果对照。隐藏文字可能来自旧识别或错误页面,选择文字成功不能代替内容一致性检查。
接入知识库前再做最后一次核对
将输出用于搜索或问答之前,保留原始来源与页码映射。答案引用某段内容时,读者应该能回到原页检查,尤其是表格、公式和带例外条件的条款。
不要把抽取成功视为资料可信。解析工具可以帮助恢复文字与结构,文档本身是否过期、是否适用于当前问题,仍由知识库的版本管理决定。
这套流程的起点可以很小:先处理几份熟悉的文件,找到原生抽取的可靠范围,再给失败类型安排后续路径。等结果可复查、错误可定位以后,再扩大到整批文档。











