pdfplumber vs PyMuPDF – 速度・テーブル・ライセンス
pdfplumber と PyMuPDF はどちらも人気の Python PDF ライブラリですが、いずれもトレードオフを強いられます。pdfplumber はテーブルに優れているものの、必要以上に29倍遅いです。PyMuPDF は高速ですが、商用利用を妨げる AGPL-3.0 ライセンスに縛られています。本ページでは両者を比較し、なぜ PDF Oxide が多くのユースケースでより良い選択肢なのかを示します。
端的に言うと: PDF Oxide は pdfplumber より29倍、PyMuPDF より5.8倍高速で、MIT ライセンスであり、テキスト・画像・フォーム・暗号化・Markdown 出力・OCR をすべて一つのライブラリで扱えます。pdfplumber が今なお優位に立つ唯一の領域は、視覚的デバッグを伴う複雑なテーブル抽出です。
クイック比較
| pdfplumber | PyMuPDF | PDF Oxide | |
|---|---|---|---|
| ライセンス | MIT | AGPL-3.0 | MIT |
| 言語 | 純粋な Python | C(MuPDF) | Rust + PyO3 |
| 平均抽出時間 | 23.2ms | 4.6ms | 0.8ms |
| p99 抽出時間 | 189ms | 28ms | 9ms |
| 成功率(3,830件の PDF) | 98.8% | 99.3% | 100% |
| テキスト抽出 | あり | あり | あり |
| 文字位置 | あり | あり | あり |
| テーブル抽出 | 高度 | 基本的 | 基本的 |
| 画像抽出 | なし | あり | あり |
| 視覚的デバッグ | あり | なし | なし |
| PDF 作成 | なし | あり | あり |
| PDF 編集 | なし | あり | あり |
| Markdown 出力 | なし | なし | あり |
| HTML 出力 | なし | なし | あり |
| フォームフィールド | 読み取りのみ | 読み取り+書き込み | 読み取り+書き込み |
| 暗号化 | なし | 読み取り+書き込み | 読み取り+書き込み |
| レンダリング | なし | あり | あり |
| OCR | なし | Tesseract | 組み込み(PaddleOCR) |
| インストールサイズ | 約1 MB | 約20 MB | 約5 MB |
| Python バージョン | 3.8+ | 3.8–3.12 | 3.8–3.14 |
速度ベンチマーク
3つのライブラリすべてを、3つの独立した公開テストスイート(veraPDF、Mozilla pdf.js、DARPA SafeDocs)から集めた同一の3,830件の PDF コーパスでベンチマークしました。このコーパスは、あらゆる PDF 仕様バージョン(1.0–2.0)、暗号化ファイル、不正な形式のドキュメント、CJK エンコーディング、複雑なレイアウトを網羅しています。
| 指標 | pdfplumber | PyMuPDF | PDF Oxide |
|---|---|---|---|
| 平均抽出時間 | 23.2ms | 4.6ms | 0.8ms |
| p99 抽出時間 | 189ms | 28ms | 9ms |
| PDF Oxide との相対比 | 29倍遅い | 5.8倍遅い | 1倍 |
| 成功率(有効な PDF) | 98.8%(3,777/3,823) | 99.3%(3,796/3,823) | 100%(3,823/3,823) |
PyMuPDF は、すべての解析を MuPDF の C ライブラリに委譲しているため、pdfplumber よりおよそ5倍高速です。pdfplumber は解析に pdfminer を使い、その上に独自の空間解析レイヤーを追加していますが、いずれも純粋な Python で書かれています。PDF Oxide は、解析・フォントデコード・テキスト組み立てのすべてを、PyO3 を介して Python プロセス内で直接動作するコンパイル済みの Rust で処理しており、これが PyMuPDF に対する5.8倍、pdfplumber に対する29倍の優位性を生んでいます。
この数字が実際に意味すること
| ワークロード | pdfplumber | PyMuPDF | PDF Oxide |
|---|---|---|---|
| 100件の PDF | 2.3秒 | 0.46秒 | 0.08秒 |
| 1,000件の PDF | 23秒 | 4.6秒 | 0.8秒 |
| 10,000件の PDF | 3.9分 | 46秒 | 8秒 |
| 100,000件の PDF | 39分 | 7.7分 | 80秒 |
数ファイルを処理する単発のスクリプトでは、速度差は問題になりません。しかし、毎日数千件のドキュメントを処理する本番パイプラインでは、39分と80秒の差はアーキテクチャの意思決定を左右します。
テーブル抽出
テーブル抽出は、開発者が PyMuPDF ではなく pdfplumber を選ぶ主な理由です。ここは pdfplumber が真に優れている領域です。
pdfplumber:構造化されたテーブル解析
pdfplumber は、設定可能な線検出、セル結合、視覚的デバッグを備えた専用のテーブル抽出機能を提供します。
import pdfplumber
with pdfplumber.open("invoice.pdf") as pdf:
page = pdf.pages[0]
# Extract all tables as structured data
tables = page.extract_tables()
for table in tables:
for row in table:
print(row)
# Fine-tune detection with custom settings
tables = page.extract_tables({
"vertical_strategy": "text",
"horizontal_strategy": "lines",
"snap_tolerance": 5,
})
# Visual debugging: render page with detected table boundaries
im = page.to_image()
im.debug_tablefinder()
im.save("debug.png")
pdfplumber は構造化された行/列データを返し、結合セル、複数列にまたがるヘッダー、罫線のないテーブルを扱えます。視覚的デバッグのオーバーレイは、扱いにくいレイアウトで抽出パラメータを調整する際に非常に役立ちます。
PyMuPDF:基本的なテーブル検出
PyMuPDF は近年のバージョンでテーブル検出を追加しましたが、pdfplumber のアルゴリズムほど成熟していません。
import fitz
doc = fitz.open("invoice.pdf")
page = doc[0]
# PyMuPDF's built-in table finder (added in v1.23)
tabs = page.find_tables()
for table in tabs:
df = table.to_pandas() # requires pandas
print(df)
PyMuPDF のテーブル抽出は、罫線が見えるシンプルなグリッド型テーブルでは機能します。しかし、罫線のないレイアウト、多階層ヘッダー、複数の行や列にまたがるセル、つまり pdfplumber が最も得意とするケースで苦戦します。
PDF Oxide:Markdown テーブル出力
PDF Oxide は、構造化出力パイプラインの一環として、テーブルを Markdown 構文に変換します。
from pdf_oxide import PdfDocument
doc = PdfDocument("invoice.pdf")
# Tables are detected and converted to Markdown table format
md = doc.to_markdown(0, detect_headings=True)
print(md)
# Also available as HTML with table tags
html = doc.to_html(0)
print(html)
PDF Oxide のテーブル検出は標準的なグリッドレイアウトで機能し、クリーンな Markdown または HTML 出力を生成します。結合セル、罫線のないデザイン、またはまたがるヘッダーを含む複雑なテーブルについては、pdfplumber の専用アルゴリズムが依然としてより堅牢です。
テーブル抽出のまとめ
| 機能 | pdfplumber | PyMuPDF | PDF Oxide |
|---|---|---|---|
| シンプルな罫線付きテーブル | あり | あり | あり |
| 罫線のないテーブル | あり | 限定的 | 限定的 |
| 結合セル | あり | 限定的 | 限定的 |
| 多階層ヘッダー | あり | なし | なし |
| 設定可能な検出 | あり | 限定的 | なし |
| 視覚的デバッグ | あり | なし | なし |
| 出力フォーマット | Python リスト | pandas DataFrame | Markdown / HTML |
| 速度 | 遅い(純粋な Python) | 高速 | 最速 |
複雑なテーブル抽出だけが目的であれば、pdfplumber が最適なツールです。高速なテキスト抽出、画像抽出、または PDF 作成と並んでテーブルが必要な場合は、PDF Oxide がより広範な領域をカバーします。
テキスト抽出
プレーンテキスト抽出については、両ライブラリとも仕事をこなしますが、速度と API 設計が異なります。
pdfplumber
import pdfplumber
with pdfplumber.open("report.pdf") as pdf:
page = pdf.pages[0]
text = page.extract_text()
print(text)
PyMuPDF
import fitz
doc = fitz.open("report.pdf")
page = doc[0]
text = page.get_text()
print(text)
PDF Oxide
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
text = doc.extract_text(0)
print(text)
3つとも、整形式の PDF に対しては同等のテキスト出力を生成します。PDF Oxide はコーパス全体で PyMuPDF と99.5%のテキスト一致率を達成しており、残り0.5%の差は空白の正規化とリガチャの扱いによるものです。
文字レベルの位置情報
pdfplumber と PyMuPDF はどちらも文字レベルの位置データを提供しており、これは空間解析、バウンディングボックス検出、カスタムレイアウト再構築にとって重要です。
pdfplumber
import pdfplumber
with pdfplumber.open("report.pdf") as pdf:
page = pdf.pages[0]
for char in page.chars[:10]:
print(f"'{char['text']}' at ({char['x0']:.1f}, {char['top']:.1f}) "
f"size={char['size']:.1f}")
PyMuPDF
import fitz
doc = fitz.open("report.pdf")
page = doc[0]
blocks = page.get_text("dict")["blocks"]
for block in blocks:
if "lines" in block:
for line in block["lines"]:
for span in line["spans"]:
print(f"'{span['text']}' size={span['size']:.1f}")
PDF Oxide
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
chars = doc.extract_chars(0)
for ch in chars[:10]:
print(f"'{ch.char}' at ({ch.x:.1f}, {ch.y:.1f}) size={ch.font_size:.1f}")
pdfplumber は、豊富なメタデータを持つ文字ごとの辞書を返します。PyMuPDF はネストされたブロック/行/スパン構造を返します。PDF Oxide は、位置とフォントのデータを持つフラットな文字オブジェクトを返します。
ライセンス
これは商用プロジェクトにおいて、pdfplumber と PyMuPDF の最も重大な違いです。
| pdfplumber | PyMuPDF | PDF Oxide | |
|---|---|---|---|
| ライセンス | MIT | AGPL-3.0 | MIT |
| 商用製品 | 可 | 商用ライセンスが必要 | 可 |
| クローズドソースの SaaS | 可 | 商用ライセンスが必要 | 可 |
| Docker での配布 | 可 | 商用ライセンスが必要 | 可 |
| 社内ツール | 可 | 可 | 可 |
| オープンソースプロジェクト | 可 | 可(AGPL 互換の場合) | 可 |
PyMuPDF の AGPL 問題
PyMuPDF は AGPL-3.0 ライセンスの MuPDF をラップしています。PyMuPDF を含むソフトウェア(SaaS、ウェブアプリ、Docker コンテナを含む)を配布する場合、自分のコードを AGPL の下でオープンソース化するか、Artifex から商用ライセンスを購入しなければなりません。
Artifex は商用ライセンスの価格を公開していません。見積もりを得るには営業チームに連絡する必要があります。ライセンスは通常アプリケーション単位で、毎年更新され、無料枠やスタートアップ向けの例外はありません。
pdfplumber と PDF Oxide はどちらも MIT
pdfplumber と PDF Oxide はどちらも MIT ライセンスです。いずれも、商用・プロプライエタリ・SaaS・オープンソースを問わず、どんなプロジェクトでも義務なしに使用できます。ライセンスが最優先事項で、pdfplumber と PyMuPDF のどちらかを選ぶ場合は、pdfplumber(または PDF Oxide)の方が安全な選択です。
暗号化された PDF
暗号化の扱いは pdfplumber の機能セットにおける大きな欠落であり、パスワード保護されたドキュメントを扱う開発者にとってよくある悩みの種です。
pdfplumber:暗号化非対応
pdfplumber は暗号化またはパスワード保護された PDF をまったく開けません。暗号化された PDF を pdfplumber に渡すとエラーが発生します。まず別のツールでファイルを復号する必要があります。
import pdfplumber
# This will fail on encrypted PDFs:
with pdfplumber.open("encrypted.pdf") as pdf:
# raises pdfminer.pdfparser.PDFSyntaxError or similar
pass
よくある回避策は、PyMuPDF または pypdf でまずファイルを復号し、その後テーブル抽出のために pdfplumber に渡すことですが、これはパイプラインに別の依存関係を追加することになります。
PyMuPDF:完全な暗号化対応
import fitz
doc = fitz.open("encrypted.pdf")
doc.authenticate("password")
page = doc[0]
text = page.get_text()
PyMuPDF はユーザーパスワードとオーナーパスワードの両方、AES-128 および AES-256 暗号化に対応し、暗号化された PDF を作成することもできます。
PDF Oxide:完全な暗号化対応
from pdf_oxide import PdfDocument
doc = PdfDocument("encrypted.pdf", password="password")
text = doc.extract_text(0)
PDF Oxide は、読み取りと書き込みの両方で、すべての標準的な PDF 暗号化方式(RC4、AES-128、AES-256)を扱えます。追加の依存関係や前処理は不要です。
画像抽出
これも pdfplumber の機能セットにおける欠落です。pdfplumber は PDF から埋め込み画像を抽出しません。
PyMuPDF
import fitz
doc = fitz.open("report.pdf")
page = doc[0]
for i, img in enumerate(page.get_images()):
xref = img[0]
base_image = doc.extract_image(xref)
with open(f"image_{i}.{base_image['ext']}", "wb") as f:
f.write(base_image["image"])
PDF Oxide
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
images = doc.extract_image_bytes(0)
for i, img in enumerate(images):
with open(f"image_{i}.{img['format']}", "wb") as f:
f.write(img["data"])
パイプラインで PDF からテキストと画像の両方を抽出する必要がある場合、pdfplumber は画像側を扱えません。そのためには PyMuPDF、PDF Oxide、または pypdfium2 が必要です。
Markdown と HTML 出力
pdfplumber も PyMuPDF も、組み込みの Markdown または HTML 変換を提供していません。これは PDF Oxide 独自の機能です。
from pdf_oxide import PdfDocument
doc = PdfDocument("paper.pdf")
# Markdown with heading detection and table formatting
md = doc.to_markdown(0, detect_headings=True)
print(md)
# HTML with semantic tags
html = doc.to_html(0)
print(html)
LLM パイプライン、RAG システム、ドキュメント変換ワークフローでは、構造化された Markdown 出力により、別途の変換ステップが不要になります。PyMuPDF ユーザーは通常、別パッケージの pymupdf4llm に頼りますが、これは PDF Oxide の組み込み変換より69倍遅いです。
各ライブラリを選ぶべき場面
次の場合は pdfplumber を選ぶ:
- 複雑なテーブル抽出が主なユースケースである。 pdfplumber のテーブルアルゴリズムは、結合セル、罫線のないテーブル、またがるヘッダーを、他のどの Python ライブラリよりもうまく扱います。
- 視覚的デバッグが必要である。 pdfplumber は、検出された線・文字・テーブル境界を示す注釈付きページ画像をレンダリングでき、扱いにくいドキュメントで抽出を調整する際に非常に役立ちます。
- 純粋な Python のソリューションが欲しい。 コンパイル済みの依存関係がなく、Python が動くところならどこにでもインストールできます。
- 速度が問題にならない。 一度に100ファイル未満を処理するのであれば、平均23ms は十分に許容できます。
次の場合は PyMuPDF を選ぶ:
- すでに商用 MuPDF ライセンスを持っており、MuPDF 固有のレンダリングや SVG エクスポートに依存している。
- 高忠実度のレンダリングが必要である。 MuPDF のレンダリングエンジンは成熟しており、複雑な PDF をうまく扱います。
- プロジェクトが AGPL 互換である。 AGPL または互換ライセンスの下でオープンソースソフトウェアを構築しているなら、PyMuPDF のライセンスは問題になりません。
- Tesseract による OCR が必要である。 PyMuPDF はスキャンされたドキュメント向けに Tesseract 統合を組み込んでいます。
次の場合は PDF Oxide を選ぶ:
- 速度と広範な機能カバレッジが必要である。 平均0.8ms の抽出 – PyMuPDF より5.8倍、pdfplumber より29倍高速 – でありながら、テキスト・画像・フォーム・作成・暗号化を一つのライブラリで扱えます。
- 速度を犠牲にせずに MIT ライセンスが欲しい。 pdfplumber は MIT だが遅い。PyMuPDF は高速だが AGPL。PDF Oxide は MIT かつ高速です。
- Markdown または HTML 出力が必要である。 LLM パイプラインと RAG システム向けの組み込み構造化変換。
- 寛容なライセンスで暗号化された PDF への対応が必要である。 pdfplumber は暗号化を扱えません。PyMuPDF は扱えますが AGPL への準拠が必要です。PDF Oxide は MIT の下で暗号化を扱います。
- 抽出・作成・編集を一つのライブラリで行いたい。 pdfplumber も PyMuPDF も、PDF ワークフローの一部には追加ツールが必要です。PDF Oxide は抽出・作成・編集・レンダリング・検証をカバーします。
PDF Oxide と pdfplumber を併用する:
高速なテキスト抽出、画像抽出、複雑なテーブル解析を必要とするパイプラインでは、一般的なパイプラインに PDF Oxide を、テーブルに pdfplumber を使います。
from pdf_oxide import PdfDocument
import pdfplumber
# Fast text and image extraction with PDF Oxide
doc = PdfDocument("report.pdf")
text = doc.extract_text(0)
images = doc.extract_images(0)
# Complex table extraction with pdfplumber
with pdfplumber.open("report.pdf") as pdf:
tables = pdf.pages[0].extract_tables()
インストール
# pdfplumber
pip install pdfplumber
# PyMuPDF
pip install pymupdf
# PDF Oxide
pip install pdf_oxide
3つとも pip でインストールできます。pdfplumber と PDF Oxide は MIT ライセンスです。PyMuPDF は AGPL-3.0 です – 商用プロジェクトに追加する前に、ライセンスの影響を確認してください。
結論
pdfplumber と PyMuPDF はどちらも問題の一部を解決します。PDF Oxide は問題全体を解決します。
| あなたにとって重要なこと | 最適な選択 |
|---|---|
| 最高速度 | PDF Oxide(0.8ms – pdfplumber より29倍高速) |
| 複雑なテーブル抽出 | pdfplumber(視覚的デバッグ、結合セル) |
| 寛容なライセンス+速度 | PDF Oxide – pdfplumber は MIT だが遅い、PyMuPDF は高速だが AGPL |
| 暗号化された PDF | PDF Oxide または PyMuPDF – pdfplumber は復号できない |
| 画像抽出 | PDF Oxide または PyMuPDF – pdfplumber は画像非対応 |
| Markdown/HTML 出力 | PDF Oxide – 組み込み変換を備えた唯一のライブラリ |
| Tesseract なしの OCR | PDF Oxide – 組み込みの PaddleOCR |
| すべてを一つのライブラリで | PDF Oxide – 抽出・作成・編集・暗号化・OCR |
ワークフロー全体が複雑なテーブル抽出(罫線のないテーブル、結合セル、視覚的デバッグ)でない限り、PDF Oxide は pdfplumber と PyMuPDF の両方を置き換えます — より高速で、機能が豊富で、MIT ライセンスです。
10秒で始める:
pip install pdf_oxide
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
text = doc.extract_text(0) # 29× faster than pdfplumber
md = doc.to_markdown(0) # built-in, no separate package
images = doc.extract_images(0) # pdfplumber can't do this
関連ページ
- PDF Oxide vs PyMuPDF – 移行ガイド付きの詳細比較
- PDF Oxide vs pdfplumber – コード例付きの詳細比較
- vs Python PDF ライブラリ – すべての Python ライブラリを比較
- パフォーマンスベンチマーク – コーパス全体のベンチマーク手法
- PDF からテーブルを抽出する – テーブル抽出ガイド
- Python で始める – インストールと最初の抽出