PythonでPDFテキスト抽出する方法 3ライブラリ比較
PDF テキスト抽出 Python は簡単そうに見えて、実際にやってみると例外処理やレイアウト崩れ、画像ベースの厄介な文書にすぐぶつかります。このガイドでは、そうした迷いやつまずきを最短で整理します。まずは代表的な Python ライブラリを比較し、用途に合うツールをすぐ選べるようにします。

続いて、PyPDF2・pdfplumber・PyMuPDF(Fitz)の3つについて、基本的な文字抽出から複雑な表の扱いまでコード例付きで見ていきます。さらに、最も手ごわいスキャンPDF OCR Python の対応方法も解説します。複雑なローカル環境を組まなくても進めやすい、実務向けのやり方に絞って紹介します。読み終えるころには、PDF 解析 Python の実装方針と、自動化に使えるコードの両方が手元に残るはずです。
結論から比較:PythonのPDFテキスト抽出ライブラリ
コードに入る前に、まずは主要ライブラリの違いをざっくり整理しておきましょう。選ぶ基準は、速度を重視するのか、手軽さを優先するのか、それともレイアウト解析の精度が必要なのかで変わります。
| ライブラリ | 向いている用途 | レイアウト・表の扱い | 処理性能 | 使いやすさ(1〜5) |
|---|---|---|---|---|
| PyPDF2 | シンプルなテキスト中心の文書、基本的な PDF 操作(結合・分割) | 弱い(文字列の流れを抽出するだけで、位置情報は持たない) | 普通 | 5 |
| pdfplumber | 表データの抽出、構造化されたレイアウトの文書 | 非常に強い(文字・線・矩形の座標を取得できる) | やや遅い | 4 |
| PyMuPDF (Fitz) | 高速なバッチ処理、画像や注釈を含む PDF の処理 | 良好(基本的な位置情報付きでテキスト抽出できる) | 非常に高い(最速) | 4 |
要点: まずは最も手軽な PyPDF2 から始めるのがおすすめです。表が出てきたら pdfplumber に切り替えましょう。処理速度を最優先するなら PyMuPDF が有力です。
事前準備:Python実行環境を整える
依存関係を整理し、ライブラリ同士の競合を避けるために、作業は必ず仮想環境の中で行いましょう。本格的に Python を使うなら、これはほぼ必須の基本です。
ターミナルでは次の手順で準備できます。
- 仮想環境を作成する:
# macOS/Linux の場合
python3 -m venv pdf_env
# Windows の場合
python -m venv pdf_env
```
2. **仮想環境を有効化する:**
```plaintext
# macOS/Linux の場合
source pdf_env/bin/activate
# Windows の場合
.\pdf_env\Scripts\activate
```
有効化できると、ターミナルのプロンプトに `(pdf_env)` と表示されます。
3. **ライブラリをインストールする:** 比較対象の3つをまとめて入れておくと、すぐ試せます。
```plaintext
pip install pypdf2 pdfplumber pymupdf
```
これで、以下のコード例をそのまま試せる状態になりました。
---
## 方法1:PyPDF2でPDFから文字を抽出する
PyPDF2 は、基本的な PDF 操作で定番のライブラリです。扱いやすく、長く使われてきた実績があり、テキストを選択できる「ネイティブ PDF」の文字抽出に向いています。レポート、記事、テキストベースの書き出しファイルのようなシンプルな文書なら、少ないコードで十分対応できます。
ただし弱点もあります。PyPDF2 は PDF 内部のテキストストリームをそのまま読み取るため、見た目の読み順どおりに取れないことがあります。特に複数カラムのレイアウトでは崩れやすいです。また、表という構造を理解しないので、セル内の文字がまとめて連結されるだけになりがちです。
まずは、PDF から全文を抽出するシンプルなスクリプトを見てみましょう。
```python
# 必要なもの: pip install pypdf2
import PyPDF2
def extract_text_with_pypdf2(pdf_path):
"""
PyPDF2 ライブラリを使って PDF ファイルからテキストを抽出します。
Args:
pdf_path (str): PDF ファイルのパス。
Returns:
str: 抽出したテキスト、またはエラーメッセージ。
"""
try:
with open(pdf_path, 'rb') as file:
reader = PyPDF2.PdfReader(file)
num_pages = len(reader.pages)
print(f"総ページ数: {num_pages}")
full_text = ""
for page_num in range(num_pages):
page = reader.pages[page_num]
full_text += page.extract_text() + "\n"
return full_text
except FileNotFoundError:
return f"エラー: {pdf_path} にファイルが見つかりませんでした。"
except Exception as e:
return f"予期しないエラーが発生しました: {e}"
# --- 使用例 ---
pdf_file = 'path/to/your/document.pdf'
extracted_text = extract_text_with_pypdf2(pdf_file)
if "Error" not in extracted_text:
print("--- 抽出したテキスト ---")
print(extracted_text)
else:
print(extracted_text)
このスクリプトは、単一カラムのシンプルな文書なら十分きれいに動きます。では、整った表が並ぶ財務諸表のような PDF を渡したらどうなるでしょうか。返ってくるのは、構造を失った文字と数字のかたまりです。そこで次に活躍するのが、表抽出に強いライブラリです。
方法2:pdfplumberで表とレイアウトを抽出する
構造化データを取り出したいなら、pdfplumber が最有力です。pdfminer.six を土台にしており、PDFページ上の位置情報や形状を細かく扱えるよう設計されています。文字・線・長方形を認識でき、表を検出して抽出する組み込み機能も非常に優秀です。
これはデータ分析や業務自動化では大きな差になります。たとえば企業のPDFレポートから四半期業績を抜き出す場面を考えてみてください。PyPDF2 だと文字列を無理やり解析する作業になりがちですが、pdfplumber ならきれいな二重リストとして取得でき、そのまま Pandas の DataFrame に渡せます。
構造化データの抽出で pdfplumber が PyPDF2 より強い最大の理由は、生のテキスト列ではなく、見た目のレイアウトを解釈できる点です。 テキスト要素が行・列でそろっていて、線で区切られていることまで踏まえて処理できます。
PDFページから表を抽出する基本例は次のとおりです。
# 必要環境: pip install pdfplumber
import pdfplumber
import pandas as pd
def extract_tables_with_pdfplumber(pdf_path, page_number=0):
"""
pdfplumber を使って、PDF の特定ページからすべての表を抽出します。
Args:
pdf_path (str): PDF ファイルのパス。
page_number (int): 表を抽出するページ番号(0始まり)。
Returns:
list of pandas.DataFrame: 各要素がページ内で見つかった表を表す
DataFrame のリスト。
"""
tables = []
try:
with pdfplumber.open(pdf_path) as pdf:
if page_number >= len(pdf.pages):
print(f"エラー: ページ {page_number} は範囲外です。この PDF は {len(pdf.pages)} ページあります。")
return tables
page = pdf.pages[page_number]
# ここで重要なのが .extract_tables() メソッド
extracted_tables = page.extract_tables()
for table_data in extracted_tables:
# 二重リストを pandas の DataFrame に変換
df = pd.DataFrame(table_data[1:], columns=table_data[0])
tables.append(df)
return tables
except FileNotFoundError:
print(f"エラー: {pdf_path} にあるファイルが見つかりませんでした。")
return tables
except Exception as e:
print(f"予期しないエラーが発生しました: {e}")
return tables
# --- 使用例 ---
# この例では pandas も必要です: pip install pandas
pdf_file_with_table = 'path/to/your/report.pdf'
all_tables = extract_tables_with_pdfplumber(pdf_file_with_table, page_number=0)
if all_tables:
print(f"ページ 0 で {len(all_tables)} 個の表が見つかりました。")
for i, table_df in enumerate(all_tables):
print(f"\n--- 表 {i+1} ---")
print(table_df)
else:
print("指定したページでは表が見つかりませんでした。")
ただし、この精度には速度とのトレードオフがあります。pdfplumber はページ解析の処理量が多いため、単純にテキストを吐き出すだけのライブラリより本質的に遅くなります。
方法3:PyMuPDF(Fitz)で高速にテキスト抽出する
数百〜数千件のPDFをすばやく処理したいなら、決め手になるのは性能です。そこで強いのが、fitz として読み込む PyMuPDF です。軽量な C ライブラリ MuPDF の Python バインディングなので、非常に高速に動作します。
以前、数千件規模の複数ページにわたる法務文書を処理する案件がありました。最初に作った pdfplumber のスクリプトでは完了まで数時間かかる見込みでしたが、PyMuPDF に切り替えたところ実行時間は30分未満まで短縮できました。速度差はそれほど大きいです。
PyMuPDF の強みは速さだけではありません。ページを画像としてレンダリングしたり(OCRワークフローでは重要)、埋め込み画像を抽出したり、注釈を扱ったりできます。表抽出は pdfplumber ほどそのまま使いやすくはないものの、生テキストの抽出速度では群を抜いています。
高速な PDF テキスト抽出を行う PyMuPDF の基本例はこちらです。
# 必要環境: pip install PyMuPDF
import fitz # PyMuPDF ライブラリ
def extract_text_with_pymupdf(pdf_path):
"""
高速な PyMuPDF(Fitz)ライブラリを使って PDF ファイルからテキストを抽出します。
Args:
pdf_path (str): PDF ファイルのパス。
Returns:
str: 抽出したテキスト内容、またはエラーメッセージ。
"""
try:
doc = fitz.open(pdf_path)
full_text = ""
for page in doc:
# 中核となるのが .get_text() 関数
full_text += page.get_text() + "\n"
doc.close()
return full_text
except FileNotFoundError:
return f"エラー: {pdf_path} にあるファイルが見つかりませんでした。"
except Exception as e:
# PyMuPDF は fitz.fitz.FitzError などの固有エラーを送出することがあります
return f"PyMuPDF でエラーが発生しました: {e}"
# --- 使用例 ---
pdf_file = 'path/to/your/document.pdf'
fast_extracted_text = extract_text_with_pymupdf(pdf_file)
if "Error" not in fast_extracted_text:
print("--- 抽出テキスト(高速版) ---")
print(fast_extracted_text)
else:
print(fast_extracted_text)
テキストベースのPDFを大量処理するなら、純粋なスループットでは PyMuPDF が最有力です。
特殊ケース:スキャンPDFをOCRで文字起こしする
ここで疑問になるのが、「どの方法でもうまくいかないPDFはどうするのか?」という点です。上のコードを、契約書の写真や電子化された書籍ページのようなスキャン文書に対して実行すると、返ってくるのは空文字列です。
これはテキストレイヤーが存在しないためです。PDFの中にあるのは文字ではなく画像です。解決するには、Optical Character Recognition(OCR)で画像を“読み取り”、機械可読なテキストへ変換する必要があります。
Python での定番は、Google の Tesseract OCR エンジン用ラッパーである pytesseract です。高機能ですが、大きな難点があります。Tesseract 本体をシステムに別途インストールし(たとえば Mac なら brew、Windows ならインストーラー)、さらに Python 側から実行ファイルを見つけられるようにしなければなりません。このセットアップは壊れやすく、特にサーバーへデプロイするときや、同僚とコードを共有するときに面倒になりがちです。
代替案:ノーコードツールで複雑なPDFを先に処理する
納期が迫っているときや、OCR 依存関係の管理に手間をかけたくないときは、まず専用ツール側でテキスト抽出を済ませるのが実用的です。こうしておくと、面倒な OCR の問題を Python の本体ロジックから切り離せます。
LynoteのAI PDFテキスト抽出ツール のようなAIツールは、強力な前処理手段として使えます。扱いづらいスキャンPDFをアップロードすれば、裏側で OCR を処理し、スクリプトにそのまま渡せるきれいなテキストを返してくれます。単発の作業や、問題のあるファイルが少数だけあるケースでは特に便利です。
ワークフローはとてもシンプルです。
- PDFファイルをアップロードします。 Lynote のワークスペースを開きます。『Upload File』タブで、PDF をドラッグ&ドロップするか、PC からファイルを選択できます。テキストベースのPDFにも、スキャン画像ベースのPDFにも対応しています。
- PDFからテキストを抽出します。 ファイルのアップロード後、「Create Note」ボタンをクリックします。Lynote の AI エンジンが文書を処理し、画像ベースのファイルを検出した場合は自動で OCR を適用して、検索可能なきれいなテキスト版を生成します。
- 抽出したテキストをコピーします。 テキストがエディタに表示されたら、内容を確認し、必要なら軽微な修正を加えたうえで、コピーボタンから全文を取得できます。これでクリップボードに入り、Python スクリプトへ文字列変数として貼り付ける準備が整います。


この方法なら、ローカルの OCR 環境構築やエラーハンドリングに時間を取られず、コードではデータ分析そのものに集中できます。
よくある落とし穴と実践テクニック
PDFからテキストを抽出する処理は、毎回きれいに成功するとは限りません。実務でよくぶつかる代表的な問題をまとめると、次のとおりです。
- 文字エンコーディング:
UnicodeDecodeErrorが出ることがあります。これは古いPDFや、特殊なソフトで作成されたPDFで起こりがちです。最近のライブラリはUTF-8を問題なく扱えることが多いですが、ライブラリ側で指定できる場合は、エンコーディングを明示すると改善することがあります。 - パスワード保護されたPDF: PDFを開くのにパスワードが必要な場合、そのままではどのライブラリでも失敗します。読み込み時にパスワードを渡してください。たとえば
PyPDF2.PdfReader(file, password='your_password')のように指定します。 - 書式情報の欠落: PDF テキスト抽出では、太字・斜体・フォントサイズ・色などの書式情報はほぼ失われます。取得できるのは見た目そのものではなく、生のテキストデータです。
- 段組みでテキストが崩れる: PyPDF2でも触れたように、複数カラムのレイアウト(論文など)では、別の列の行が混ざって抽出されることがあります。
pdfplumberはページ上の位置関係を見て処理できるため、この種のレイアウト分析ではかなり有利です。
実務のポイント: スクリプトは必ず、実際に扱うPDFに近いサンプルで検証しましょう。あるPDFで完璧に動く方法でも、作成元が違う別のPDFではまったく通用しないことがあります。
よくある質問
PDFの表を抽出したら、なぜ1本の長い文字列になってしまうのですか?
これは、ページレイアウトを解析しない PyPDF2 のようなライブラリでよく起きる典型的な問題です。ファイル内部に保存されている順番どおりに生テキストを読むため、画面上で見えている行・列の構造と一致しないことが少なくありません。PDFの表抽出を正しく行いたいなら、**pdfplumber** のようなレイアウト対応ライブラリを使う必要があります。 pdfplumber は表形式データの認識を前提に設計されています。
PythonでPDFページの特定範囲だけ文字抽出できますか?
はい、可能です。ただし、座標情報を扱えるライブラリが必要です。pdfplumber と PyMuPDF はこの用途に向いています。pdfplumber なら .crop((x0, top, x1, bottom)) で対象範囲のボックスを切り出し、その範囲内だけに対して .extract_text() や .extract_tables() を実行できます。
スキャンPDFで文字抽出結果が空になるのはなぜですか?
そのPDFには文字データではなく、文字が写った画像が入っているためです。通常のライブラリでは画像の中身までは読めません。こうしたスキャンPDF OCRには、Optical Character Recognition(OCR)の処理が必要です。pytesseract でローカルにOCR環境を構築する方法もありますし、Lynote のような前処理ツールで画像ベースのPDFを先にきれいなテキストへ変換してから、Pythonで扱う方法もあります。
複数言語が混在するPDFはどう扱えばいいですか?
PyMuPDF や pdfplumber のような最近のライブラリは、Unicode(多くの言語を扱える文字体系)への対応が比較的しっかりしています。主な難所は OCR の段階です。たとえば Tesseract では、使いたい言語パックを事前にダウンロードし、明示的に指定する必要があります(例: 英語とフランス語なら -l eng+fra)。
まとめ:用途別に選ぶ Python PDF テキスト抽出ツール
PythonでPDFからテキストを抽出する方法に、万能な「最適解」はありません。どのライブラリを選ぶべきかは、PDFの種類とプロジェクトの目的で決まります。
迷ったら、まずは次のシンプルな判断基準で選ぶのがおすすめです。
- シンプルなテキスト主体のPDF から文字だけ取れればよいなら、実装しやすく導入も速い PyPDF2 が最初の候補です。
- 表や構造化レイアウトを含むPDF をデータとして解析したいなら(たとえばデータベース投入や Pandas DataFrame 化)、pdfplumber が最も使いやすい選択です。
- 大量のPDFを処理する うえで速度を最優先するなら、PyMuPDF (Fitz) が最も高性能です。
- スキャンPDFや画像ベースのPDF を扱う場合は、OCR が必須です。ローカル環境の構築に手間をかけず、手早く安定して処理したいなら、外部ツールで先にPDFを前処理してテキスト化し、その後で Python に取り込む流れが現実的です。
まずは要件を満たす最もシンプルなツールから始めて、PDFの複雑さが増してきた段階で、より高機能なライブラリへ切り替えるのが失敗しにくい進め方です。


