乐于分享
好东西不私藏

200 份 PDF 跑完只要 0.47 秒,PDF 转 Markdown 这块的排名换人了

200 份 PDF 跑完只要 0.47 秒,PDF 转 Markdown 这块的排名换人了

把一批 PDF 喂给知识库,第一步永远是把它们变成文本。

这一步的常规做法,是全部丢进 OCR。反正 OCR 什么都能读,省事。

问题是 OCR 按页收钱,而且慢。一份三十页的年报,走一遍云端 OCR,两秒到十秒起步,账单按张累加。跑一千份,钱和时间都是实打实往外掉。

更冤的是,这里面大部分文件压根不需要 OCR。

Firecrawl 团队给出的比例是 54%。也就是说你送去 OCR 的文件里,超过一半本身就带着完整的文本层,直接读就行,掏钱让机器再认一遍字,纯属重复劳动。

他们为此写了一个东西,叫 pdf-inspector。这两天在 GitHub 周榜上一周涨了八千多星,现在总数 14202,MIT 协议,纯 Rust。

有意思的不是它涨得快,是它把同赛道的几个老选手,在同一份语料上按住了。

五个引擎,同一份 200 文档语料

这个横评不是厂商自己画饼,用的是 opendataloader-bench 的公开语料,200 份 PDF,M4 Pro,七月三十一号跑的。参赛的五个都是干 PDF 转 Markdown 这活的本地引擎,不带模型解析,OCR 全关,分数区间 0 到 1,越高越好。

引擎
总分
阅读顺序
表格
标题
跑完 200 份
pdf-inspector
0.875
0.915
0.814
0.788
0.470 秒
liteparse
0.873
0.913
0.693
0.811
0.750 秒
opendataloader
0.831
0.902
0.489
0.739
2.569 秒
pymupdf4llm
0.735
0.886
0.401
0.424
17.117 秒
markitdown
0.589
0.844
0.273
0.000
16.165 秒

先看最后一列。

0.470 秒和 17.117 秒,差了三十六倍。同样是本地跑、同样二百份文件、同样一台机器。

再看表格那一列。0.814 对 0.401 对 0.273。财报、发票、合同这类东西,表格塌了基本等于白转,因为数字错位之后,下游模型读到的是一堆对不上号的数。

markitdown 那个标题分 0.000 值得单独说一句。它不是分低,是根本没输出标题层级。你拿它转出来的 Markdown 去做分块,整份文档在结构上是平的,切出来的块之间没有从属关系。做 RAG 的人应该懂这意味着什么。

pdf-inspector 唯一输掉的一项是标题,0.788 对 liteparse 的 0.811。差距很小,但这是它承认的短板。

快是因为它少干了活

PDF 转 Markdown 这条链路上,三十六倍的差距通常不是靠优化抠出来的,是架构上少做了事。

pdf-inspector 里没有机器学习模型。没有版面检测网络,没有表格识别模型,一个权重文件都不下载。整个库的外部依赖只有一个 lopdf,用来解析 PDF 结构。

它的表格是怎么认出来的。两条路并行,一条从 PDF 的绘图指令里直接捞矩形,画了框线的表格属于这类。另一条看文字的对齐关系,没框线但一列一列码整齐的,靠坐标推。财务表格里那种被合并成一大坨的数值,它会再拆一次。

标题是按字号分层的,正文字号算基准,比它大的按比例分成 H1 到 H4,中间做 0.5pt 的聚类,免得同一级标题因为渲染误差被拆成两级。加粗和斜体从字体名里读,Bold、Italic、Oblique 这些词就在字体名里写着。代码块靠等宽字体识别,Courier、Consolas、Monaco、Menlo、Fira Code、JetBrains Mono 都在名单里。

还有一处省得比较狠。文档只加载一次。检测阶段和提取阶段共用同一份解析结果,不像有些管线先跑一遍判断类型、再重新打开跑提取。

分栏也处理了。报纸式的多栏排版会被自动识别,按人眼的阅读顺序串起来,不会出现左栏读一行右栏读一行的错乱。跨行断开的单词会重新拼回去,目录里那一长串点号会折成省略号,页码直接过滤掉。

这些都是很土的工程活,没什么概念上的新东西。但拼起来的结果就是 0.470 秒。

装它的三种方式,别照着首页抄

这一点得提前说,不然你会白折腾十分钟。

它 README 的 Python 快速开始,写的是先装 maturin 再 maturin develop --release。那是从源码构建的开发者路径,需要本地有 Rust 工具链。

但 PyPI 上已经有发布版了,0.2.6。直接装就行。

pip install pdf-inspector
import pdf_inspector  result = pdf_inspector.process_pdf("report.pdf") print(result.pdf_type) print(result.markdown)

pdf_type 有四个值,text_based、scanned、image_based、mixed。同时还会给一个 0 到 1 的置信度,以及 pages_needing_ocr,具体到哪几页缺文本。

Node 这边是 npm install @firecrawl/pdf-inspector,浏览器里跑的话装 @firecrawl/pdf-inspector-wasm,WebAssembly 版本内嵌了 CMap,不用回服务器。这个对做前端文档预览的场景挺关键,用户的文件不用上传就能出结构化文本。

如果你只是想在命令行里试试水,装 CLI 更快。

cargo install pdf-inspector  detect-pdf report.pdf --json pdf2md report.pdf --compact pdf2md report.pdf --select-pages 1,3,5-10

--compact 那个参数建议默认带上,它会把目录里那种长串点号和源文件里的填充空白压掉,输出给大模型的时候省 token。--select-pages 支持范围写法,只转你要的那几页。

它真正想替你省的是那笔 OCR 钱

前面那些分数都是附带的,这个库最实用的用法是当分流器。

流程很短。PDF 进来,先跑分类,大约 10 到 50 毫秒出结果。判定为 text_based 且置信度够高的,本地提取,150 毫秒左右完事。剩下的才送去 OCR 服务,那边是 2 到 10 秒。

三百页的文档,分类阶段也是毫秒级完成的,因为它只解析 xref 表和页面树,不做完整对象加载,然后在内容流里找 Tj、TJ 这些文字操作符和 Do 这个图像操作符,按采样页判断。

扫描策略有四档可选。默认是 EarlyExit,扫到第一个无文本页就停,适合只想快速把纯文本 PDF 挑出来的管线。Full 是全扫不提前退出,想精确区分 mixed 和 scanned 就用这个。Sample(n) 是均匀抽 n 页,特大文件用。Pages 是你自己指定页码。

注意 pages_needing_ocr 里的页码是从 1 开始数的,不是 0。这个之前坑过人,Python 类型存根里一度没标注这件事,导致有人拿去当数组下标用,整体错一页。现在补上了。

按 54% 这个比例粗算,一千份文件的管线,五百多份不用付 OCR 费用,延迟从秒级降到毫秒级。这才是它值得装的理由,跑分只是顺带。

哪些情况别用它

它不做 OCR。一个字都不认。扫描件、纯图片 PDF 到了它这里,只会拿到一个类型判断和一份需要 OCR 的页码清单,文字还得靠别人。把它当全能解析器用,第一份扫描合同就会让你失望。

标题层级敏感的场景要掂量。0.788 对 0.811,liteparse 在这一项上更稳。如果你的下游是按标题切块做检索,而文档标题结构又复杂,值得两个都跑一遍比比。

还有依赖那条。整个库只压在 lopdf 一个依赖上,好处是轻,坏处是 lopdf 的问题就是它的问题。今年有过一个嵌套深度的拒绝服务漏洞,编号 RUSTSEC-2026-0187,升到 0.42 才修掉。startxref 指针损坏的恢复也是后来补的,而且目前只覆盖了传统 xref 表,PDF 1.5 之后的交叉引用流那种损坏还没处理。

仓库现在挂着 126 个 open issue。这个数字放在一万四千星的项目上不算离谱,但也说明它还在快速迭代期,别在生产管线里锁死某个小版本就不管了。

浏览器 WASM 那个版本,官方标注是可用的,但同一份 Rust 解析器搬进浏览器,大文件的内存占用得自己测。

今天可以花两分钟做的事

打开你放资料的那个文件夹。

装完 CLI 之后,对着里面的 PDF 批量跑一遍检测,看看到底有多少是 text_based。

cargo install pdf-inspector for f in *.pdf; do detect-pdf "$f" --json; done

这一遍跑完你会得到一个具体的比例。如果你手里的文件大部分是研报、论文、发票、合同、政府公开文件,这个比例大概率会比 54% 还高,因为这些东西本来就是电子排版直接导出的。

比例出来了,接下来的决定就不用拍脑袋了。比例高,加个分流层,OCR 只留给真扫描件。比例低,说明你的场景确实以扫描件为主,那就老实用 OCR,这个库对你只值一个类型判断。

顺带一说,这种「先量一遍再决定」的做法,比直接换工具靠谱得多。很多 PDF 提取工具对比文章会给你一张排行榜,但排行榜是在别人的语料上跑出来的。你自己那批文件长什么样,只有你自己跑一遍才知道。

PDF 转 Markdown 这件事上,没有一个引擎能通吃。有的强在表格,有的强在标题,有的干脆只负责告诉你该把哪一页送去 OCR。把它们按用途拆开用,比找一个万能选手现实。

---

相关阅读

  • 《OpenWork 实测,Claude Cowork 的开源平替长什么样》
  • 《4GB 显卡跑 70B,airllm 那套逐层加载到底靠不靠谱》
  • 《腾讯开源的 Agent 记忆中枢,四种可复用记忆资产拆开看》