pdf-inspector:基于 Rust 的 PDF 分类与文本提取工具项目

Fast Rust library for PDF inspection, classification, and text extraction. Intelligently detects scanned vs text-based PDFs to enable smart routing decisions.

Branch196Tags23
This repository is empty

pdf-inspector

Crates.io npm PyPI License: MIT

一款用于 PDF 分类与文本提取的高性能 Rust 库。默认情况下,它会判断 PDF 是文本型还是扫描型,并以位置感知方式提取文本,将其转换为干净的 Markdown,而无需 OCR。原生 Rust 和 CLI 使用者可选择启用选择性 OCR。提供 PythonNode.js 以及浏览器 WebAssembly 绑定。

Firecrawl 打造,可在本地于 200ms 内处理文本型 PDF,并为约 54% 无需 OCR 的 PDF 跳过昂贵的 OCR 服务。

功能特性

  • 智能分类 — 通过采样内容流,在约 10-50ms 内检测 TextBased、Scanned、ImageBased 或 Mixed PDF。返回置信度分数(0.0-1.0)和逐页 OCR 路由。
  • 文本提取 — 位置感知提取,包含字体信息、X/Y 坐标,并自动恢复多栏阅读顺序。旋转的文本行(页边印章、图表轴标题)保留真实的轴对齐包围盒,并报告其 rotation 角度,而不是将宽度折叠为零。
  • Markdown 转换 — 标题(H1-H4,基于字号比例)、项目符号/编号/字母列表、代码块(等宽字体检测)、表格(基于矩形和启发式规则)、粗体/斜体格式、URL 链接以及分页。
  • 表格检测 — 双模式:基于 PDF 绘图指令的矩形检测,以及基于文本对齐的启发式检测。可处理财务表格、脚注以及跨页的连续表格。
  • CID 字体支持 — 支持 Type0/Identity-H 字体的 ToUnicode CMap 解码,支持 UTF-16BE、UTF-8 和 Latin-1 编码。
  • 多栏布局 — 自动检测报纸式栏位、顺序阅读顺序,并支持 RTL 文本。
  • 编码问题检测 — 自动标记损坏的字体编码,以便调用方回退到 OCR。
  • 选择性 OCR — Rust、CLI、Python 和 Node 可仅渲染需要 OCR 的页面,在本地运行 PP-OCRv6 Small,并保留逐页来源信息以及托管回退建议。
  • 单次文档加载 — 文档仅解析一次,并在检测和提取之间共享,避免冗余 I/O。
  • 浏览器 WebAssembly — 在浏览器和 Web Workers 中本地运行相同的 Rust 解析器,内置 CMaps,无需服务器往返。
  • 默认轻量 — 默认 Rust 和浏览器构建保持纯提取。原生 Python 和 Node 软件包包含 OCR 集成,但 PDFium、ONNX Runtime 和模型文件仍保持外部依赖状态,仅在页面被路由到 OCR 时才会被加载。

基准测试

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。速度为排除一次预热运行后,五次交替或轮换完整语料库运行的中位数;每个解析器都在单个进程中按顺序处理文档。

完整的解析器配置、逐文档预测、评估器输出以及生成的图表,可在可复现结果分支中获取。

最佳适用场景: 对速度、阅读顺序和表格结构要求较高的原生文本 PDF。在本次对比中,pdf-inspector 取得了更高的总体、阅读顺序和表格得分,并拥有最快的完整运行耗时。这使它成为报告、研究论文、财务文件、发票和法律 PDF 的理想本地默认方案,这些文件需要干净、结构化的 Markdown,且无需引入额外的 OCR 延迟或基础设施。

使用配对基准测试框架,在完全相同的语料库和评估器版本下比较两个本地构建版本。

快速开始

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 string or None

# Selective OCR; clean text PDFs do not load the external OCR runtime.
ocr = pdf_inspector.process_pdf_with_ocr("document.pdf")
print(ocr.pages_routed_to_ocr)

完整 API 参考:docs/python.md

Node.js

npm install @firecrawl/pdf-inspector
import { readFileSync } from 'fs';
import { processPdf, processPdfWithOcr } from '@firecrawl/pdf-inspector';

const pdf = readFileSync('document.pdf');
const result = processPdf(pdf);
console.log(result.pdfType);   // "TextBased", "Scanned", "ImageBased", "Mixed"
console.log(result.markdown);  // Markdown string or null

const ocr = await processPdfWithOcr(pdf); // selective OCR, off the event loop
console.log(ocr.pagesRoutedToOcr);

完整 API 参考:napi/README.md

浏览器 WebAssembly

npm install @firecrawl/pdf-inspector-wasm
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 安装:

cargo add pdf-inspector

或者手动添加:

[dependencies]
pdf-inspector = "1"
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

# Install the CLI tools
cargo install pdf-inspector

# Convert PDF to Markdown
pdf2md document.pdf

# JSON output (for piping)
pdf2md document.pdf --json

# Positioned TextItem JSON (coordinates relative to the visible page box): axis-aligned box, rotation, font, underline metadata
pdf2md document.pdf --items-json

# Raw markdown only (no headers)
pdf2md document.pdf --raw

# Token-efficient output (collapses long dot leaders and similar source padding)
pdf2md document.pdf --compact

# Insert page break markers (<!-- Page N -->)
pdf2md document.pdf --pages

# Process only specific pages
pdf2md document.pdf --select-pages 1,3,5-10

# Detection only (no extraction)
detect-pdf document.pdf
detect-pdf document.pdf --json

# Detection + layout analysis (tables, columns)
detect-pdf document.pdf --analyze --json

Rust 与 CLI 使用者可在构建时选择启用 OCR:

cargo install pdf-inspector --features ocr --bin pdf2md
PDFIUM_LIB_PATH=/path/to/libpdfium ORT_DYLIB_PATH=/path/to/libonnxruntime \
  pdf2md scan.pdf --ocr auto --json

带版本号的 OCR JSON 封装会报告已路由页面、每页来源与置信度、警告信息,以及建议交由托管文档流水线处理的页面。原生 Python 和 Node 包可暴露相同流水线,无需源码构建特性。所有原生入口点仍然只在 OCR 被路由时,才需要单独安装的 PDFium 和 ONNX Runtime 库。如需了解固定版本下载、平台支持、模型缓存行为以及托管回退集成,请参阅 OCR 运行时配置指南。如需更低层级的控制,请参阅 Rust API 指南

在源码检出环境中,请改用 cargo run --bin pdf2md -- document.pdfcargo run --bin detect-pdf -- document.pdf

架构

PDF bytes
  │
  ├─► detector         → PdfType (TextBased / Scanned / ImageBased / Mixed)
  │
  └─► extractor
        ├─ fonts        → font widths, encodings
        ├─ content_stream → walk PDF operators → TextItems + PdfRects
        ├─ xobjects     → Form XObject text, image placeholders
        ├─ links        → hyperlinks, AcroForm fields
        └─ layout       → column detection → line grouping → reading order
              │
              ├─► tables
              │     ├─ detect_rects      → rectangle-based tables (union-find)
              │     ├─ detect_heuristic  → alignment-based tables
              │     ├─ grid              → column/row assignment → cells
              │     └─ format            → cells → Markdown table
              │
              └─► markdown
                    ├─ analysis     → font stats, heading tiers
                    ├─ preprocess   → merge headings, drop caps
                    ├─ convert      → line loop + table/image insertion
                    ├─ classify     → captions, lists, code
                    └─ postprocess  → cleanup → final Markdown

文档通过 load_document_from_path / load_document_from_mem 仅加载一次,并在检测与提取阶段之间共享,因此不存在重复解析。

项目结构

src/
  lib.rs                — Public API, PdfOptions builder, convenience functions
  python.rs             — PyO3 Python bindings
  types.rs              — Shared types: TextItem, TextLine, PdfRect, ItemType
  text_utils.rs         — Character/text helpers (CJK, RTL, ligatures, bold/italic)
  process_mode.rs       — ProcessMode enum (DetectOnly, Analyze, Full)
  detector.rs           — Fast PDF type detection without full document load
  glyph_names.rs        — Adobe Glyph List → Unicode mapping
  tounicode.rs          — ToUnicode CMap parsing for CID-encoded text
  extractor/            — Text extraction pipeline
  tables/               — Table detection and formatting
  markdown/             — Markdown conversion and structure detection
  bin/                  — CLI tools (pdf2md, detect_pdf)
napi/                   — Node.js/Bun bindings (napi-rs)
wasm/                   — Browser bindings (wasm-bindgen)

分类机制

  1. 解析 xref 表和页树(不加载完整对象)
  2. 根据 ScanStrategy 选择页面(默认:扫描全部页面并提前退出)
  3. 在内容流中查找 Tj/TJ(文本操作符)和 Do(图像操作符)
  4. 根据采样页面中是否存在文本操作符进行分类

该机制可在毫秒内识别 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 绘制操作中的矩形检测,加上基于文本对齐的启发式检测
财务表格 对合并的数值进行拆分
图注/表注 检测 "Figure"、"Table"、"Source:" 前缀
上标/下标 相对于基线的字号和 Y 轴偏移
网址 转换为 Markdown 链接
连字符断行 将跨行拆分的单词重新连接
页码 从输出中过滤掉
首字下沉 将大号首字母与后续文本合并
点线引导符 目录样式的点线被折叠为 " ... "

应用场景:智能 PDF 路由

pdf-inspector 专为大规模处理 PDF 的流水线而打造。无需将每一份 PDF 都进行 OCR 处理:

PDF arrives
  → pdf-inspector classifies it (~20ms)
  → TextBased + high confidence?
      YES → extract locally (~150ms), done
      NO  → send to OCR service (2-10s)

这有助于降低大多数本身即为文本型 PDF 文件(如报告、论文、发票和法律文档)的处理成本与延迟。

调试

有关 RUST_LOG 环境变量的用法,请参阅 docs/debugging.md

许可证

MIT

Introduction

用于 PDF 检查、分类和文本提取的快速 Rust 库。智能检测扫描型与文本型 PDF,助力实现智能路由决策。【此简介由AI生成】

Customize your domain
5819.13 K1.28 KVisit GitHub