前提条件
- Python 3.8以上と
requestsライブラリ(pip install requests)。 - APIキー: 無料アカウントを作成し、ダッシュボードからキーをコピーします。コードに直接記述せず、環境変数に保存してください:
export PDF_SUMMARIZE_KEY="sk_live_..."
Pythonでの初めてのPDF要約
- requestsのインストール
pip install requestsを実行します。 - APIキーの設定環境変数
PDF_SUMMARIZE_KEYに設定します。 - PDFの送信フィールド名を
fileとした multipart/form-data として送信します。 - JSONの読み込み要約は
summaryに格納されます。successとHTTPステータスを確認してください。
import os
import requests
API_URL = "https://pdf-summarize.com/api/summarize.php"
API_KEY = os.environ["PDF_SUMMARIZE_KEY"]
def summarize_pdf(path, length="medium", fmt="bullets", lang="auto"):
with open(path, "rb") as f:
resp = requests.post(
API_URL,
headers={"Authorization": f"Bearer {API_KEY}"},
files={"file": (os.path.basename(path), f, "application/pdf")},
data={"length": length, "format": fmt, "outputLang": lang, "includeKeywords": "1"},
timeout=180,
)
data = resp.json()
if resp.status_code != 200 or not data.get("success"):
raise RuntimeError(f"{resp.status_code}: {data.get('error', data)}")
return data
result = summarize_pdf("annual-report.pdf")
print(result["summary"])
print("ページ数:", result["page_count"], "| キーワード:", result.get("keywords"))
レスポンス
{
"success": true,
"summary": "- 売上高は6%増の...",
"keywords": "revenue, margin, guidance, ...",
"page_count": 48,
"original_length": 182340,
"summary_length": 1210,
"processing_time": 6.214,
"requests_remaining": 4987
}
requests_remaining は、その月の残りの利用枠です(-1 は無制限を意味します)。
要約のストリーミング
長文の文書やインタラクティブなアプリでは、要約が生成されるにつれてストリーミング形式で受信します:
import json
def stream_summary(path):
with open(path, "rb") as f:
with requests.post(
API_URL + "?stream=1",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"file": (os.path.basename(path), f, "application/pdf")},
data={"length": "long", "format": "mixed"},
stream=True, timeout=300,
) as resp:
resp.raise_for_status()
for line in resp.iter_lines(decode_unicode=True):
if not line or not line.startswith("data: "):
continue
payload = line[6:]
if payload == "[DONE]":
break
event = json.loads(payload)
if "error" in event:
raise RuntimeError(event["error"])
if event.get("type") == "summary":
print(event["content"], end="", flush=True)
stream_summary("research-paper.pdf")
PDFフォルダの一括処理
import pathlib, time
out_dir = pathlib.Path("summaries")
out_dir.mkdir(exist_ok=True)
for pdf in sorted(pathlib.Path("pdfs").glob("*.pdf")):
target = out_dir / (pdf.stem + ".md")
if target.exists():
continue # 中断からの再開に対応
for attempt in range(3):
try:
data = summarize_pdf(str(pdf), length="long", fmt="mixed")
target.write_text(data["summary"], encoding="utf-8")
print("成功", pdf.name, data["page_count"], "ページ")
break
except RuntimeError as e:
if str(e).startswith("429"):
time.sleep(30 * (attempt + 1)) # レート制限: バックオフ(待機)
else:
print("失敗", pdf.name, e)
break
エラーハンドリング
| ステータス | 意味 | 対処法 |
|---|---|---|
| 400 | ファイルの欠落、不正な形式、ページ数制限オーバー | ファイルとプランのページ制限を確認する |
| 401 | APIキーの欠落または無効 | Authorization ヘッダーを確認する |
| 403 | アカウントが停止されている | サポートに問い合わせる |
| 413 | ファイルサイズが大きすぎる | PDFを圧縮するか分割する |
| 422 | 読み取り可能なテキストがない(空、保護されている、またはスキャンが不鮮明) | パスワードを解除するか、スキャン品質を改善する |
| 429 | レート制限または月間クォータに到達 | バックオフして再試行するか、プランをアップグレードする |
| 500 | 要約サービスが一時的に利用不可 | バックオフして再試行する |
ヒント
- 長いPDFの場合は、タイムアウト時間を余裕を持たせて(2〜3分に)設定してください。
- 同じ文書に対して二重に料金が発生しないよう、ファイルハッシュによる結果のキャッシュを実装してください。
- キーはサーバー側で厳重に管理し、フロントエンドやモバイルアプリに同梱しないでください。
- パラメータの完全なリファレンスについては、APIドキュメントを参照してください。
よくある質問
無料のAPIプランはありますか?
はい。無料プランには、クレジットカード不要で使える毎月のリクエスト枠が含まれています。料金プランをご覧ください。
ファイルの代わりにPDFのURLを送信できますか?
APIはファイルそのものを受け付けます。コード内でPDFをダウンロードし(requestsなどを使用)、そのバイトデータを送信してください。
要約の言語は何に対応していますか?
文書の言語をそのまま維持するには outputLang=auto を使用します。また、ja、en、fr、es、de などの言語コードを指定することも可能です。
スキャンされたPDFはどのようにAPIで要約しますか?
他のPDFと同様に送信してください。利用可能なテキストレイヤーがない場合、抽出パイプラインが自動的にOCRにフォールバックします。