2026 年おすすめ Python PDF ライブラリ比較
PDF Oxide を PyMuPDF (fitz)、pypdfium2、pypdf、pdfplumber、pdfminer などと比較します。このページでは、テキスト抽出に適した Python の PDF ライブラリを選べるよう、処理性能、機能のカバー範囲、ライセンス、API の違いを整理しました。
サマリー
| PDF Oxide | PyMuPDF | pypdfium2 | pypdf | pdfplumber | pdfminer | |
|---|---|---|---|---|---|---|
| 平均抽出時間 | 0.8ms | 4.6ms | 4.1ms | 12.1ms | 23.2ms | 16.8ms |
| 成功率(3,830 PDF) | 100% | 99.3% | 99.2% | 98.4% | 98.8% | 98.8% |
| ライセンス | MIT | AGPL-3.0 | Apache-2.0 | BSD-3 | MIT | MIT |
| 実装言語 | Rust + PyO3 | C (MuPDF) | C (PDFium) | Pure Python | Pure Python | Pure Python |
| テキスト抽出 | 対応 | 対応 | 対応 | 対応 | 対応 | 対応 |
| 文字位置情報 | 対応 | 対応 | 対応 | 一部 | 対応 | 対応 |
| 画像抽出 | 対応 | 対応 | 対応 | 対応 | 非対応 | 非対応 |
| フォームフィールド | 読み書き | 読み書き | 読み取りのみ | 読み書き | 読み取りのみ | 非対応 |
| PDF 生成 | 対応 | 対応 | 非対応 | 限定的 | 非対応 | 非対応 |
| PDF 編集 | 対応 | 対応 | 非対応 | 対応 | 非対応 | 非対応 |
| Markdown 出力 | 対応 | 非対応 | 非対応 | 非対応 | 非対応 | 非対応 |
| HTML 出力 | 対応 | 非対応 | 非対応 | 非対応 | 非対応 | 非対応 |
| 暗号化 | 読み書き | 読み書き | 読み取りのみ | 読み書き | 非対応 | 非対応 |
| PDF/A 検証 | 対応 | 非対応 | 非対応 | 非対応 | 非対応 | 非対応 |
| レンダリング | 対応 | 対応 | 対応 | 非対応 | 非対応 | 非対応 |
| 検索 | 正規表現+空間検索 | 対応 | 対応 | 非対応 | 非対応 | 非対応 |
| Python バージョン | 3.8–3.14 | 3.8–3.12 | 3.8+ | 3.6+ | 3.8+ | 3.6+ |
| インストールサイズ | ~5 MB wheel | ~20 MB wheel | ~3 MB wheel | ~1 MB | ~1 MB | ~1 MB |
性能比較
1 PDF あたりのテキスト抽出の平均時間を、3,830 PDF からなる全コーパスで計測しました。独立して公開されている 3 種類のテストスイートを組み合わせており、PDF 仕様の各バージョン(1.0–2.0)、暗号化ファイル、破損ドキュメント、CJK エンコーディング、複雑なレイアウト、セキュリティのエッジケースを網羅しています。各スイートで検証している内容と結果の再現性についてはコーパスの詳細をご覧ください。
| ライブラリ | 平均 | 相対比 | p99 | 成功率 |
|---|---|---|---|---|
| PDF Oxide | 0.8ms | 1× | 9ms | 100% |
| PyMuPDF | 4.6ms | 5.8× | 28ms | 99.3% |
| pypdfium2 | 4.1ms | 5.1× | 42ms | 99.2% |
| pymupdf4llm | 55.5ms | 69× | 280ms | 99.1% |
| pdftext | 7.3ms | 9.1× | 82ms | 99.0% |
| pdfminer | 16.8ms | 21× | 124ms | 98.8% |
| pdfplumber | 23.2ms | 29× | 189ms | 98.8% |
| markitdown | 108.8ms | 136× | 378ms | 98.6% |
| pypdf | 12.1ms | 15.1× | 97ms | 98.4% |
PDF Oxide の速さは、PyO3 を介して Python 拡張モジュールとしてコンパイルされたネイティブ Rust コアに由来します。サブプロセスのオーバーヘッドも、C ライブラリを橋渡しする処理もなく、Rust コードが Python プロセス内で直接実行されます。
信頼性
PDF Oxide は有効な 3,823 PDF すべてを失敗なく処理し、成功率 100% を達成しています。3,830 ファイルのコーパス内で処理できなかった 7 ファイルは、意図的に壊されたテスト用フィクスチャです(PDF ヘッダー欠落、ファジングで破壊されたカタログ、無効な xref ストリーム)。
| ライブラリ | 有効 PDF 成功数 | 成功率 |
|---|---|---|
| PDF Oxide | 3,823 / 3,823 | 100% |
| PyMuPDF | 3,796 / 3,823 | 99.3% |
| pypdfium2 | 3,792 / 3,823 | 99.2% |
| pymupdf4llm | 3,787 / 3,823 | 99.1% |
| pdftext | 3,784 / 3,823 | 99.0% |
| pdfminer | 3,777 / 3,823 | 98.8% |
| pdfplumber | 3,777 / 3,823 | 98.8% |
| markitdown | 3,771 / 3,823 | 98.6% |
| pypdf | 3,762 / 3,823 | 98.4% |
テキスト品質
PDF Oxide は全コーパスで PyMuPDF および pypdfium2 と比較して 99.5% のテキスト一致率を達成します。品質評価は抽出結果を文字単位で比較して測定しました。残りの 0.5% の差は空白の正規化とリガチャ処理に関するもので、PDF Oxide の出力のほうがより整ったものになります。
ライセンス比較
| ライブラリ | ライセンス | 商用利用 | コピーレフト |
|---|---|---|---|
| PDF Oxide | MIT | 制限なし | なし |
| pypdfium2 | Apache-2.0 | 制限なし | なし |
| PyMuPDF | AGPL-3.0 | 商用ライセンス必須(有償) | あり |
| pypdf | BSD-3 | 制限なし | なし |
| pdfplumber | MIT | 制限なし | なし |
| pdfminer | MIT | 制限なし | なし |
| pdftext | GPL-3.0 | オープンソース化が必要 | あり |
PyMuPDF は MuPDF を AGPL-3.0 ライセンスで利用しています。PyMuPDF を組み込んだソフトウェアを配布する場合、そのソフトウェアも AGPL-3.0 で公開するか、Artifex から商用ライセンスを購入する必要があります。これは SaaS 製品、Web アプリ、配布される任意のバイナリに適用されます。
PDF Oxide は MIT ライセンスで制約がありません。独自製品、SaaS プラットフォーム、クローズドソースのアプリケーションでライセンス上の義務なく利用できます。
| 用途 | PDF Oxide (MIT) | PyMuPDF (AGPL) | pypdfium2 (Apache) | pypdf (BSD) | pdfplumber (MIT) | pdfminer (MIT) |
|---|---|---|---|---|---|---|
| 商用製品 | 可 | ライセンス必要 | 可 | 可 | 可 | 可 |
| クローズドソース | 可 | 不可(ライセンスなし) | 可 | 可 | 可 | 可 |
| SaaS/クラウド | 可 | ライセンス必要 | 可 | 可 | 可 | 可 |
| 社内ツール | 可 | 可 | 可 | 可 | 可 | 可 |
API 比較
テキスト抽出
PDF Oxide:
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
text = doc.extract_text(0)
print(text)
PyMuPDF:
import fitz
doc = fitz.open("report.pdf")
page = doc[0]
text = page.get_text()
print(text)
pypdf:
from pypdf import PdfReader
reader = PdfReader("report.pdf")
page = reader.pages[0]
text = page.extract_text()
print(text)
pdfplumber:
import pdfplumber
with pdfplumber.open("report.pdf") as pdf:
page = pdf.pages[0]
text = page.extract_text()
print(text)
pdfminer:
from pdfminer.high_level import extract_text
text = extract_text("report.pdf", page_numbers=[0])
print(text)
文字単位の抽出
PDF Oxide:
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
chars = doc.extract_chars(0)
for ch in chars:
print(f"'{ch.char}' at ({ch.bbox[0]:.1f}, {ch.bbox[1]:.1f}) "
f"size={ch.font_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}")
pdfplumber:
import pdfplumber
with pdfplumber.open("report.pdf") as pdf:
page = pdf.pages[0]
for char in page.chars:
print(f"'{char['text']}' at ({char['x0']:.1f}, {char['top']:.1f}) "
f"size={char['size']:.1f}")
pdfminer:
from pdfminer.high_level import extract_pages
from pdfminer.layout import LTChar
for page_layout in extract_pages("report.pdf"):
for element in page_layout:
if hasattr(element, '__iter__'):
for text_line in element:
if hasattr(text_line, '__iter__'):
for char in text_line:
if isinstance(char, LTChar):
print(f"'{char.get_text()}' at ({char.x0:.1f}, {char.y0:.1f}) "
f"size={char.size:.1f}")
画像抽出
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"])
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"])
pypdf:
from pypdf import PdfReader
reader = PdfReader("report.pdf")
page = reader.pages[0]
for i, image in enumerate(page.images):
with open(f"image_{i}.{image.name.split('.')[-1]}", "wb") as f:
f.write(image.data)
PDF の生成
PDF Oxide:
from pdf_oxide import Pdf
pdf = Pdf.from_markdown("# Hello World\n\nThis is a PDF.")
pdf.save("output.pdf")
# HTML にも対応
pdf = Pdf.from_html("<h1>Hello</h1><p>World</p>")
pdf.save("output.pdf")
PyMuPDF:
import fitz
doc = fitz.open()
page = doc.new_page()
text_point = fitz.Point(72, 72)
page.insert_text(text_point, "Hello World", fontsize=24)
doc.save("output.pdf")
pypdf:
# pypdf は PDF の結合・編集はできますが、テキストを含む PDF をゼロから生成することはできません。
# 生成は reportlab か fpdf2 で行い、結合に pypdf を使用してください。
暗号化 PDF
PDF Oxide:
from pdf_oxide import PdfDocument
doc = PdfDocument("encrypted.pdf", password="password")
text = doc.extract_text(0)
PyMuPDF:
import fitz
doc = fitz.open("encrypted.pdf")
doc.authenticate("password")
page = doc[0]
text = page.get_text()
pypdf:
from pypdf import PdfReader
reader = PdfReader("encrypted.pdf")
reader.decrypt("password")
text = reader.pages[0].extract_text()
Markdown・HTML 出力
PDF Oxide(独自機能):
from pdf_oxide import PdfDocument
doc = PdfDocument("paper.pdf")
# 見出し検出付きで Markdown に変換
md = doc.to_markdown(0, detect_headings=True)
print(md)
# HTML に変換
html = doc.to_html(0)
print(html)
組み込みで Markdown または HTML 変換を備える Python PDF ライブラリは他にありません。
各ライブラリのプロフィール
PDF Oxide
強み:
- Rust コアにより、ベンチマークで最速のテキスト抽出(PyMuPDF より 5.8× 高速)
- 3,830 PDF コーパスで 100% 成功率。テスト対象ライブラリ中で最高の信頼性
- 抽出・生成・編集を単一ライブラリの統一 API で提供
- 見出し検出付きの Markdown・HTML エクスポートを内蔵
- MIT ライセンスでコピーレフト制約なし
- 規格準拠検証(PDF/A、PDF/UA、PDF/X)をネイティブで搭載
- 主要プラットフォームと Python 3.8–3.14 向けのビルド済み wheel を提供
- システム依存なし。wheel にすべて含まれます
制約:
- 歴史が浅く、コミュニティがまだ小さい
- 表抽出は pdfplumber のアルゴリズムほど高度ではない
- レンダリングエンジンの成熟度は MuPDF に及ばない
PyMuPDF (fitz)
強み:
- 実戦投入の実績が豊富(MuPDF ベースで 2005 年から開発が続く)
- 複雑な PDF に対して優れたレンダリング品質
- OCR 連携(Tesseract)を内蔵
- 機能が豊富:SVG 出力、ページ操作、表検出
制約:
- AGPL-3.0 ライセンスにより、アプリケーションのソース公開か商用ライセンス購入が必要
- MuPDF を同梱するため wheel サイズが大きい(~20 MB)
- Markdown エクスポートは非搭載
- 規格準拠検証は非搭載
pypdfium2
強み:
- 高速(Google の PDFium エンジンがベース)
- Apache-2.0 ライセンスで商用利用に寛容
- 良好なレンダリング品質
制約:
- PDF Oxide や PyMuPDF に比べテキスト抽出 API が限定的
- PDF の生成・編集は不可
- フォームフィールドは読み取り専用のみ対応
pypdf
強み:
- Pure Python でどこにでもインストール可能、コンパイル依存なし
- 軽量でメンテナンスも活発
- 結合、分割、回転、暗号化などの PDF 操作に適する
- コミュニティが大きく、ドキュメントが充実
制約:
- テキスト抽出は PDF Oxide の 15× 遅い
- 複雑なレイアウトではテキスト抽出の品質が低下する
- レンダリング、Markdown/HTML 出力、表抽出はいずれも非対応
pdfplumber
強み:
- Python PDF ライブラリで最高クラスの表抽出
- 文字単位の優れた位置情報
- 可視化デバッグツール(注釈付きのページ画像)
- MIT ライセンス
制約:
- Pure Python のため PDF Oxide の 29× 遅い
- 読み取り専用。PDF の生成や編集は不可
- 暗号化・レンダリングとも非対応
pdfminer
強み:
- 文字・レイアウトの詳細な解析が可能
- CJK テキストのサポートが良好
- pdfplumber など他ツールの基盤
- MIT ライセンス
制約:
- PDF Oxide の 21× 遅い(Pure Python、非最適化)
- 読み取り専用。生成や編集は不可
- 定番処理に対して API が冗長
- メンテナンスは控えめ
どのライブラリを使うべきか
| 用途 | 推奨ライブラリ |
|---|---|
| 高速なテキスト抽出 | PDF Oxide |
| 商用・独自製品 | PDF Oxide、pypdfium2、pypdf、pdfplumber、pdfminer |
| PyMuPDF の代替(MIT ライセンス) | PDF Oxide |
| Markdown/HTML から PDF 生成 | PDF Oxide |
| 規格準拠検証(PDF/A、PDF/X) | PDF Oxide |
| 請求書などからの表抽出 | pdfplumber |
| 抽出結果の可視化デバッグ | pdfplumber |
| 既存の MuPDF 資産を活かす | PyMuPDF(AGPL と両立する場合) |
| 依存関係を最小限に | pypdf(Pure Python) |
| 詳細なレイアウト解析 | pdfminer |
| スキャン文書の OCR | PyMuPDF |
インストール
# PDF Oxide
pip install pdf_oxide
# PyMuPDF
pip install pymupdf
# pypdfium2
pip install pypdfium2
# pypdf
pip install pypdf
# pdfplumber
pip install pdfplumber
# pdfminer
pip install pdfminer.six
PDF Oxide は Linux(x86_64、aarch64)、macOS(x86_64、arm64)、Windows(x86_64)向けにビルド済み wheel を提供します。コンパイラやシステムライブラリは不要です。
関連ページ
- 性能ベンチマーク – 全コーパスでの詳細結果
- Python で始める – インストールと初回抽出
- Python API リファレンス – Python API 全体
- vs Rust PDF ライブラリ – Rust エコシステムでの比較