ClaudeCodeでPDFからテキストを抽出する方法【完全実践ガイド】
「請求書PDFが100枚あるが、明細をExcelに転記するのに丸2日かかる」「議事録PDFから必要な情報を検索したいが、コピペが面倒」「スキャナで取り込んだ古い書類をテキスト化したい」——PDFを扱う業務は、見た目以上に手間がかかります。本記事では、ClaudeCodeを使ってPDFファイルからテキスト・表・画像を抽出する方法を、ライブラリ選びからOCR連携まで、初心者の方でも迷わず実行できるよう体系的に解説します。実際のプロンプト例とコードサンプルを豊富に掲載し、コピー&ペーストですぐ動かせる構成にしました。
結論:PDF抽出は「種類の見極め」と「ツール選び」が9割
結論を先にお伝えします。PDFからの情報抽出は、「PDFの種類を正しく見極め」「適切なライブラリを選ぶ」だけで、ほぼ自動化できます。理由は明確で、PDFには大きく分けて2種類しかないからです。1つ目はテキストPDF(PCで作成、文字を直接抽出可能)、2つ目は画像PDF(スキャンや写真、OCRが必要)。この見極めができれば、テキストPDFには pypdf や pdfplumber、画像PDFには pytesseract(Tesseract OCRのラッパー)を使い分けるだけで、ほとんどの業務に対応できます。ClaudeCodeはこの判別と切り替えを自動で行ってくれるため、利用者は「このPDFから明細を抜いて」「議事録から発言者ごとにテキストを整理して」と日本語で頼むだけで済みます。本記事では、テキスト抽出・表抽出・画像抽出・OCRの4つの代表的なシナリオをすべて実演し、最終的には「100枚のPDFを一括処理してExcelに集約する」ところまで到達します。PDFに振り回されてきた時間を、本記事を読み終える頃には“ボタン1つの作業”に変換できているはずです。
h2-1. PDF抽出に必要なライブラリの全体像
PDF処理でよく使われるPythonライブラリは、用途別に役割が異なります。最初に全体像を整理しておきましょう。
| ライブラリ | 主な用途 | 強み |
|---|---|---|
| pypdf | テキスト抽出、ページ操作 | 軽量・依存少 |
| pdfplumber | テキスト+表の抽出 | 表の構造化が得意 |
| PyMuPDF (fitz) | 高速処理、画像抽出 | 速度と機能のバランス |
| pdf2image | PDFを画像に変換 | OCR前処理に必須 |
| pytesseract | OCR(画像→テキスト) | 日本語対応 |
初めての方は、まず pdfplumber から覚えるのがおすすめです。テキストも表もこれ1本で大半をカバーできます。
プロンプト例1:ライブラリを一括インストール
PDF処理に必要な主要ライブラリ(pypdf、pdfplumber、PyMuPDF、pdf2image、pytesseract)をまとめてインストールするコマンドを教えてください。pipで実行できる形でお願いします。
ClaudeCodeの回答例:
pip install pypdf pdfplumber PyMuPDF pdf2image pytesseract pillow
加えて、OCRを使う場合は別途 Tesseract 本体のインストールが必要です(後述)。
h2-2. テキストPDFか画像PDFかを判別する
PDF処理の第一歩は「このPDFがテキストPDFなのか、画像PDFなのか」を見極めることです。テキストPDFなら数秒で全文抽出できますが、画像PDFはOCRが必要で処理時間も大きく変わります。
プロンプト例2:PDFの種別を判定
sample.pdf がテキストPDFか画像PDFかを判定するスクリプトを書いてください。各ページのテキスト抽出量と画像数を比較する方法でお願いします。
ClaudeCodeのコード例:
import pdfplumber
def detect_pdf_type(path: str) -> str:
with pdfplumber.open(path) as pdf:
total_text = 0
total_pages = len(pdf.pages)
for page in pdf.pages:
text = page.extract_text() or ""
total_text += len(text.strip())
avg = total_text / total_pages if total_pages else 0
print(f"ページ数: {total_pages}, 平均文字数: {avg:.0f}")
return "テキストPDF" if avg > 100 else "画像PDF(OCR必要)"
print(detect_pdf_type("sample.pdf"))
このように、1ページあたりの平均文字数が100文字以上ならテキストPDF、そうでなければ画像PDFと判定する簡易ロジックです。
h2-3. テキスト抽出の基本(pypdfとpdfplumber)
ここからは実際の抽出です。まずはシンプルなテキスト抽出から。
プロンプト例3:PDFの全テキストを抽出
report.pdf から全ページのテキストを抽出し、output.txt に保存するスクリプトを作ってください。ページごとに区切り線を入れてください。
pypdf 版:
from pypdf import PdfReader
reader = PdfReader("report.pdf")
with open("output.txt", "w", encoding="utf-8") as f:
for i, page in enumerate(reader.pages, 1):
f.write(f"\n===== Page {i} =====\n")
f.write(page.extract_text() or "")
print(f"{len(reader.pages)}ページを出力しました")
pdfplumber 版(レイアウトを保持しやすい):
import pdfplumber
with pdfplumber.open("report.pdf") as pdf, open("output.txt", "w", encoding="utf-8") as f:
for i, page in enumerate(pdf.pages, 1):
f.write(f"\n===== Page {i} =====\n")
f.write(page.extract_text() or "")
実務では「議事録の段組がガタガタになる」ことがあります。その場合は pdfplumber の extract_text(layout=True) を使うとレイアウトが保たれやすくなります。
特定ページだけ抽出
report.pdf の3ページ目から5ページ目までのテキストだけ抽出してください。
from pypdf import PdfReader
reader = PdfReader("report.pdf")
for i in range(2, 5): # 0始まり
print(reader.pages[i].extract_text())
h2-4. 表(テーブル)の抽出
請求書や報告書には「表」が含まれていることが非常に多く、ここを正確に抜けるかが業務効率を大きく左右します。
プロンプト例4:請求書PDFから明細表を抽出
invoice.pdf に商品名・数量・単価・金額の明細表があります。pdfplumberを使って表を抽出し、Pandas DataFrameに変換してください。最後にCSVとして保存してください。
import pdfplumber
import pandas as pd
all_rows = []
with pdfplumber.open("invoice.pdf") as pdf:
for page in pdf.pages:
tables = page.extract_tables()
for table in tables:
all_rows.extend(table)
# 1行目をヘッダーとして利用
df = pd.DataFrame(all_rows[1:], columns=all_rows[0])
df.to_csv("invoice_items.csv", index=False, encoding="utf-8-sig")
print(df.head())
encoding="utf-8-sig" を指定しているのは、Excelで開いたときに文字化けしないためのテクニックです。覚えておくと便利です。
表抽出の精度が出ないとき
pdfplumberで抽出した表の罫線がうまく認識されません。table_settingsを調整して精度を上げてください。
settings = {
"vertical_strategy": "text",
"horizontal_strategy": "text",
"snap_tolerance": 3,
}
tables = page.extract_tables(table_settings=settings)
vertical_strategy を "text" にすると、罫線がない表でも文字位置で列を推定してくれます。
h2-5. 画像抽出と画像PDFの取り扱い
PDF内に挿入された写真やロゴを取り出したい場合は、PyMuPDF が便利です。
プロンプト例5:PDF内の画像を全部取り出す
catalog.pdf に含まれる画像をすべて抽出し、images フォルダにページ番号と通し番号付きで保存してください。
import fitz # PyMuPDF
from pathlib import Path
Path("images").mkdir(exist_ok=True)
doc = fitz.open("catalog.pdf")
for page_no, page in enumerate(doc, 1):
for img_idx, img in enumerate(page.get_images(full=True), 1):
xref = img[0]
pix = fitz.Pixmap(doc, xref)
ext = "png" if pix.alpha == 0 else "png"
pix.save(f"images/page{page_no}_img{img_idx}.{ext}")
pix = None
print("画像の抽出が完了しました")
商品カタログPDFから画像を一括取得して、ECサイトに転載するような業務に最適です。
h2-6. OCRでスキャンPDFをテキスト化する
スキャナで取り込んだ請求書、契約書、議事録などは「画像PDF」になります。これを読み取るにはOCRが必須です。
Tesseractのインストール(事前準備)
- Mac:
brew install tesseract tesseract-lang - Windows: 公式インストーラーから取得し、PATHを通す
日本語OCRには tesseract-lang の中の jpn.traineddata が必要です。
プロンプト例6:スキャンPDFを日本語OCRする
scanned.pdf はスキャンされた画像PDFです。各ページを画像化してから、pytesseractで日本語OCRをかけ、テキストファイルとして保存してください。
from pdf2image import convert_from_path
import pytesseract
pages = convert_from_path("scanned.pdf", dpi=300)
with open("ocr_result.txt", "w", encoding="utf-8") as f:
for i, page in enumerate(pages, 1):
text = pytesseract.image_to_string(page, lang="jpn")
f.write(f"\n===== Page {i} =====\n{text}")
print("OCR完了")
dpi=300 がポイントです。デフォルトの200だと精度が落ちるため、文字密度が高い書類ほど高解像度に設定するのがコツです。
OCRの精度を上げる工夫
OCRの精度が低いです。前処理として画像を二値化・ノイズ除去してから再度OCRをかけてください。
from PIL import Image, ImageOps, ImageFilter
img = page.convert("L") # グレースケール
img = ImageOps.autocontrast(img) # コントラスト調整
img = img.filter(ImageFilter.MedianFilter(3)) # ノイズ除去
img = img.point(lambda x: 0 if x < 150 else 255, "1") # 二値化
text = pytesseract.image_to_string(img, lang="jpn")
このひと手間で、認識率が体感1〜2割上がります。
h2-7. 100枚のPDFを一括処理する
ここまでの内容を踏まえて、実務で最もインパクトのある「複数PDFの一括処理」を行います。
プロンプト例7:請求書PDFを一括で表抽出してExcelに集約
invoices フォルダ内の全PDF(各ファイルが1つの請求書)から、商品名・数量・単価・金額の明細を抽出してください。ファイル名(請求書番号として扱う)も列に加え、最終的に1つのExcelファイル all_invoices.xlsx にまとめてください。
import pdfplumber
import pandas as pd
from pathlib import Path
records = []
for pdf_path in Path("invoices").glob("*.pdf"):
with pdfplumber.open(pdf_path) as pdf:
for page in pdf.pages:
for table in page.extract_tables() or []:
header = table[0]
for row in table[1:]:
if len(row) != len(header):
continue
record = dict(zip(header, row))
record["請求書ファイル"] = pdf_path.name
records.append(record)
df = pd.DataFrame(records)
df.to_excel("all_invoices.xlsx", index=False)
print(f"{len(records)}件の明細を抽出しました")
実測で、100枚の請求書PDFを5分以内で1つのExcelにまとめられます。月次の経理作業がそのまま自動化できる威力です。
h2-8. よくあるトラブルと対処法
PDF処理では、独特のトラブルが起こりがちです。代表例をまとめます。
1. 文字化け(特に古いPDF)
CIDフォントの埋め込みが原因のことが多いです。pdfplumber でダメなら PyMuPDF の page.get_text("text") を試すと改善することがあります。
2. 縦書き日本語が崩れる
縦書きはOCRの方が安定する場合があります。pytesseract で lang="jpn_vert" を指定するのが定番です。
3. パスワード付きPDF
パスワード付きPDF secret.pdf を開いてテキスト抽出するスクリプトを書いてください。パスワードは "1234" です。
from pypdf import PdfReader
reader = PdfReader("secret.pdf")
if reader.is_encrypted:
reader.decrypt("1234")
text = "\n".join(p.extract_text() or "" for p in reader.pages)
print(text[:500])
4. 一部だけテキスト・一部だけ画像のPDF
ページごとに種別判定してから処理を切り替えるのが正解です。プロンプト例8でその実装を扱います。
プロンプト例8:ページごとに自動で抽出方法を切り替え
mixed.pdf にはテキストページと画像ページが混在しています。ページごとに自動で判別し、テキストページは pdfplumber、画像ページは OCR で処理して、1つのテキストファイルにまとめてください。
import pdfplumber
from pdf2image import convert_from_path
import pytesseract
results = []
with pdfplumber.open("mixed.pdf") as pdf:
pages_img = None
for i, page in enumerate(pdf.pages, 1):
text = (page.extract_text() or "").strip()
if len(text) > 100:
results.append(f"\n===== Page {i} (text) =====\n{text}")
else:
if pages_img is None:
pages_img = convert_from_path("mixed.pdf", dpi=300)
ocr_text = pytesseract.image_to_string(pages_img[i-1], lang="jpn")
results.append(f"\n===== Page {i} (OCR) =====\n{ocr_text}")
with open("mixed_result.txt", "w", encoding="utf-8") as f:
f.write("\n".join(results))
これで「混在PDF問題」もワンストップで解決できます。
実践チュートリアル:請求書PDFをExcel明細に変換する30分プログラム
最後に、本記事のテーマである「具体的に使える」流れを30分で完走するチュートリアルとしてまとめます。
ステップ1: invoices というフォルダを作り、対象の請求書PDFを全部入れる。
ステップ2: ターミナルで該当フォルダに移動して claude 起動。
ステップ3: 次のプロンプトを順に投げる。
1. invoices フォルダに何枚のPDFがありますか?まずファイル一覧を見せてください。
2. 1枚だけサンプルとして開き、テキストPDFか画像PDFか判定してください。
3. テキストPDFなら pdfplumber、画像PDFなら OCR で明細を抽出するスクリプトを作ってください。
4. 全PDFに対して一括処理し、 all_invoices.xlsx に集約してください。
5. 集約後、商品名ごとの合計金額、月別合計などの集計シートも追加してください。
経理担当者なら、毎月数時間〜半日の作業が、確実に1時間以内に圧縮できます。
FAQ
Q1. PDFの種類によって抽出精度に差があるのはなぜですか?
PDFは見た目が同じでも、内部構造はバラバラです。Wordから書き出されたPDFは文字情報を保持しているため抽出が容易ですが、紙をスキャンしたPDFは画像なのでOCRが必要です。さらに、フォントが特殊(CIDフォント等)だと文字化けが起きやすくなります。最初に種別を判別するクセをつけましょう。
Q2. OCRの精度が低いとき、何をすればよいですか?
(1) DPIを上げる(300以上推奨)、(2) 画像を二値化・ノイズ除去する、(3) Tesseractの言語データを最新にする、(4) --psm オプションでページセグメンテーションモードを変える——この4点を試してみてください。それでも改善しない場合はクラウドOCR(Google Cloud Vision、Azure AI Document Intelligence)の利用も検討対象になります。社内利用の場合はエンジニアに相談してください。
Q3. パスワード付きPDFを安全に扱う方法は?
パスワードはソースコードに直書きせず、環境変数や .env ファイルから読み込むようにします。.env ファイルは絶対にGitHubにコミットしないようにしましょう。
Q4. 縦書き日本語の議事録がうまく読めません。
縦書きPDFは pytesseract の lang="jpn_vert" を指定するか、ページを90度回転させてから処理する方法が有効です。ClaudeCodeに「縦書きPDFのOCRをかけてください」と一言伝えれば、自動で適切な処理を選んでくれます。
Q5. 100枚以上のPDFを処理するとき、メモリは大丈夫ですか?
ファイルごとに開いて閉じる形にすれば、メモリは問題になりません。with pdfplumber.open(...) の with 構文を使えば、自動でリソースを解放してくれます。
Q6. PDFを編集(テキスト書き換え)したいのですが、可能ですか?
技術的には可能ですが、安全に行うには PyMuPDF の知識が必要です。書き換えではなく「新しいPDFを生成する」アプローチ(reportlab などを使う)の方が現実的なことが多いです。
Q7. 機密情報を含むPDFをClaudeCodeで扱っても大丈夫ですか?
ClaudeCodeはローカルでPythonを実行するため、抽出処理自体は外部に出ません。ただし、抽出結果をClaudeに見せるかどうかは設定や運用次第です。機密情報を含む場合は、必ず社内ルールに従い、不明な点はエンジニアに確認してください。
まとめ
PDFは“見るための形式”であり、データを取り出すには工夫が必要です。本記事では、テキスト抽出、表抽出、画像抽出、OCRという4つの代表的な手法を、ClaudeCodeと組み合わせて実演しました。重要なのは、(1)まずPDFの種別を判別する、(2)用途に応じてライブラリを使い分ける、(3)一括処理で“面倒”を“仕組み”に変える——この3点です。請求書、議事録、契約書、カタログ——PDFが絡む業務はどこにでもあります。本記事のコードをベースに、自分の業務に合わせてカスタマイズすれば、年間で数百時間の削減も夢ではありません。
関連記事
- ClaudeCodeとは何か?基本の理解
- ClaudeCodeの初めての使い方
- ClaudeCodeのプロンプトのコツ
- ClaudeCodeでPythonを使う方法
- ClaudeCodeでデータ分析を行う方法
- ClaudeCodeでスクレイピングを行う方法