在 0.47 秒内完成 200 份 PDF 的解析、分类和 Markdown 转换——无需 OCR、无需 ML 模型,纯 Rust 实现。这就是 firecrawl/pdf-inspector 能做的事。
读完本文你将了解:PDF 智能分类的原理 | 文本提取与表格检测的工程实现 | 多语言绑定的使用方式 | 与 PyMuPDF/MarkItDown 等竞品的横向对比
🎯 这个项目解决什么问题?
54% 的 PDF 是文本型 PDF,不需要 OCR 就能提取内容。但长期以来,PDF 解析领域缺乏一个"快速、准确、轻量"的统一工具——要么太慢(PyMuPDF4LLM 需要 17 秒),要么太差(MarkItDown 表格完全不可用)。
pdf-inspector 用 Rust 在 0.47 秒内处理 200 份 PDF,整体准确率 0.875,表格检测 TEDS 分数 0.814,同时支持 Python / Node.js / WebAssembly 三种语言绑定。
🔧 快速上手
环境要求
- Rust 1.70+ 或 Python 3.8+ / Node.js 18+
- 无需任何外部模型或 OCR 服务
Python 安装
pipinstallpdf-inspector一行调用
importpdf_inspector result=pdf_inspector.process_pdf("document.pdf")print(result.pdf_type)# "text_based", "scanned", "image_based", "mixed"print(result.markdown)# 提取的 Markdown 文本Node.js 安装
npminstall@firecrawl/pdf-inspectorimport{processPdf}from'@firecrawl/pdf-inspector';import{readFileSync}from'fs';constresult=processPdf(readFileSync('document.pdf'));console.log(result.pdfType);// "TextBased", "Scanned", "ImageBased", "Mixed"console.log(result.markdown);// 提取的 Markdown浏览器端 WebAssembly
npminstall@firecrawl/pdf-inspector-wasmimportinit,{processPdf}from'@firecrawl/pdf-inspector-wasm';awaitinit();constresponse=awaitfetch('/document.pdf');constpdf=newUint8Array(awaitresponse.arrayBuffer());constresult=processPdf(pdf);console.log(result.pdfType);console.log(result.markdown);CLI 工具
# 转换为 Markdownpdf2md document.pdf# JSON 输出(管道友好)pdf2md document.pdf--json# 仅检测 PDF 类型detect-pdf document.pdf# 检测 + 布局分析detect-pdf document.pdf--analyze--json# 指定页处理pdf2md document.pdf --select-pages1,3,5-10⚙️ 技术原理
核心流程:单文档加载 + 双路径共享
pdf-inspector 最大的工程亮点是只解析一次文档,分类和提取共享解析结果,避免了冗余 I/O:
智能分类机制
分类器通过内容流采样,在 10-50ms 内判断 PDF 类型:
- TextBased:有完整的文本内容流,置信度 > 0.9
- Scanned:只有图像,无文本内容流
- ImageBased:嵌入图片 + 少量文本
- Mixed:部分文本 + 部分扫描页
分类器返回: - 全局 PDF 类型
- 置信度分数(0.0-1.0)
- 逐页 OCR 路由建议——告诉调用者哪些页需要 OCR,哪些可以直接提取
文本提取与 Markdown 转换
标题识别:基于字体大小比率(H1-H4),无需 NLP,纯排版特征判断。
列表识别:项目符号、编号列表、字母列表——基于文本对齐和缩进模式。
代码块检测:等宽字体自动检测,嵌入 Markdown 代码围栏。
链接与分页:自动识别 URL,插入<!-- Page N -->分页标记。
表格检测:双模式策略
- 矩形检测:从 PDF 底层绘制操作(drawing ops)提取矩形,通过 Union-Find 合并相邻矩形形成表格网格
- 启发式检测:基于文本对齐、列间距、行间距识别表格
- 支持财务表格、脚注、跨页续表
CID 字体与编码处理
支持 ToUnicode CMap 解码,覆盖 Type0/Identity-H、UTF-16BE、UTF-8、Latin-1。当检测到字体编码损坏时,自动标记该区域,让调用者可以回退到 OCR。
多栏布局
自动检测报纸式多栏排版,确定正确的阅读顺序,支持 RTL(从右到左)文本。
🏗️ 架构分析
项目结构
pdf-inspector/ ├── src/ │ ├── lib.rs # 核心库入口 │ ├── detector.rs # PDF 类型分类器 │ ├── extractor.rs # 文本提取引擎 │ ├── layout.rs # 多栏布局检测 │ ├── tables.rs # 双模式表格检测 │ ├── markdown.rs # Markdown 生成器 │ └── fonts.rs # CID 字体处理 ├── python/ # Python 绑定 ├── napi/ # Node.js NAPI 绑定 ├── wasm/ # WebAssembly 构建 ├── benches/ # 性能基准测试 └── docs/ # 文档设计哲学
- 纯 Rust,无 ML 依赖:所有算法基于排版特征和结构分析,无需加载模型文件
- 单次解析,共享状态:避免重复 I/O,提升速度
- 渐进式精度:轻量分类器先行,确定需要 OCR 的页才调用重型处理
- 多目标编译:Rust 原生 + Python FFI + Node.js NAPI + WebAssembly,一套代码四种部署方式
性能基准对比
在 opendataloader-bench 标准测试集(200 份 PDF)上的对比:
| 引擎 | 综合得分 | 阅读顺序 NID | 表格 TEDS | 标题 MHS | 处理速度 |
|---|---|---|---|---|---|
| pdf-inspector | 0.875 | 0.915 | 0.814 | 0.788 | 0.470s |
| liteparse | 0.873 | 0.913 | 0.693 | 0.811 | 0.750s |
| opendataloader | 0.831 | 0.902 | 0.489 | 0.739 | 2.569s |
| pymupdf4llm | 0.735 | 0.886 | 0.401 | 0.424 | 17.117s |
| markitdown | 0.589 | 0.844 | 0.273 | 0.000 | 16.165s |
| pdf-inspector 在表格检测上领先第二名 17%,整体速度比 PyMuPDF4LLM 快 36 倍。 |
✅ 优缺点 & 适用场景
优势
- 速度极致:200 份 PDF 仅 0.47 秒,比竞品快 5-36 倍
- 表格检测强:TEDS 分数 0.814,远超竞品
- 轻量无依赖:纯 Rust,无 ML 模型,无外部 API
- 多语言覆盖:Python / Node.js / WASM / Rust CLI
- 浏览器可用:WebAssembly 版本支持浏览器端 PDF 解析
局限
- 仅支持文本型 PDF:扫描型 PDF 需搭配 OCR 使用
- 纯 Rust 生态:无 Java / Go / C# 原生绑定
- 仍在快速迭代:API 可能不稳定
- 表格检测对复杂嵌套表格仍有局限
适用场景
- RAG 管道中的文档预处理(跳过 54% 不需要 OCR 的 PDF)
- 财务、法律、学术文档的批量提取
- 浏览器端 PDF 预览与搜索
- 离线文档处理(无网络需求)
总结
pdf-inspector 代表了 PDF 解析领域一个新的工程范式:用纯结构分析替代 ML 模型,在速度和精度上同时取得优势。如果你的场景涉及文本型 PDF 的批量处理,这是一个值得纳入技术栈的优秀工具。
收藏本文,在构建 RAG 系统或文档处理管道时,可以直接参考这里的性能基准和选型建议。
关注作者,获取开源工具深度分析和实战指南。
评论区聊聊:你在使用 PDF 解析时遇到过哪些坑?欢迎分享。