firecrawl/pdf-inspector
摘要
Firecrawl 发布了 pdf-inspector,这是一个用于 PDF 分类和文本提取的快速 Rust 库,无需 OCR 即可将基于文本的 PDF 转换为 Markdown,并提供 Python、Node.js 和 WebAssembly 的绑定。
查看缓存全文
缓存时间: 2026/08/03 13:30
firecrawl/pdf-inspector
来源:https://github.com/firecrawl/pdf-inspector
pdf-inspector
Crates.io (https://crates.io/crates/pdf-inspector) npm (https://www.npmjs.com/package/@firecrawl/pdf-inspector) PyPI (https://pypi.org/project/pdf-inspector/) 许可证:MIT
用于 PDF 分类和文本提取的快速 Rust 库。可检测 PDF 是基于文本还是扫描件,提取带位置信息的文本,并转换为干净的 Markdown——全程无需 OCR。包含 Python、Node.js 和浏览器 WebAssembly 绑定。
由 Firecrawl (https://firecrawl.dev) 构建,可在 200ms 内在本地处理基于文本的 PDF,为约 54% 不需要 OCR 的 PDF 跳过昂贵的 OCR 服务。
特性
- 智能分类 — 通过采样内容流,在约 10-50ms 内检测 TextBased、Scanned、ImageBased 或 Mixed PDF。返回置信度分数(0.0-1.0)以及按页的 OCR 路由建议。
- 文本提取 — 带位置信息的提取,包含字体信息、X/Y 坐标,以及自动多栏阅读顺序。
- Markdown 转换 — 标题(通过字体大小比率识别 H1-H4)、项目符号/编号/字母列表、代码块(等宽字体检测)、表格(基于矩形和启发式)、粗体/斜体格式、URL 链接和分页符。
- 表格检测 — 双模式:基于 PDF 绘图操作的矩形检测,以及基于文本对齐的启发式检测。可处理财务报表、脚注和跨页续表。
- CID 字体支持 — 针对 Type0/Identity-H 字体的 ToUnicode CMap 解码,支持 UTF-16BE、UTF-8 和 Latin-1 编码。
- 多栏布局 — 自动检测报纸式分栏、顺序阅读顺序,并支持 RTL 文本。
- 编码问题检测 — 自动标记损坏的字体编码,使调用方可以回退到 OCR。
- 单次文档加载 — 文档仅解析一次,并在检测和提取之间共享,避免冗余 I/O。
- 浏览器 WebAssembly — 在浏览器和 Web Worker 中本地运行相同的 Rust 解析器,内置 CMap,无需服务器往返。
- 轻量级 — 纯 Rust,无 ML 模型,无外部服务。仅依赖
lopdf进行 PDF 解析。
基准测试
在 opendataloader-bench (https://github.com/opendataloader-project/opendataloader-bench) 语料库(200 个 PDF)上评估。仅展示不使用基于模型的 PDF 解析的本地引擎;OCR 已禁用。分数为 0-1,越高越好。
| 引擎 | 总体 | 阅读顺序 (NID) | 表格 (TEDS) | 标题 (MHS) | 速度(200 份文档) |
|---|---|---|---|---|---|
| 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 |
结果于 2026 年 7 月 31 日在 Apple M4 Pro 上刷新。引擎版本为 pdf-inspector 0.2.6、LiteParse 2.10.1、OpenDataLoader 2.2.1、PyMuPDF4LLM 0.2.0 和 MarkItDown 0.1.5。速度是排除预热运行后五次交替或轮换的完整语料库运行的中位数,每个解析器在单个进程中顺序处理文档。
完整的解析器配置、逐文档预测、评估器输出和生成的图表可在可复现结果分支 (https://github.com/firecrawl/opendataloader-bench/tree/abi/pdf-parser-benchmark-results) 中获取。
最佳适用场景: 需要速度、阅读顺序和表格结构的原生文本 PDF。在此对比中,pdf-inspector 在总体、阅读顺序和表格得分上更高,同时完整运行速度最快。这使得它成为报告、研究论文、财务文档、发票和法律 PDF 的理想本地默认选择,无需增加 OCR 延迟或基础设施即可获得干净、结构化的 Markdown。
使用配对基准测试工具 可在完全相同的语料库和评估器修订版本上比较两个本地构建。
快速开始
Python
bash pip install maturin maturin develop --release
``python import pdf_inspector
result = pdf_inspector.process_pdf(“document.pdf”) print(result.pdf_type) # “text_based”, “scanned”, “image_based”, “mixed” print(result.markdown) # Markdown 字符串或 None ``
完整 API 参考:docs/python.md
Node.js
bash npm install @firecrawl/pdf-inspector
``javascript 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); // Markdown 字符串或 null ``
完整 API 参考:napi/README.md
浏览器 WebAssembly
bash npm install @firecrawl/pdf-inspector-wasm
``javascript import init, { processPdf } from ‘@firecrawl/pdf-inspector-wasm’;
await init(); const response = await fetch(‘/document.pdf’); const pdf = new Uint8Array(await response.arrayBuffer()); const result = processPdf(pdf);
console.log(result.pdfType); console.log(result.markdown); ``
完整 API 参考:wasm/README.md
Rust
从 crates.io (https://crates.io/crates/pdf-inspector) 安装:
bash cargo add pdf-inspector
或手动添加:
toml [dependencies] pdf-inspector = "0.1"
``rust use pdf_inspector::process_pdf;
let result = process_pdf(“document.pdf”)?; println!(“Type: {:?}”, result.pdf_type); if let Some(markdown) = &result.markdown { println!(“{}”, markdown); } ``
完整 API 参考:docs/rust-api.md
CLI
``bash
安装 CLI 工具
cargo install pdf-inspector
将 PDF 转换为 Markdown
pdf2md document.pdf
JSON 输出(用于管道)
pdf2md document.pdf –json
带位置信息的 TextItem JSON,包含 is_underline 元数据
pdf2md document.pdf –items-json
仅原始 Markdown(无头部信息)
pdf2md document.pdf –raw
Token 高效输出(折叠长点引导符和类似的源填充)
pdf2md document.pdf –compact
插入分页标记()
pdf2md document.pdf –pages
仅处理指定页面
pdf2md document.pdf –select-pages 1,3,5-10
仅检测(不提取)
detect-pdf document.pdf detect-pdf document.pdf –json
检测 + 布局分析(表格、分栏)
detect-pdf document.pdf –analyze –json ``
如果从源代码检出,请使用 cargo run --bin pdf2md -- document.pdf 或 cargo run --bin detect-pdf -- document.pdf。
架构
PDF 字节 │ ├─► 检测器 → PdfType (TextBased / Scanned / ImageBased / Mixed) │ └─► 提取器 ├─ 字体 → 字体宽度、编码 ├─ 内容流 → 遍历 PDF 运算符 → TextItems + PdfRects ├─ xobjects → Form XObject 文本、图像占位符 ├─ 链接 → 超链接、AcroForm 字段 └─ 布局 → 分栏检测 → 行分组 → 阅读顺序 │ ├─► 表格 │ ├─ detect_rects → 基于矩形的表格(并查集) │ ├─ detect_heuristic → 基于对齐的表格 │ ├─ grid → 列/行分配 → 单元格 │ └─ format → 单元格 → Markdown 表格 │ └─► Markdown ├─ analysis → 字体统计、标题层级 ├─ preprocess → 合并标题、首字下沉 ├─ convert → 行循环 + 表格/图像插入 ├─ classify → 标题、列表、代码 └─ postprocess → 清理 → 最终 Markdown
文档通过 load_document_from_path / load_document_from_mem 仅加载一次,并在检测和提取阶段之间共享,因此没有冗余解析。
项目结构
src/ lib.rs — 公共 API、PdfOptions 构建器、便捷函数 python.rs — PyO3 Python 绑定 types.rs — 共享类型:TextItem、TextLine、PdfRect、ItemType text_utils.rs — 字符/文本辅助(CJK、RTL、连字、粗体/斜体) process_mode.rs — ProcessMode 枚举(DetectOnly、Analyze、Full) detector.rs — 无需完整加载文档即可快速检测 PDF 类型 glyph_names.rs — Adobe Glyph List → Unicode 映射 tounicode.rs — 用于 CID 编码文本的 ToUnicode CMap 解析 extractor/ — 文本提取流水线 tables/ — 表格检测和格式化 markdown/ — Markdown 转换和结构检测 bin/ — CLI 工具(pdf2md、detect_pdf) napi/ — Node.js/Bun 绑定(napi-rs) wasm/ — 浏览器绑定(wasm-bindgen)
分类工作原理
- 解析 xref 表和页面树(不完整加载对象)
- 根据
ScanStrategy选择页面(默认:所有页面,支持提前退出) - 在内容流中查找
Tj/TJ(文本运算符)和Do(图像运算符) - 根据采样页面中文本运算符的出现情况分类
这可在毫秒内检测包含 300+ 页的 PDF。结果包含 pages_needing_ocr —— 一个缺少文本的特定页码列表,支持按页 OCR 路由,而不是全有或全无。
扫描策略
| 策略 | 行为 | 最佳适用场景 |
|---|---|---|
EarlyExit(默认) | 扫描所有页面,在遇到第一个非文本页面时停止 | 将 TextBased PDF 路由到快速提取的流水线 |
Full | 扫描所有页面,无提前退出 | 准确的 Mixed 与 Scanned 分类 |
Sample(n) | 采样 n 个均匀分布的页面(首页、末页、中间页) | 速度比精度更重要的超大 PDF |
Pages(vec) | 仅扫描指定的从 1 开始的页码 | 调用方知道要检查哪些页面时 |
Markdown 输出
转换器处理:
| 元素 | 检测方式 |
|---|---|
| 标题(H1-H4) | 相对正文文本的字体大小层级,带 0.5pt 聚类 |
| 粗体/斜体 | 字体名称模式(Bold、Italic、Oblique) |
| 项目符号列表 | *、-、*、○、●、◦ 前缀 |
| 编号列表 | 1.、1)、(1) 模式 |
| 字母列表 | a.、a)、(a) 模式 |
| 代码块 | 等宽字体(Courier、Consolas、Monaco、Menlo、Fira Code、JetBrains Mono)和关键字检测 |
| 表格 | 基于 PDF 绘图操作的矩形检测 + 基于文本对齐的启发式检测 |
| 财务报表 | 针对合并数字值的 Token 拆分 |
| 标题说明 | “Figure”、“Table”、“Source:” 前缀检测 |
| 上标/下标 | 相对基线的字体大小和 Y 偏移 |
| URL | 转换为 Markdown 链接 |
| 连字符断词 | 重新连接跨行断开的单词 |
| 页码 | 从输出中过滤 |
| 首字下沉 | 大型首字母与后续文本合并 |
| 点引导符 | 目录样式的点折叠为 “ … “ |
用例:智能 PDF 路由
pdf-inspector 专为大规模处理 PDF 的流水线而构建。无需将每个 PDF 都发送到 OCR:
PDF 到达 → pdf-inspector 分类(约 20ms) → TextBased 且置信度高? 是 → 本地提取(约 150ms),完成 否 → 发送到 OCR 服务(2-10s)
这为大多数已经是基于文本的 PDF(报告、论文、发票、法律文档)节省了成本和延迟。
调试
有关 RUST_LOG 环境变量的用法,请参阅 docs/debugging.md。
许可证
相似文章
@GitHub_Daily: 给大模型喂 PDF 文档,常见做法是先跑 OCR 再提文字,但实际上有一半多的 PDF 本来就是文字版,根本不需要 OCR。 Firecrawl 团队最近开源的 pdf-inspector,能自动判断 PDF 是文字版还是扫描版,文字版的…
Firecrawl 团队开源了 pdf-inspector,一个快速 Rust 库,可自动判断 PDF 是文字版还是扫描版,并直接提取文字转成 Markdown,免去不必要的 OCR,支持表格、多栏排版识别,提供 Python/Node.js/Rust/WASM 接口。
firecrawl/firecrawl
Firecrawl 是一个开源 API,用于搜索、抓取和将网页内容转换为干净的 Markdown 或结构化数据,供 AI 应用使用。它能处理代理、速率限制和 JavaScript 密集型页面,且延迟低。
@knowledgefxg: 实用开源小工具推荐:pdf-inspector 解决的是一个很实际的问题:并不是所有 PDF 都需要 OCR。 比方说你扔给它一个 PDF,它先判断这个 PDF 到底是什么类型——是正常的文字版(比如用 Word 导出的)、还是扫描版(图…
pdf-inspector 是一个开源的 Rust 库,用于智能分类 PDF 类型(文字版或扫描版),并提取文本和转换为 Markdown,避免不必要的 OCR,提高速度和节省成本。
@jerryjliu0: 我们刚刚发布了LiteParse的一个功能,该功能允许在Rust中原生处理图像到PDF的转换,从而去除对外部包的依赖……
LiteParse是一个快速、轻量级、开源的PDF解析工具,使用Rust编写,原生支持图像到PDF的转换,并提供带有边界框的空间文本解析,可通过多种包(Rust、Node.js、Python、WASM)使用。
@jerryjliu0: 以光速解析PDF(此视频为1倍速)简直是电影
Jerry Liu宣布了LiteParse v2,一款基于Rust的PDF解析器,据称是目前最快、最准确的开源、无模型PDF解析器。