引言:PDF 解析的痛點

作為開發者,處理 PDF 文件是一個繞不開的需求——發票解析、合約提取、論文爬取、資料歸檔,幾乎每個後端專案都會遇到。但 PDF 解析長期以來是個痛點:

  • OCR 服務昂貴:呼叫雲 OCR API 每頁幾毛錢,量大成本驟增
  • 開源方案慢:PyMuPDF4LLM 處理 200 份文件需要 17 秒,MarkItDown 需要 16 秒
  • 格式丟失:傳統提取工具只吐純文字,標題層級、表格結構、程式碼區塊全丟了
  • 智慧路由缺失:無法自動區分掃描件和原生文字 PDF,導致對不需要 OCR 的文件也走 OCR 流程

2026 年 7 月,知名網頁爬取平台 Firecrawl 開源了一個 Rust 編寫的 PDF 解析函式庫 pdf-inspector,上線僅數週就拿下 7,900+ Stars,GitHub Trending 日榜前三。它承諾在 200ms 內完成本機 PDF 分類和文字提取,自動輸出帶格式的 Markdown——無需 OCR,無需外部服務。

今天我們就來深度體驗這個專案,看看它憑什麼能在效能上輾壓主流方案。

pdf-inspector 是什麼?

pdf-inspector 是 Firecrawl 團隊用 Rust 編寫的 PDF 分類和文字提取函式庫,核心能力包括:

  1. 智慧分類 — 在 10-50ms 內偵測 PDF 類型:原生文字(TextBased)、掃描件(Scanned)、圖片型(ImageBased)或混合型(Mixed),返回信賴度和逐頁 OCR 路由建議
  2. 文字提取 — 帶位置感知的文字提取,包含字型資訊、X/Y 座標、自動多欄閱讀順序
  3. Markdown 轉換 — 自動識別 H1-H4 標題、列表、程式碼區塊(等寬字型偵測)、表格、粗斜體、URL 連結和分頁符
  4. 表格偵測 — 雙模式表格偵測(基於 PDF 繪製操作的矩形偵測 + 基於文字對齊的啟發式偵測),完美處理財務報表和跨頁表格
  5. CID 字型支援 — ToUnicode CMap 解碼,支援 Type0/Identity-H 字型、UTF-16BE、UTF-8 和 Latin-1 編碼
  6. 多語言綁定 — 提供 Python、Node.js 和瀏覽器 WebAssembly 綁定

為什麼用 Rust? Rust 的零成本抽象和記憶體安全特性讓 pdf-inspector 在不依賴 ML 模型和外部服務的情況下,實現了極致的解析速度。整個函式庫只有一個外部依賴:lopdf(Rust PDF 解析函式庫)。

效能對比

根據官方在 Apple M4 Pro 上的基準測試(200 份文件,opendataloader-bench 語料庫):

引擎 綜合成績 閱讀順序 表格識別 標題識別 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.169s
MarkItDown 0.589 0.844 0.273 0.000 16.117s

pdf-inspector 在綜合成績、閱讀順序、表格識別和速度上均全面領先,耗時僅為 PyMuPDF4LLM 的 1/36、MarkItDown 的 1/34

安裝

pdf-inspector 支援多種安裝方式,涵蓋 Rust、Python、Node.js 和瀏覽器環境。

Rust(原生)

Cargo.toml 中添加相依套件:

[dependencies]
pdf-inspector = "0.2"

或透過 cargo 命令列安裝:

cargo add pdf-inspector

Python

pdf-inspector 透過 maturin 提供 Python 綁定:

pip install maturin
git clone https://github.com/firecrawl/pdf-inspector.git
cd pdf-inspector
maturin develop --release

💡 提示: 目前 PDF-inspector 尚未發布到 PyPI,需要透過原始碼編譯安裝。Firecrawl 團隊計畫在穩定後發布 PyPI 套件。

Node.js

npm install @firecrawl/pdf-inspector

瀏覽器 WebAssembly

npm install @firecrawl/pdf-inspector-wasm

Wasm 版本將完整的 Rust 解析器嵌入瀏覽器,可以在 Web Worker 中執行,無需伺服器往返。

快速上手

Python 範例

安裝完成後,使用非常簡單——只需呼叫一個函式:

import pdf_inspector

# 處理單個 PDF 檔案
result = pdf_inspector.process_pdf("document.pdf")

# 檢視 PDF 類型分類
print(f"PDF 類型: {result.pdf_type}")
# 輸出: "text_based", "scanned", "image_based", 或 "mixed"

# 獲取 Markdown 輸出
if result.markdown:
    print(result.markdown)

就這麼簡單。一行程式碼,完成分類 + 提取 + Markdown 轉換。

Node.js 範例

const { processPdf } = require('@firecrawl/pdf-inspector');
const fs = require('fs');

async function analyzePdf(filePath) {
  const pdfBuffer = fs.readFileSync(filePath);
  const result = await processPdf(pdfBuffer);

  console.log('PDF 類型:', result.pdfType);
  console.log('信賴度:', result.confidence);
  console.log('--- Markdown 輸出 ---');
  console.log(result.markdown);
}

analyzePdf('report.pdf');

Rust 原生範例

use pdf_inspector::{PdfInspector, ProcessPdfResult};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let inspector = PdfInspector::new();
    let result: ProcessPdfResult = inspector.process_pdf_path("document.pdf")?;

    println!("PDF 類型: {:?}", result.pdf_type);
    println!("信賴度: {:.2}", result.confidence);

    if let Some(markdown) = result.markdown {
        println!("Markdown:\n{}", markdown);
    }

    Ok(())
}

核心功能詳解

1. 智慧分類:避免不必要的 OCR 開銷

pdf-inspector 最實用的功能之一是自動分類。它透過對 PDF 內容流進行取樣,在 10-50ms 內判斷文件類型:

類型 說明 建議處理策略
text_based 原生文字 PDF,包含可提取的文字內容流 直接用 pdf-inspector 提取,跳過 OCR
scanned 掃描件(圖片型頁面) 需要 OCR 服務
image_based 以圖片為主的 PDF(如截圖集合) 需要 OCR 或圖片處理
mixed 混合類型(部分頁面有文字,部分是掃描件) 逐頁決定:文字頁直接提取,掃描頁呼叫 OCR

實戰場景:建構智慧 PDF 處理管道

import pdf_inspector
# 假設你有自己的 OCR 函式
def smart_pdf_pipeline(pdf_path, ocr_function):
    result = pdf_inspector.process_pdf(pdf_path)

    if result.pdf_type == "text_based":
        # 原生文字,直接提取——快速、免費、準確
        print("✅ 原生文字 PDF,直接提取")
        return result.markdown

    elif result.pdf_type == "scanned":
        # 掃描件,呼叫 OCR
        print("🔍 掃描件 PDF,呼叫 OCR")
        return ocr_function(pdf_path)

    elif result.pdf_type == "mixed":
        # 混合型——逐頁處理
        print("📄 混合型 PDF,逐頁路由")
        pages = []
        for page_info in result.page_results:
            if page_info.needs_ocr:
                pages.append(ocr_function_for_page(pdf_path, page_info.page_number))
            else:
                pages.append(page_info.markdown)
        return "\n\n".join(pages)

    else:
        # 純圖片型,無法提取文字
        print("❌ 圖片型 PDF,無法提取文字")
        return None

這個管道可以對約 54% 的 PDF(原生文字型)完全跳過 OCR,大幅降低處理成本和延遲。

2. Markdown 轉換:保留文件結構

pdf-inspector 的 Markdown 輸出不僅僅是純文字——它會智慧識別並保留文件的結構資訊:

  • 標題層級(H1-H4):透過字型大小比例自動推斷
  • 列表:自動識別項目符號列表、編號列表、字母編號列表
  • 程式碼區塊:透過等寬字型偵測自動標記為程式碼區塊
  • 表格:支援矩形偵測和啟發式偵測,處理財務報表和跨頁表格
  • 粗斜體:保留粗體和斜體格式
  • URL 連結:自動識別並轉換為 Markdown 連結格式
  • 分頁符:用 --- 分隔不同頁面

來看看實際效果。假設有一份學術論文 PDF:

# Deep Learning Approaches for Natural Language Processing

## 1. Introduction

Natural language processing (NLP) has seen remarkable progress in recent years...

### 1.1 Background

The transformer architecture, introduced by Vaswani et al., has become...

## 2. Methodology

| Model | BLEU Score | Training Time |
|-------|-----------|---------------|
| Transformer | 38.2 | 12 hours |
| BERT | 41.0 | 24 hours |
| GPT-4 | 45.7 | 72 hours |

## 3. Results

The experimental results demonstrate...

> **Note:** All experiments were conducted on...

標題層級、表格、引用區塊都完整保留了,這比傳統 PDF 提取工具只輸出純文字強太多。

3. 多欄和閱讀順序偵測

很多 PDF(如論文、報紙、雜誌)採用多欄版面配置。pdf-inspector 會自動偵測欄結構並按正確的閱讀順序提取:

result = pdf_inspector.process_pdf("newspaper.pdf")

# pdf-inspector 自動偵測雙欄/三欄版面配置
# 並按從上到下、從左到右的正確順序輸出
print(result.markdown)

同時支援 RTL(從右到左)文字,適合阿拉伯語、希伯來語等文件。

4. CID 字型與編碼問題偵測

處理中文、日文、韓文 PDF 時,字型編碼常常出問題。pdf-inspector 支援 ToUnicode CMap 解碼,能正確處理:

  • Type0 / Identity-H 字型
  • UTF-16BE、UTF-8 和 Latin-1 編碼
  • 自動標記破損的字型編碼

這意味著處理中日韓文 PDF 時,它能告訴你哪些頁面可能有亂碼風險,讓你提前決定是否需要 OCR 回退。

進階實戰:建構 PDF 處理服務

下面我們來建構一個完整的 PDF 處理微服務,整合 pdf-inspector 的智慧分類能力。

場景:文件歸檔系統

假設你在搭建一個企業內部文件歸檔系統,每天需要處理數百份 PDF(合約、發票、報告等):

# pdf_service.py
import os
import json
from datetime import datetime
import pdf_inspector

class PdfProcessingService:
    def __init__(self, output_dir="./processed"):
        self.output_dir = output_dir
        os.makedirs(output_dir, exist_ok=True)

    def process_batch(self, pdf_files):
        """批次處理 PDF 檔案"""
        results = []
        for pdf_path in pdf_files:
            result = self.process_single(pdf_path)
            results.append(result)
        return results

    def process_single(self, pdf_path):
        """處理單個 PDF 檔案"""
        filename = os.path.basename(pdf_path)
        pdf_result = pdf_inspector.process_pdf(pdf_path)

        # 提取元資訊
        metadata = {
            "filename": filename,
            "pdf_type": pdf_result.pdf_type,
            "confidence": pdf_result.confidence,
            "processed_at": datetime.now().isoformat(),
            "pages_count": len(pdf_result.page_results) if hasattr(pdf_result, 'page_results') else 0,
            "needs_ocr": pdf_result.pdf_type in ("scanned", "image_based"),
        }

        # 儲存 Markdown 輸出
        if pdf_result.markdown:
            md_filename = filename.replace(".pdf", ".md")
            md_path = os.path.join(self.output_dir, md_filename)
            with open(md_path, "w", encoding="utf-8") as f:
                f.write(pdf_result.markdown)
            metadata["markdown_path"] = md_path

        # 儲存元資訊
        meta_path = os.path.join(
            self.output_dir,
            filename.replace(".pdf", ".meta.json")
        )
        with open(meta_path, "w", encoding="utf-8") as f:
            json.dump(metadata, f, ensure_ascii=False, indent=2)

        return metadata

# 使用範例
service = PdfProcessingService(output_dir="./output")

# 批次處理
pdf_files = [
    "contracts/contract_2026_001.pdf",
    "invoices/invoice_aug_2026.pdf",
    "reports/q2_financial_report.pdf",
]

results = service.process_batch(pdf_files)
for r in results:
    status = "需要 OCR" if r["needs_ocr"] else "已直接提取"
    print(f"{r['filename']}: {r['pdf_type']} ({status})")

場景:與 LLM 文件分析管道整合

pdf-inspector 輸出的高品質 Markdown 可以直接餵給 LLM 進行分析:

import pdf_inspector
# 假設你使用 OpenAI 相容 API
from openai import OpenAI

def analyze_pdf_with_llm(pdf_path, prompt="總結這份文件的主要內容"):
    """用 LLM 分析 PDF 內容"""
    # 1. 用 pdf-inspector 提取 Markdown
    result = pdf_inspector.process_pdf(pdf_path)

    if not result.markdown:
        return "無法提取文字內容,可能需要 OCR"

    # 2. 如果文件太長,截取前 8000 字元
    markdown_content = result.markdown[:8000]

    # 3. 呼叫 LLM 分析
    client = OpenAI(api_key="YOUR_API_KEY")
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": "你是一個文件分析助手。"},
            {"role": "user", "content": f"請基於以下文件內容{prompt}:\n\n{markdown_content}"}
        ]
    )

    return response.choices[0].message.content

# 使用
summary = analyze_pdf_with_llm("annual_report.pdf", "提取關鍵財務指標")
print(summary)

這種管道在 RAG(檢索增強生成)系統中特別有用——先用 pdf-inspector 快速提取結構化文字,再向量化存入知識庫。

與其他方案的對比

pdf-inspector vs PyMuPDF4LLM

維度 pdf-inspector PyMuPDF4LLM
語言 Rust Python (C 綁定)
綜合成績 0.875 0.735
表格識別 0.814 0.401
速度(200 文件) 0.47s 17.169s
Markdown 結構 ✅ 完整保留 ⚠️ 部分丟失
智慧分類 ✅ 內建 ❌ 無
瀏覽器 Wasm ✅ 支援 ❌ 不支援

pdf-inspector vs MarkItDown(Microsoft)

維度 pdf-inspector MarkItDown
綜合成績 0.875 0.589
標題識別 0.788 0.000
速度(200 文件) 0.47s 16.117s
多語言綁定 Python/Node/Wasm Python
專注度 專注 PDF 解析 通用文件轉換

什麼時候用 pdf-inspector,什麼時候用 OCR?

  • 用 pdf-inspector:原生文字 PDF、報告、論文、合約、發票等帶文字內容流的文件
  • 用 OCR:掃描件、純圖片 PDF、手寫文件
  • 混合使用:先用 pdf-inspector 分類,text_based 直接提取,scanned/image_based 走 OCR——這正是 pdf-inspector 設計的路由策略

專案資訊與社群

  • GitHubfirecrawl/pdf-inspector
  • Stars:7,900+(2026 年 7 月上線,增速強勁)
  • License:Apache-2.0(商業友好)
  • 語言:Rust
  • 生態:Firecrawl 出品(知名網頁爬取平台,同時開源了 firecrawl 爬蟲引擎)

安裝管道

平台 安裝方式
Rust crates.io/crates/pdf-inspector
Python 原始碼編譯(maturin develop --release
Node.js npm install @firecrawl/pdf-inspector
瀏覽器 npm install @firecrawl/pdf-inspector-wasm

總結

pdf-inspector 的出現填補了一個重要空白——輕量、快速、本機化的 PDF 解析方案。它不需要 ML 模型,不需要外部服務,純 Rust 實現,在保持高精度的同時實現了遠超同類工具的速度。

核心優勢總結:

  1. 🚀 極快速度——200ms 級解析,是 PyMuPDF4LLM 的 36 倍
  2. 🧠 智慧分類——自動區分文字/掃描/圖片型 PDF,最佳化 OCR 路由
  3. 📐 結構保留——標題、表格、程式碼區塊、列表完整保留為 Markdown
  4. 🔒 純本機——無外部依賴,無 API 呼叫,資料不出機器
  5. 🌐 多平台——Rust/Python/Node.js/瀏覽器 Wasm 全涵蓋

如果你正在建構文件處理管道、RAG 系統或任何需要解析 PDF 的應用,pdf-inspector 值得加入你的技術棧。特別是對於以原生文字 PDF 為主的場景,它能幫你省去大量 OCR 成本和延遲。

🔗 相關連結 - GitHub: firecrawl/pdf-inspector - Python 文件: docs/python.md - 基準測試: opendataloader-bench - Firecrawl: firecrawl.dev