Skip to content

Python PDF ライブラリ — PDF Oxide を 10 行で

PDF Oxide は Python 向けの最速 PDF ライブラリです。テキスト抽出はページ平均 0.8 ms、PyMuPDF の約 5 倍の速度で、3,830 件の PDF でパス率 100%。抽出・作成・編集をワンストップで扱えます。MIT ライセンス、Rust コア、システム依存はありません。

インストール

pip install pdf_oxide

要件: Python 3.8 以降。Linux・macOS・Windows の x86_64 / ARM64 向けにビルド済みの wheel を用意しています。コンパイラやシステムパッケージは不要です。

PDF を開く

PdfDocument で任意の PDF ファイルを開いて中身を確認できます。

from pdf_oxide import PdfDocument

doc = PdfDocument("research-paper.pdf")
print(f"Pages: {doc.page_count()}")
print(f"PDF version: {doc.version()}")

Page API

v0.3.34 から PdfDocument はイテラブルかつインデックス可能になり、遅延プロパティを持つ PdfPage オブジェクトを返します。

from pdf_oxide import PdfDocument

with PdfDocument("paper.pdf") as doc:
    for page in doc:            # len(doc)、doc[i]、doc[-1] すべて有効
        text = page.text        # 遅延評価 — アクセス時に計算
        md = page.markdown(detect_headings=True)
        for table in page.tables:
            for row in table["rows"]:
                print([cell["text"] for cell in row["cells"]])

ページのプロパティ(すべて遅延評価): textcharswordslinesspanstablesimagespathsannotationswidthheightbbox。メソッド: markdown()plain_text()html()render()search()region(x, y, w, h)

エディタ側のページクラスは v0.3.34 で EditorPage に改名され、PdfPage との衝突を回避しました。

テキスト抽出

単一ページ

0 始まりのインデックスでページのプレーンテキストを抽出します。

from pdf_oxide import PdfDocument

doc = PdfDocument("report.pdf")
text = doc.extract_text(0)
print(text)

全ページ

from pdf_oxide import PdfDocument

doc = PdfDocument("book.pdf")
for i in range(doc.page_count()):
    text = doc.extract_text(i)
    print(f"--- Page {i + 1} ---")
    print(text)

文字単位の抽出

extract_chars() はページ上の各文字について、正確な位置とフォントメタデータを含む TextChar のリストを返します。

from pdf_oxide import PdfDocument

doc = PdfDocument("paper.pdf")
chars = doc.extract_chars(0)

for ch in chars[:10]:
    print(f"'{ch.char}' at ({ch.x:.1f}, {ch.y:.1f}) "
          f"size={ch.font_size:.1f} font={ch.font_name} "
          f"bbox={ch.bbox}")

TextChar のフィールドは以下のとおりです。

フィールド 説明
char str Unicode 文字
x float 水平位置(ポイント)
y float 垂直位置(ポイント)
font_size float フォントサイズ(ポイント)
font_name str PostScript フォント名
bbox tuple[float, 4] バウンディングボックス (x0, y0, x1, y1)

テキストスパン

extract_spans() は同じフォント・サイズを共有する連続した文字をスパンにまとめ、フォントメタデータ付きの構造化テキストを返します。

from pdf_oxide import PdfDocument

doc = PdfDocument("paper.pdf")
spans = doc.extract_spans(0)

for span in spans:
    print(f"'{span.text}' font={span.font_name} size={span.font_size}")

Markdown 変換

PDF ページを Markdown に変換します。見出し検出は任意です。

from pdf_oxide import PdfDocument

doc = PdfDocument("paper.pdf")
md = doc.to_markdown(0, detect_headings=True)
print(md)

HTML 変換

PDF ページを HTML に変換します。

from pdf_oxide import PdfDocument

doc = PdfDocument("paper.pdf")
html = doc.to_html(0)
print(html)

画像抽出

extract_images() はページに埋め込まれたすべての画像を ImageInfo のリストで返します。コンテンツストリーム内の画像やネストされた Form XObject の画像も含まれます。

from pdf_oxide import PdfDocument

doc = PdfDocument("brochure.pdf")
images = doc.extract_image_bytes(0)

for i, img in enumerate(images):
    print(f"Image {i}: {img['width']}x{img['height']} "
          f"({len(img['data'])} bytes)")
    with open(f"image_{i}.{img['format']}", "wb") as f:
        f.write(img["data"])

extract_image_bytes() が返す各 dict のキーは次のとおりです。

キー 説明
width int 画像の幅(ピクセル)
height int 画像の高さ(ピクセル)
data bytes 画像の生データ
format str 画像フォーマット(例: png, jpeg

バイト列から開く

メモリ上のバイト列から PDF を開けます。S3・HTTP・データベースから取得したバイナリに便利です。

from pdf_oxide import PdfDocument

doc = PdfDocument.from_bytes(pdf_bytes)
text = doc.extract_text(0)

# パスワードも指定可能:
doc = PdfDocument.from_bytes(pdf_bytes, password="secret")

ビルダー API の場合:

from pdf_oxide import Pdf

pdf = Pdf.from_bytes(existing_pdf_bytes)
pdf.save("modified.pdf")

パスワード付き PDF

暗号化された文書を開くにはコンストラクタに password= を渡します。

from pdf_oxide import PdfDocument

doc = PdfDocument("confidential.pdf", password="secret")
text = doc.extract_text(0)
print(text)

開いたあとに doc.authenticate(password) を呼び出す方法もあります。

PDF の作成

Pdf クラスは、さまざまな入力形式から PDF を生成するファクトリメソッドを提供します。

Markdown から

from pdf_oxide import Pdf

pdf = Pdf.from_markdown("# Hello World\n\nThis is a PDF.")
pdf.save("output.pdf")

HTML から

from pdf_oxide import Pdf

pdf = Pdf.from_html("<h1>Invoice</h1><p>Amount due: $42.00</p>")
pdf.save("invoice.pdf")

プレーンテキストから

from pdf_oxide import Pdf

pdf = Pdf.from_text("Plain text document.\n\nSecond paragraph.")
pdf.save("notes.pdf")

画像から

from pdf_oxide import Pdf

pdf = Pdf.from_image("scan.jpg")
pdf.save("scan.pdf")

検索

文書全体または単一ページから文字列を検索します。

from pdf_oxide import PdfDocument

doc = PdfDocument("manual.pdf")

# 全ページを検索
results = doc.search("configuration")
for r in results:
    print(f"Page {r.page}: '{r.text}' at ({r.x:.0f}, {r.y:.0f})")

# 単一ページを検索
page_results = doc.search_page(0, "configuration")

エラー処理

PDF Oxide は PDF 固有のエラーを PdfError として送出し、I/O の問題には標準の Python 例外を利用します。

from pdf_oxide import PdfDocument, PdfError

try:
    doc = PdfDocument("document.pdf")
    text = doc.extract_text(0)
except PdfError as e:
    print(f"PDF error: {e}")
except FileNotFoundError:
    print("File not found")

次のステップ