processing-pdf について
PDFのテキスト、表、フォームの抽出に加え、ページの画像化、分割、結合、回転を行うスキルです。スキャン文書や複雑な複数ページ文書にはpdf-extractorエージェントを使い、簡易処理にはコマンドラインやPythonのツールを利用します。
主な機能
- 01テキスト、表、メタデータの抽出
- 02スキャンページを画像化してLLMで読み取り
- 03PDFフォームの確認と入力
- 04ページの分割、結合、回転、削除
- 05ページ別の抽出結果の整理
活用シーン
- 01スキャン文書や複雑なレイアウトからの情報抽出
- 02指定ページのテキストの簡易抽出
- 03抽出した表のCSV保存
- 04フォーム入力やPDFページの整理
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ osmontero/ opencode-skills --skill processing-pdfインストール後、Claude Code で/processing-pdfを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSE.txtscripts/check_forms.pyextract_tables.pyextract_text.pyfill_form.pymetadata.pyto_images.py詳細
PDF の処理
コマンドラインツールと Python ライブラリを使用して PDF ファイルを処理します。スキャンされた PDF の場合は、ページを画像に変換し、LLM の組み込み画像理解機能を使って読み取ります。
前提条件
Python スクリプトを実行する前に、opencode 仮想環境を有効化してください。
source ~/.local/opencode-venv/bin/activate
その後、通常どおり python3 scripts/... を使用します。
利用可能なツール
| ツール | コマンド | 用途 |
|---|---|---|
pdf-extractor エージェント | グローバルエージェント(task 経由で呼び出し) | PDF の完全な抽出(全ページ、全データ、構造化されたフォルダーツリー) |
pdftotext | システム(Poppler) | テキストの簡易抽出 |
pdfinfo | システム(Poppler) | メタデータ、ページ数 |
pypdf | Python(venv) | 結合、分割、回転 |
pdfplumber | Python(venv) | 表の抽出、詳細なテキスト |
to_images.py | Python スクリプト(venv) | ページを PNG 画像に変換 |
選択ガイド
Need to process a PDF?
│
├─ Extract everything from a PDF?
│ └─ Dispatch the `pdf-extractor` agent.
│ It converts all pages to images, reads each one, and stores
│ per-page results in extracted_data/<pdf_name>/page_NNN/content.md
│ along with images and a summary.
│
├─ Quick text from a normal PDF?
│ ├─ Simple: pdftotext input.pdf output.txt
│ └─ With page numbers: python3 scripts/extract_text.py input.pdf
│
├─ Extract tables?
│ └─ python3 scripts/extract_tables.py input.pdf -o ./tables/
│
├─ Fill a form?
│ ├─ Check fields: python3 scripts/check_forms.py input.pdf
│ └─ Fill: python3 scripts/fill_form.py input.pdf fields.json output.pdf
│
├─ Read a scanned PDF (quick)?
│ ├─ Convert: python3 scripts/to_images.py scanned.pdf -o ./pages/ --dpi 200
│ └─ Read the images and extract what you need
│
├─ Merge/Split/Rotate?
│ └─ See pypdf examples below
│
└─ Large file (>50MB)?
├─ Quick text: pdftotext (fastest)
└─ Page ranges: pdftotext -f N -l M input.pdf
PDF の完全な抽出
PDF からすべてのデータ(テキスト、表、フォーム、構造)を完全に抽出するには、pdf-extractor エージェントを呼び出します。このエージェントは次の処理を行います。
- すべてのページを PNG 画像に変換します
- LLM の視覚機能を使って各画像を読み取ります
- テキスト、表、重要な事実、フォームフィールド、注記を抽出します
- ページごとに
extracted_data/<pdf_name>/page_NNN/に出力します。page_NNN.png— ページ画像content.md— すべてのテキストと抽出した事実を Markdown 形式で記載- 必要に応じて、LLM が読み取れるその他のファイル
- ドキュメント全体の概要をまとめた
summary.mdを作成します
抽出エージェントを使う場合
- すべてのデータが必要な複数ページのドキュメント
- スキャンされた PDF、またはスキャン画像とデジタルデータが混在する PDF
- 複雑なレイアウト(表、段組み、フォーム)のドキュメント
- 結果を構造化された、参照しやすいフォルダーツリーで取得する必要がある場合
簡易抽出(エージェントなし)
1 ページだけの場合や、内容を手早く確認したい場合は、以下の手順を手動で実行します。
スキャンされた PDF の読み取り(簡易、エージェントなし)
PDF がスキャンされたもので(選択可能なテキストがない場合)は、ページを画像に変換し、LLM に読み取らせます。
手順 1:PDF がスキャンされたものか確認する
pdftotext document.pdf - | head -20
出力が空、または空白文字だけの場合、PDF はスキャンされたものです。
手順 2:ページを画像に変換する
# All pages at 200 DPI (sufficient for most documents)
python3 scripts/to_images.py document.pdf -o ./pdf-pages/ --dpi 200
# Higher quality for handwritten or low-quality scans
python3 scripts/to_images.py document.pdf -o ./pdf-pages/ --dpi 300
手順 3:画像を読み取る
生成された PNG ファイルを直接参照します。LLM はそのまま画像を読み取れます。テキスト、表、フィールドの抽出や、ドキュメントの内容に関する質問への回答を依頼してください。
手順 4:後片付け
rm -rf ./pdf-pages/
スキャンされた PDF に関するヒント
- ほとんどのドキュメントでは 200 DPI で十分です
- 手書きの内容や不鮮明なスキャンには 300 DPI を使用します
- 大きな PDF はページを分割してバッチ処理します(先に pypdf で分割してから変換します)
- 読み取り後は、生成された画像ディレクトリを必ず削除してください
テキストの抽出
簡易抽出(pdftotext)
# Simple extraction
pdftotext input.pdf output.txt
# Single page
pdftotext -f 3 -l 3 input.pdf page3.txt
# With layout preservation
pdftotext -layout input.pdf output.txt
# Page range
pdftotext -f 5 -l 10 input.pdf pages_5_10.txt
ページ番号付き(スクリプト)
python3 scripts/extract_text.py input.pdf
PDF 情報の取得
pdfinfo input.pdf
表の抽出
スクリプト(推奨)
python3 scripts/extract_tables.py input.pdf -o ./tables/
Python(インライン)
import pdfplumber
import csv
with pdfplumber.open("input.pdf") as pdf:
for i, page in enumerate(pdf.pages):
tables = page.extract_tables()
for j, table in enumerate(tables):
with open(f"page{i+1}_table{j+1}.csv", "w", newline="") as f:
writer = csv.writer(f)
for row in table:
writer.writerow([cell or "" for cell in row])
フォームの処理
入力可能なフィールドを確認する
python3 scripts/check_forms.py input.pdf
フォームに入力する
python3 scripts/fill_form.py input.pdf fields.json output.pdf
fields.json の内容は次のとおりです。
{
"field_name": "John Smith",
"email": "[email protected]",
"date": "2026-05-04"
}
PDF の操作(pypdf)
PDF を結合する
from pypdf import PdfReader, PdfWriter
writer = PdfWriter()
for pdf_file in ["file1.pdf", "file2.pdf", "file3.pdf"]:
reader = PdfReader(pdf_file)
for page in reader.pages:
writer.add_page(page)
with open("merged.pdf", "wb") as f:
writer.write(f)
個別のページに分割する
from pypdf import PdfReader, PdfWriter
reader = PdfReader("input.pdf")
for i, page in enumerate(reader.pages):
writer = PdfWriter()
writer.add_page(page)
with open(f"page_{i+1:03d}.pdf", "wb") as f:
writer.write(f)
ページを回転する
from pypdf import PdfReader, PdfWriter
reader = PdfReader("input.pdf")
writer = PdfWriter()
for page in reader.pages:
page.rotate(90) # 90, 180, or 270 degrees
writer.add_page(page)
with open("rotated.pdf", "wb") as f:
writer.write(f)
ページを削除する
from pypdf import PdfReader, PdfWriter
reader = PdfReader("input.pdf")
writer = PdfWriter()
pages_to_keep = {0, 1, 4, 5} # 0-indexed
for i, page in enumerate(reader.pages):
if i in pages_to_keep:
writer.add_page(page)
with open("trimmed.pdf", "wb") as f:
writer.write(f)
メタデータ
python3 scripts/metadata.py input.pdf
画像に変換する
python3 scripts/to_images.py input.pdf --dpi 200
大きなファイル
大きな PDF(>50MB)の場合:
- 簡易抽出には
pdftotextを使用します(Python より高速です) pdfplumberでページをバッチ処理します- 特定のページ範囲には
pdftotextの-fフラグと-lフラグを使用します
大きな出力ファイルの書き込み
非常に大きな PDF からテキストを抽出する場合は、一度に書き込むのではなく、編集ごとに約 1000 トークンずつ、出力を段階的に書き込んでください。
よくあるパターン
PDF 内のテキストを検索する
pdftotext input.pdf - | grep -n "search term"
2 つの PDF を比較する(テキストの差分)
pdftotext doc1.pdf - > /tmp/doc1.txt
pdftotext doc2.pdf - > /tmp/doc2.txt
diff /tmp/doc1.txt /tmp/doc2.txt
エッジケース
暗号化された PDF
from pypdf import PdfReader
reader = PdfReader("encrypted.pdf")
if reader.is_encrypted:
reader.decrypt("") # Try empty password first
破損または無効な PDF
try:
with pdfplumber.open("file.pdf") as pdf:
# process...
except Exception as e:
print(f"Error processing PDF: {e}")
非常に大きな PDF(>100MB)
- 高速化のために
pdftotextを使用します - pdfplumber を使ってページごとのバッチで処理します
- ファイル全体をメモリに読み込まないようにします
コンテンツが混在する場合(一部のページがスキャン済みで、一部は未スキャン)
- まず標準的な抽出(
pdftotext)を試します - テキストが空で返されたページを確認します
- それらのページだけを画像に変換し、LLM に読み取らせます