你有没有遇到过这种情况?
要处理一批 PDF:合同、发票、论文、报表……第一反应是找个库把它转成 Markdown 或纯文本,好喂给大模型。
结果一跑,心态崩了:
有的 PDF 其实是扫描件,纯文本提取出来全是乱码,只能上 OCR; 有的 PDF 排版花里胡哨,转出来的 Markdown 表格错位、列表消失、标题全乱; 最难受的是——你不知道手里这批文件到底哪些需要 OCR、哪些不需要,只能全部走一遍贵的 OCR 服务。
今天介绍一个开源项目,就是专门治这个病的:
pdf-inspector —— Firecrawl 团队开源的 PDF 检查、分类与文本提取库,纯 Rust 实现。
项目地址:https://github.com/firecrawl/pdf-inspector[1]
它解决的核心问题:先分类,再决定花不花 OCR 的钱
官方一句话定位:
Fast Rust library for PDF inspection, classification, and text extraction. Intelligently detects scanned vs text-based PDFs to enable smart routing decisions.
翻译成人话就是:它能在 10~50 毫秒内判断一个 PDF 是「文本版」还是「扫描版」,然后告诉你哪些页面需要 OCR、哪些页面直接本地提取就行。
为什么要先分类?因为现实中一个惊人的事实是:
大约 54% 的 PDF 根本不需要 OCR。
它们本身就是带文本层的电子文档(比如 Word 导出的、浏览器打印的、系统生成的报表),只是很多人不知道,傻乎乎地全量送了 OCR,钱和时间都白花了。
pdf-inspector 的做法是:本地先花 200ms 内把文本型 PDF 处理完,只有真正的扫描件才送去 OCR 服务(2~10 秒),把昂贵的 OCR 开销砍掉一半以上。
它的分类结果有四种,还带置信度:
TextBased | |
Scanned | |
ImageBased | |
Mixed |
关键是它还能返回具体需要 OCR 的页码列表(pages_needing_ocr),做到逐页路由——一个 300 页的 PDF,可能只有 3 页是扫描的,其余 297 页本地秒处理。
实测数据:比 PyMuPDF 快 36 倍
官方在 opendataloader-bench 语料(200 个真实 PDF)上跑了基准测试(2026-07-31 刷新,M4 Pro 机器,纯本地无 OCR):
| pdf-inspector | 0.875 | 0.915 | 0.814 | 0.470s | |
几个值得注意的点:
速度碾压:200 个 PDF,pdf-inspector 只要 0.47 秒,PyMuPDF 要 17 秒——快了约 36 倍; 综合质量第一:0.875 综合分排第一,尤其是表格(0.814)和阅读顺序(0.915),碾压 PyMuPDF(表格只有 0.401)和 markitdown(表格 0.273、标题直接 0 分); 表格能力是它最大的差异化:专门做了矩形检测 + 文本对齐启发式两种表格识别,支持财务表格、脚注、跨页连续表格。
简单说:既要快,又要准,还要表格还原度高——在这类开源纯本地方案里,pdf-inspector 是目前最能打的之一。
支持哪些功能?
除了分类,它还内置了一整套 PDF 处理能力:
位置感知文本提取:带字体信息、X/Y 坐标,自动处理多栏阅读顺序; Markdown 转换:H1-H4 标题(按字号比例识别)、列表、代码块(等宽字体检测)、表格、粗斜体、链接、分页符,一站式转好; 表格检测双模式:基于 PDF 绘图操作的矩形检测 + 基于文本对齐的启发式检测; 多栏布局:自动检测报纸式多栏,RTL 文本也支持; 编码问题检测:发现字体编码损坏时自动标记,提醒你回退到 OCR——而不是默默输出乱码; 浏览器 WASM:同一套 Rust 解析器可以编译成 WebAssembly 在浏览器本地跑,不需要服务器往返,内嵌 CMap。
最贴心的一点是:文档只解析一次,检测和提取共享解析结果,不做重复 I/O。
怎么用?五种方式任选
1. CLI(最快上手)
cargo install pdf-inspector# PDF 转 Markdownpdf2md document.pdf# 输出 JSON,方便管道处理pdf2md document.pdf --json# 只检测不提取detect-pdf document.pdf# 检测 + 布局分析(表格、分栏)detect-pdf document.pdf --analyze --json还可以只处理指定页面:pdf2md document.pdf --select-pages 1,3,5-10。
2. Python
import pdf_inspectorresult = pdf_inspector.process_pdf("document.pdf")print(result.pdf_type) # "text_based", "scanned", "image_based", "mixed"print(result.markdown) # Markdown 字符串3. Node.js
import { readFileSync } from'fs';import { processPdf, classifyPdf } from'@firecrawl/pdf-inspector';const result = processPdf(readFileSync('document.pdf'));console.log(result.pdfType); // "TextBased", "Scanned", "ImageBased", "Mixed"console.log(result.markdown);4. 浏览器 WASM(本地解析,无服务器)
import init, { processPdf } from'@firecrawl/pdf-inspector-wasm';awaitinit();const pdf = newUint8Array(await (awaitfetch('/document.pdf')).arrayBuffer());const result = processPdf(pdf);console.log(result.pdfType, result.markdown);5. Rust
use pdf_inspector::process_pdf;letresult = process_pdf("document.pdf")?;println!("Type: {:?}", result.pdf_type);ifletSome(markdown) = &result.markdown {println!("{}", markdown);}典型使用场景
场景一:PDF 管线智能路由(核心场景)
PDF 进来 → pdf-inspector 分类(~20ms) → 文本型 + 高置信度? 是 → 本地提取(~150ms),完成 否 → 送去 OCR 服务(2~10s)场景二:批量文档喂大模型
报表、研究论文、发票、法律文档批量转 Markdown,直接作为 RAG 语料或大模型输入。本地处理,不需要 OCR 的延迟和费用。
场景三:浏览器端文档工具
用 WASM 在浏览器本地解析 PDF,用户上传的文档不出浏览器就能转成 Markdown——隐私友好,还没有服务器成本。
需要注意的坑
它不解决扫描件:纯扫描 PDF 它只会告诉你「这是扫描件,请走 OCR」,它自己不做 OCR(这是设计取舍,OCR 交给更专业的服务); 适合原生文本 PDF:报表、论文、发票、法律文档是它的主场;如果是排版极其诡异的 PDF(比如复杂嵌套表格、艺术字),还原度会打折扣; Rust 生态:CLI 需要 cargo 安装,Python/Node 绑定是 PyO3/napi-rs 编译的,安装时可能需要编译环境(或者用官方预编译包); 还在快速迭代:项目很活跃,近期还在修表格检测、损坏 PDF 恢复(startxref 单比特损坏也能自动修复了)、安全修复等,用的时候留意版本更新。
一句话总结
如果你在做 PDF 相关工具、或者经常要批量处理 PDF 喂大模型:
先用 pdf-inspector 分类,把 54% 不需要 OCR 的文档本地秒处理掉,只把真正的扫描件送去 OCR——省时间,更省钱。
顺便说一句,Firecrawl 团队(firecrawl.dev)就是做网页/文档抓取转结构化数据的,pdf-inspector 是他们内部管线的一部分,现在开源出来了,MIT 协议,放心用。
项目链接: https://github.com/firecrawl/pdf-inspector
扩展阅读: Firecrawl 官网 https://firecrawl.dev[2]
引用链接
[1]https://github.com/firecrawl/pdf-inspector
[2]https://firecrawl.dev
夜雨聆风