做 RAG 或者文档处理的人,基本都绕不开 PDF 这个东西。
让人头疼的倒不是 PDF 本身,而是很多团队的处理方式有点拧巴。拿到一个 PDF,管它有没有文本层,一股脑全丢给 OCR。OCR 确实能认字,但又慢又贵,云服务按页收费,量大了非常费钱。实际上一半以上的 PDF 是自带文本层的,报告、论文、发票、合同这类文件,文字本来就在文件里躺着,根本不需要识别图像。
Firecrawl 开源的 pdf-inspector 就是冲着这个问题来的。这是一个 Rust 写的库,拿到 PDF 先判断类型,有文本的直接本地提取,全程不用 OCR,200 毫秒以内出结果。我这两天把仓库和文档翻了一遍,拿它的 CLI 跑了几个文件,这篇给大家把这个开源项目捋清楚。
pdf-inspector 是干什么的 Firecrawl 很多人应该不陌生,做网页抓取转 Markdown 的,AI 应用里喂数据经常能见到它,我前两天的推文有介绍这个项目。他们前阵子在搭自己的 PDF 解析引擎 Fire-PDF,顺手把里面负责分类和提取的核心部分抽出来开源了,就是 pdf-inspector。
它干的活可以归成三类,判断 PDF 是文本型还是扫描件,把文本带着位置信息提出来,再有就是转成结构完整的 Markdown。官方给的一个数字是,大概 54% 的 PDF 不需要 OCR,这部分用它可以完全在本地解决,不调任何外部服务。
项目是纯 Rust 实现,没有机器学习模型,不连外部服务,整个库只有一个外部依赖,就是 PDF 解析库 lopdf。协议 MIT,商用没有负担。目前 GitHub 上 1.1 万 Star,还在涨。
功能详情 先分清 PDF 是哪种类型 我觉得这是整个库里最值钱的功能,放前面说。
pdf-inspector 会把 PDF 分成四类:TextBased(自带文本层)、Scanned(扫描件)、ImageBased(以图片为主)、Mixed(混合)。判断方式是采样 PDF 的内容流,看里面有没有文本操作符,不用渲染页面,所以速度很快,10 到 50 毫秒出结果,300 多页的 PDF 也是毫秒级。
分类结果还带一个 0 到 1 的置信度,外加一个 pages_needing_ocr 字段,告诉我们具体哪几页没有文本。这个字段很关键,Firecrawl 官方博客里举过一个例子,一份财报 150 页有文本、60 页是扫描件,老的管道会把 210 页整本送去 OCR,用上这个字段之后,只有那 60 页需要走 OCR,剩下 150 页本地直接提,混合文档不再一刀切。
Firecrawl 自己的 Fire-PDF 引擎就是拿它当第一道关卡用,文本页走本地提取,只有扫描页才上 GPU 做 OCR,官方说整套流程平均下来一页不到 400 毫秒。自家的生产线在跑,说明这个用法不是纸上谈兵。
文本提取带位置信息 提取不是简单把字抠出来。每个文本片段都带着字体信息和 X/Y 坐标,库会根据坐标做多栏布局识别。双栏排版的论文、报纸那种版式,它能按正确的阅读顺序输出,不会左右栏串着读。
中日韩 PDF 里常见的 Type0、Identity-H 字体编码也支持,走 ToUnicode CMap 解码。遇到字体编码本身有毛病的文件,它会主动标记出来,让我们知道这页提出来的可能是乱码,好提前降级到 OCR,而不是把乱码悄悄混进结果里。
转出来的 Markdown 带完整结构 普通的提取工具给我们的是一坨纯文本,标题层级、列表、表格全没了。pdf-inspector 转 Markdown 的时候会把这些结构留下来。
标题按字号相对正文的比例分成 H1 到 H4,无序列表、数字列表、字母列表都能认出来,用等宽字体排的内容它会当成代码块处理。粗体斜体保留,URL 自动转成 Markdown 链接。还有些小地方也照顾到了,跨行断开的单词会接回去,页码会被过滤掉,目录里那种一长串的引导点也会压缩掉。
对喂大模型这件事来说,结构完整的 Markdown 和一坨纯文本的差距是实打实的,标题和表格都在,模型理解起来顺畅得多。
表格识别做了两手准备
表格是 PDF 提取里最容易翻车的环节,pdf-inspector 用了两条路子:一条看 PDF 的绘制指令,按画出来的矩形框识别表格;另一条不看线,按文字对齐方式做启发式判断。财报里常见的数字表格、跨页的续表、脚注都覆盖了,提出来直接就是 Markdown 表格。
跑分和速度都排在前面 官方在 opendataloader-bench 的 200 个 PDF 上做了对比测试,只比本地解析、不开 OCR 的工具,结果是这样的:
综合分、阅读顺序、表格、速度这四项它都是第一。速度差距尤其大,200 个文档它跑完用 0.47 秒,PyMuPDF4LLM 要 17 秒,微软的 MarkItDown 要 16 秒多,差出 30 多倍。标题识别这一项它略低于 liteparse,0.788 对 0.811,如实写上。
各语言绑定齐全,浏览器里也能跑 Rust 直接用 cargo 装,Python 有 pip 包,Node.js 有 npm 包。另外还有一个 WebAssembly 版本,同一个 Rust 解析器跑在浏览器里,PDF 字节不出浏览器,解析全部在本地完成,不用往服务器传文件。想做在线 PDF 工具又在意隐私的,这个形态挺合适。
上手跑一下 最省事的是直接用 CLI,装完就有 pdf2md 和 detect-pdf 两个命令:
cargo install pdf-inspector # PDF 转 Markdown pdf2md document.pdf # 只检测类型,不提取 detect-pdf document.pdf --json # 只处理指定页 pdf2md document.pdf --select-pages 1,3,5-10 Python 这边一行装好:
pip install pdf-inspector import pdf_inspector result = pdf_inspector.process_pdf( "document.pdf" ) print (result.pdf_type) # "text_based"、"scanned"、"image_based"、"mixed" print (result.markdown) # Markdown 字符串 只想做路由判断的话,用 detect_pdf ,拿不到文本但速度更快,还会返回 pages_needing_ocr :
result = pdf_inspector.detect_pdf( "document.pdf" ) if result.pdf_type == "text_based" : print ( "本地直接提取" ) else : print ( f"需要OCR的页: {result.pages_needing_ocr} " ) Node.js 也类似:
npm install @firecrawl/pdf-inspector import { readFileSync } from 'fs' ; import { processPdf } from '@firecrawl/pdf-inspector' ; const result = processPdf ( readFileSync ( 'document.pdf' )); console . log (result. pdfType ); console . log (result. markdown ); 什么场景适合用它 批量处理 PDF 的系统最值得上,先拿它分类,文本型的本地解决,扫描件才送 OCR,量大了 OCR 费用能省一大块,延迟也下来了。
做 RAG 的也合适,它输出的 Markdown 结构完整,标题、表格、代码块都在,拿去切分入库,质量比纯文本强不少。
还有浏览器端的在线工具,用 WebAssembly 版本,文件不出用户本地,服务器一点压力没有。
我的看法 我一直都很关注类似这样的开源工具库,垂直类的工具非常实用,它没想做大而全,扫描件它明说自己不管,老老实实把这事还给 OCR。分类加路由这个角色看着不起眼,真到批量处理的时候才知道值钱,几十毫秒判断一次,换来的是大部分文档不用碰 OCR。
短板也得说,标题识别那项跑分它不是第一。遇到纯扫描件它一点办法没有,我们还得自己备一套 OCR 方案兜底。它毕竟是个新库,碰上排版特别奇葩的文件,翻车概率肯定比打磨多年的老工具高一些。
不过对要处理大量 PDF 的团队来说,先拿它过滤一遍、能本地解决的绝不惊动 OCR,这个思路很好。代码我翻过,结构挺清爽,文档只加载一次,检测和提取共用一份解析结果,细节上是用了心的。1.1 万 Star 涨得这么快,说明这玩意儿做的确实不错。
开源地址 https://github.com/firecrawl/pdf-inspector