Python PDF生成完全ガイド|ReportLab・WeasyPrint・API比較と実装例
「PythonでPDFを生成したい」という要件は、請求書・レポート・証明書・帳票など、あらゆるWebアプリやデータパイプラインで発生します。Pythonにはライブラリが豊富にある一方、それぞれに得意・不得意があります。
この記事では、Pythonプロジェクトでよく使われる6つのアプローチを実際に動くコード例とともに比較し、ユースケース別の選び方を解説します。FUNBREW PDF APIを使う方法を中心に、Django・FastAPI・Flask連携、バッチ処理まで幅広くカバーします。
PythonでのPDF生成:6つのアプローチ比較
まず主要な手法を一覧で比較します。
| アプローチ | HTMLサポート | CSS精度 | 依存関係 | サーバーレス | おすすめ用途 |
|---|---|---|---|---|---|
| FUNBREW PDF API | 完全 | 高(Chromium) | requestsのみ |
対応 | 本番環境・SaaS・複雑レイアウト |
| ReportLab | なし | — | 中 | 対応 | 数値・グラフ・データレポート |
| WeasyPrint | 完全 | 中〜高 | 大(GTK依存) | 困難 | HTMLメール→PDF・中規模アプリ |
| xhtml2pdf | XHTML | 低 | 中 | 対応 | 小規模・シンプルなレイアウト |
| pdfkit(wkhtmltopdf) | 完全 | 中 | wkhtmltopdfバイナリ | 困難 | 既存wkhtmltopdf環境の維持 |
| Playwright for Python | 完全 | 高(Chromium) | Chromiumバイナリ | 困難 | ローカル・テスト自動化兼用 |
複雑なHTMLレイアウト(グラフ・表・日本語フォント)を含む業務PDFには PDF API が最も適しています。PDF APIとライブラリの比較で詳しく解説しています。
1. FUNBREW PDF API(推奨)
インストールと基本設定
pip install requests python-dotenv
# pdf_client.py
import os
import requests
from dotenv import load_dotenv
load_dotenv()
FUNBREW_API_KEY = os.environ["FUNBREW_API_KEY"]
FUNBREW_API_URL = os.getenv("FUNBREW_API_URL", "https://api.pdf.funbrew.cloud/v1")
def html_to_pdf(
html: str,
engine: str = "quality", # "quality"(Chromium)または "fast"(wkhtmltopdf)
format: str = "A4",
landscape: bool = False,
margin: dict | None = None,
) -> bytes:
"""
HTML文字列をPDFバイナリに変換する。
Args:
html: PDF化するHTML文字列
engine: "quality"(Chromium)または "fast"(wkhtmltopdf)
format: 用紙サイズ("A4", "Letter", "Legal" など)
landscape: 横向きにするか
margin: 余白設定(top/bottom/left/right をmm単位で指定)
Returns:
PDFのバイナリデータ(bytes)
"""
if margin is None:
margin = {"top": "20mm", "bottom": "20mm", "left": "15mm", "right": "15mm"}
response = requests.post(
f"{FUNBREW_API_URL}/pdf/from-html",
headers={
"Authorization": f"Bearer {FUNBREW_API_KEY}",
"Content-Type": "application/json",
},
json={
"html": html,
"engine": engine,
"format": format,
"landscape": landscape,
"margin": margin,
},
timeout=30,
)
response.raise_for_status()
return response.content
APIドキュメントでオプションの完全仕様を確認できます。
基本的な使い方
# generate_basic.py
from pdf_client import html_to_pdf
html = """<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<style>
body { font-family: 'Noto Sans JP', sans-serif; padding: 40px; color: #1e293b; }
h1 { color: #2563eb; }
</style>
</head>
<body>
<h1>Hello, PDF!</h1>
<p>PythonからFUNBREW PDF APIでPDFを生成しました。</p>
</body>
</html>"""
pdf_bytes = html_to_pdf(html)
with open("output.pdf", "wb") as f:
f.write(pdf_bytes)
print(f"PDF生成完了: {len(pdf_bytes):,} bytes")
請求書PDFの実用例
# invoice_generator.py
from datetime import date
from pdf_client import html_to_pdf
def build_invoice_html(
customer_name: str,
amount: int,
items: list[dict] | None = None,
company_name: str = "株式会社FUNBREW",
) -> str:
tax = int(amount * 0.1)
total = amount + tax
invoice_number = f"INV-{date.today().strftime('%Y%m%d')}-001"
issue_date = date.today().strftime("%Y年%m月%d日")
if not items:
items = [{"name": "サービス利用料", "quantity": 1, "price": amount}]
rows = "".join(
f"<tr><td>{item['name']}</td>"
f"<td style='text-align:right'>{item['quantity']}</td>"
f"<td style='text-align:right'>¥{item['price']:,}</td>"
f"<td style='text-align:right'>¥{item['price'] * item['quantity']:,}</td></tr>"
for item in items
)
return f"""<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<style>
@page {{ size: A4; margin: 20mm 15mm; }}
* {{ box-sizing: border-box; margin: 0; padding: 0; }}
body {{
font-family: 'Noto Sans JP', 'Hiragino Sans', sans-serif;
font-size: 12px; color: #1e293b;
-webkit-print-color-adjust: exact; print-color-adjust: exact;
}}
.header {{ display: flex; justify-content: space-between;
border-bottom: 3px solid #2563eb; padding-bottom: 16px; margin-bottom: 24px; }}
.title {{ font-size: 28px; font-weight: 700; color: #2563eb; }}
table {{ width: 100%; border-collapse: collapse; margin-top: 16px; }}
th {{ background: #dbeafe; padding: 10px; text-align: left; }}
td {{ padding: 10px; border-bottom: 1px solid #e2e8f0; }}
.total {{ text-align: right; margin-top: 16px; }}
.total-amount {{ font-size: 22px; font-weight: 700; color: #2563eb; }}
</style>
</head>
<body>
<div class="header">
<div>
<div class="title">請求書</div>
<div>請求番号: {invoice_number}</div>
<div>発行日: {issue_date}</div>
</div>
<div style="text-align:right"><strong>{company_name}</strong></div>
</div>
<p><strong>{customer_name} 御中</strong></p>
<table>
<thead>
<tr><th>品目</th><th>数量</th><th>単価</th><th>小計</th></tr>
</thead>
<tbody>{rows}</tbody>
</table>
<div class="total">
<p>小計: ¥{amount:,}</p>
<p>消費税 (10%): ¥{tax:,}</p>
<p class="total-amount">合計: ¥{total:,}</p>
</div>
</body>
</html>"""
def generate_invoice_pdf(customer_name: str, amount: int, items=None) -> bytes:
html = build_invoice_html(customer_name, amount, items)
return html_to_pdf(html, engine="quality", format="A4")
if __name__ == "__main__":
pdf = generate_invoice_pdf(
customer_name="株式会社サンプル",
amount=150_000,
items=[
{"name": "Webシステム開発", "quantity": 1, "price": 120_000},
{"name": "保守サポート(月額)", "quantity": 3, "price": 10_000},
],
)
with open("invoice.pdf", "wb") as f:
f.write(pdf)
print(f"請求書PDF生成: {len(pdf):,} bytes")
エラーハンドリングとリトライ
# pdf_client_production.py
import time
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
def create_pdf_session() -> requests.Session:
"""リトライ付きのHTTPセッションを作成する"""
session = requests.Session()
retry = Retry(
total=3,
backoff_factor=1.0, # 1s, 2s, 4s でリトライ
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["POST"],
)
adapter = HTTPAdapter(max_retries=retry)
session.mount("https://", adapter)
return session
_session = create_pdf_session()
def html_to_pdf_with_retry(html: str, **kwargs) -> bytes:
response = _session.post(
f"{FUNBREW_API_URL}/pdf/from-html",
headers={
"Authorization": f"Bearer {FUNBREW_API_KEY}",
"Content-Type": "application/json",
},
json={"html": html, "engine": "quality", "format": "A4", **kwargs},
timeout=30,
)
response.raise_for_status()
return response.content
2. ReportLab
インストール
pip install reportlab
基本的な使い方
# reportlab_basic.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import mm
from reportlab.lib import colors
from reportlab.platypus import SimpleDocTemplate, Paragraph, Table, TableStyle, Spacer
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from io import BytesIO
# 日本語フォント登録(NotoSansCJKjp-Regular.otfが必要)
# pdfmetrics.registerFont(TTFont("NotoSans", "NotoSansCJKjp-Regular.otf"))
def generate_report_pdf(title: str, data: list[list]) -> bytes:
"""
ReportLabで表形式レポートPDFを生成する。
日本語を使う場合はフォント登録が必要。
"""
buffer = BytesIO()
doc = SimpleDocTemplate(
buffer,
pagesize=A4,
topMargin=20 * mm,
bottomMargin=20 * mm,
leftMargin=15 * mm,
rightMargin=15 * mm,
)
styles = getSampleStyleSheet()
elements = []
# タイトル
elements.append(Paragraph(title, styles["Title"]))
elements.append(Spacer(1, 12))
# テーブル
table = Table(data, colWidths=[80 * mm, 40 * mm, 40 * mm])
table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#2563eb")),
("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
("FONTSIZE", (0, 0), (-1, 0), 11),
("ALIGN", (1, 0), (-1, -1), "RIGHT"),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [colors.white, colors.HexColor("#f1f5f9")]),
("GRID", (0, 0), (-1, -1), 0.5, colors.HexColor("#e2e8f0")),
("TOPPADDING", (0, 0), (-1, -1), 8),
("BOTTOMPADDING", (0, 0), (-1, -1), 8),
]))
elements.append(table)
doc.build(elements)
return buffer.getvalue()
if __name__ == "__main__":
data = [
["商品名", "数量", "金額"],
["Product A", "10", "¥50,000"],
["Product B", "5", "¥30,000"],
["Product C", "20", "¥80,000"],
]
pdf = generate_report_pdf("売上レポート 2026年4月", data)
with open("report_reportlab.pdf", "wb") as f:
f.write(pdf)
print(f"ReportLab PDF: {len(pdf):,} bytes")
ReportLabの特徴:
- HTMLなしでプログラム的にPDFを組み立てる低水準API
- 日本語にはフォント登録が必要(
TTFontで.otfや.ttfを読み込む) - グラフ描画(
reportlab.graphics)が得意 - 複雑なHTMLレイアウトの再現は困難
3. WeasyPrint
インストール
# macOS
brew install python3 pango
pip install weasyprint
# Ubuntu/Debian
sudo apt-get install python3-cffi libcairo2 libpango-1.0-0 libgdk-pixbuf2.0-0
pip install weasyprint
基本的な使い方
# weasyprint_basic.py
from weasyprint import HTML, CSS
from io import BytesIO
def html_to_pdf_weasyprint(html: str, base_url: str | None = None) -> bytes:
"""WeasyPrintでHTMLをPDFに変換する"""
buffer = BytesIO()
HTML(string=html, base_url=base_url).write_pdf(
buffer,
stylesheets=[CSS(string="@page { size: A4; margin: 20mm 15mm; }")],
)
return buffer.getvalue()
html = """<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<style>
body { font-family: sans-serif; padding: 20px; }
h1 { color: #2563eb; border-bottom: 2px solid #2563eb; padding-bottom: 8px; }
table { width: 100%; border-collapse: collapse; margin-top: 16px; }
th { background: #dbeafe; padding: 8px; text-align: left; }
td { padding: 8px; border-bottom: 1px solid #e2e8f0; }
</style>
</head>
<body>
<h1>WeasyPrint デモ</h1>
<table>
<thead><tr><th>項目</th><th>値</th></tr></thead>
<tbody>
<tr><td>ライブラリ</td><td>WeasyPrint 62.x</td></tr>
<tr><td>エンジン</td><td>Cairo / Pango</td></tr>
<tr><td>日本語対応</td><td>システムフォント使用</td></tr>
</tbody>
</table>
</body>
</html>"""
pdf = html_to_pdf_weasyprint(html)
with open("output_weasyprint.pdf", "wb") as f:
f.write(pdf)
print(f"WeasyPrint PDF: {len(pdf):,} bytes")
WeasyPrintの特徴:
- HTMLとCSSを比較的忠実に再現(CSS Paged Media対応)
- GTK/Pangoへの依存があり、Dockerイメージが大きくなりやすい
- JavaScript非対応(動的レンダリング不可)
- 日本語はシステムフォントに依存(環境によってフォントが変わる)
4. xhtml2pdf
インストール
pip install xhtml2pdf
基本的な使い方
# xhtml2pdf_basic.py
from io import BytesIO
from xhtml2pdf import pisa
def html_to_pdf_xhtml2pdf(html: str) -> bytes:
"""xhtml2pdfでHTMLをPDFに変換する"""
buffer = BytesIO()
result = pisa.CreatePDF(html, dest=buffer)
if result.err:
raise RuntimeError(f"xhtml2pdf変換エラー: {result.err}")
return buffer.getvalue()
html = """<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
@page { size: A4; margin: 20mm; }
body { font-family: sans-serif; font-size: 12px; }
h1 { color: #2563eb; }
</style>
</head>
<body>
<h1>xhtml2pdf サンプル</h1>
<p>シンプルなPDFを手軽に生成できます。</p>
</body>
</html>"""
pdf = html_to_pdf_xhtml2pdf(html)
with open("output_xhtml2pdf.pdf", "wb") as f:
f.write(pdf)
print(f"xhtml2pdf PDF: {len(pdf):,} bytes")
xhtml2pdfの特徴:
- 外部バイナリ不要で軽量
- CSS 2.1の一部のみ対応(Flexbox・Grid・CSS変数は非対応)
- シンプルなレイアウトには十分だが複雑なデザインは崩れやすい
- 日本語には別途フォント指定が必要
5. pdfkit(wkhtmltopdf)
インストール
# wkhtmltopdfバイナリが別途必要
# macOS: brew install wkhtmltopdf
# Ubuntu: sudo apt-get install wkhtmltopdf
pip install pdfkit
基本的な使い方
# pdfkit_basic.py
import pdfkit
options = {
"page-size": "A4",
"margin-top": "20mm",
"margin-bottom": "20mm",
"margin-left": "15mm",
"margin-right": "15mm",
"encoding": "UTF-8",
"enable-local-file-access": "",
}
# HTML文字列からPDF生成
html = """<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>body{font-family:sans-serif;padding:40px;}</style>
</head>
<body>
<h1 style="color:#2563eb">pdfkit サンプル</h1>
<p>wkhtmltopdfを使ってPDFを生成します。</p>
</body>
</html>"""
# ファイルに保存
pdfkit.from_string(html, "output_pdfkit.pdf", options=options)
# バイナリとして取得
pdf_bytes = pdfkit.from_string(html, False, options=options)
print(f"pdfkit PDF: {len(pdf_bytes):,} bytes")
# URLからPDF生成
# pdfkit.from_url("https://example.com", "output_url.pdf")
pdfkitの特徴:
- wkhtmltopdfバイナリが必須(サーバーへのインストールが必要)
- CSS 3の多くをサポートするが、最新CSSには追従していない
- wkhtmltopdfはメンテナンス停止状態(2024年以降更新なし)
- 既存のwkhtmltopdf環境を維持する場合に有用
6. Playwright for Python
インストール
pip install playwright
playwright install chromium
基本的な使い方
# playwright_basic.py
import asyncio
from playwright.async_api import async_playwright
async def html_to_pdf_playwright(html: str, output_path: str = "output.pdf") -> bytes:
"""Playwright for PythonでHTMLをPDFに変換する(非同期)"""
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.set_content(html, wait_until="networkidle")
pdf_bytes = await page.pdf(
format="A4",
margin={"top": "20mm", "bottom": "20mm", "left": "15mm", "right": "15mm"},
print_background=True,
)
await browser.close()
return pdf_bytes
async def main():
html = """<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<style>
body { font-family: 'Noto Sans JP', sans-serif; padding: 40px; }
h1 { color: #2563eb; }
.chart-placeholder {
width: 400px; height: 200px; background: #dbeafe;
display: flex; align-items: center; justify-content: center;
border-radius: 8px; font-size: 14px; color: #1e40af;
}
</style>
</head>
<body>
<h1>Playwright PDF デモ</h1>
<p>JavaScriptのレンダリング結果を含むPDFを生成できます。</p>
<div class="chart-placeholder">グラフエリア(JS描画)</div>
</body>
</html>"""
pdf = await html_to_pdf_playwright(html)
with open("output_playwright.pdf", "wb") as f:
f.write(pdf)
print(f"Playwright PDF: {len(pdf):,} bytes")
asyncio.run(main())
Playwright for Pythonの特徴:
- Chromiumを内蔵し、JavaScriptの実行結果も含めてPDFを生成できる
playwright install chromiumで約200MBのバイナリが追加される- ローカル開発・テスト自動化と組み合わせる場合に特に有効
- 本番環境ではFUNBREW PDF APIに移行するとインフラが軽くなる
ユースケース別の選び方
請求書・契約書(複雑なレイアウト、日本語あり)
推奨: FUNBREW PDF API
# ✅ HTMLとCSSを完全制御。日本語フォントも問題なし
pdf = html_to_pdf(invoice_html, engine="quality")
HTMLとCSSで既にデザインされた帳票テンプレートがある場合、PDF APIへのHTTPリクエスト1回で高品質なPDFを得られます。Django・FastAPIでのPDF API連携も参照してください。
データ分析レポート(グラフ・表のみ)
推奨: ReportLab
# ✅ matplotlibのグラフをReportLabに埋め込む
from reportlab.platypus import Image as RLImage
import matplotlib.pyplot as plt
from io import BytesIO
# matplotlibでグラフを生成
fig, ax = plt.subplots(figsize=(5, 3))
ax.bar(["Q1", "Q2", "Q3", "Q4"], [120, 145, 132, 178])
ax.set_title("四半期売上")
img_buffer = BytesIO()
fig.savefig(img_buffer, format="png", dpi=150, bbox_inches="tight")
img_buffer.seek(0)
plt.close(fig)
# ReportLabに埋め込む
chart_img = RLImage(img_buffer, width=130*mm, height=78*mm)
elements.append(chart_img)
大量バッチ生成(数百〜数千件)
推奨: FUNBREW PDF API + 非同期並列処理
# batch_pdf.py
import asyncio
import aiohttp
from typing import AsyncIterator
async def html_to_pdf_async(
session: aiohttp.ClientSession,
html: str,
semaphore: asyncio.Semaphore,
) -> bytes:
async with semaphore:
async with session.post(
f"{FUNBREW_API_URL}/pdf/from-html",
headers={
"Authorization": f"Bearer {FUNBREW_API_KEY}",
"Content-Type": "application/json",
},
json={"html": html, "engine": "quality", "format": "A4"},
) as resp:
resp.raise_for_status()
return await resp.read()
async def generate_pdfs_batch(html_list: list[str], concurrency: int = 5) -> list[bytes]:
"""複数のHTMLを並列でPDF変換する"""
semaphore = asyncio.Semaphore(concurrency) # 同時5件に制限
connector = aiohttp.TCPConnector(limit=10)
async with aiohttp.ClientSession(connector=connector) as session:
tasks = [html_to_pdf_async(session, html, semaphore) for html in html_list]
results = await asyncio.gather(*tasks, return_exceptions=True)
# エラーを除外して成功分だけ返す
pdfs = []
for i, result in enumerate(results):
if isinstance(result, Exception):
print(f"[警告] {i}番目のPDF生成に失敗: {result}")
else:
pdfs.append(result)
return pdfs
async def main():
# 10件の請求書を並列生成
html_list = [
build_invoice_html(f"顧客{i:03d}", 100_000 + i * 5_000)
for i in range(1, 11)
]
pdfs = await generate_pdfs_batch(html_list, concurrency=5)
print(f"{len(pdfs)}件のPDFを生成しました")
if __name__ == "__main__":
asyncio.run(main())
詳細なバッチ処理のパターンはPDF一括生成ガイドを参照してください。
FastAPI・Django での組み込み
# FastAPI エンドポイント例
from fastapi import FastAPI, HTTPException
from fastapi.responses import Response
from pydantic import BaseModel
from pdf_client import html_to_pdf
app = FastAPI()
class InvoiceRequest(BaseModel):
customer_name: str
amount: int
items: list[dict] | None = None
@app.post("/api/pdf/invoice")
async def create_invoice_pdf(req: InvoiceRequest):
try:
html = build_invoice_html(req.customer_name, req.amount, req.items)
pdf_bytes = html_to_pdf(html, engine="quality", format="A4")
return Response(
content=pdf_bytes,
media_type="application/pdf",
headers={
"Content-Disposition": f"attachment; filename=invoice.pdf",
"Content-Length": str(len(pdf_bytes)),
},
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
Django・Flask・FastAPIでの詳細な実装はDjango・FastAPI・FlaskでのPDF API統合ガイドで解説しています。
ライブラリ別 詳細比較
CSSサポート比較
| CSS機能 | FUNBREW PDF API | WeasyPrint | xhtml2pdf | pdfkit |
|---|---|---|---|---|
| Flexbox | ✅ | ✅ | ❌ | △ |
| CSS Grid | ✅ | ✅ | ❌ | ❌ |
| CSS変数 | ✅ | ✅ | ❌ | ❌ |
@page ルール |
✅ | ✅ | △ | △ |
| WebFont(Google Fonts) | ✅ | △ | ❌ | ❌ |
print-color-adjust |
✅ | ✅ | ❌ | △ |
依存関係のサイズ比較
# FUNBREW PDF API
pip install requests # ~2MB
# WeasyPrint
pip install weasyprint # ~50MB(GTK含む)
# + brew install pango / apt-get install libpango-1.0-0
# pdfkit
pip install pdfkit # ~1MB
# + wkhtmltopdf バイナリ ~90MB
# Playwright
pip install playwright # ~15MB
playwright install chromium # ~200MB
よくある質問
PythonでPDFを最も簡単に生成するには?
FUNBREW PDF APIを使う方法が最も簡単です。pip install requestsだけで始められ、複雑なHTMLのレイアウトやCSSもブラウザ品質で変換できます。外部バイナリのインストールが不要なため、Dockerイメージも軽量に保てます。
WeasyPrintをDockerで使うには?
GTK・Pango・Cairoなどの依存ライブラリをインストールする必要があります。Dockerfileに以下を追加してください:
FROM python:3.12-slim
RUN apt-get update && apt-get install -y \
libpango-1.0-0 \
libpangocairo-1.0-0 \
libcairo2 \
libgdk-pixbuf2.0-0 \
libffi-dev \
&& rm -rf /var/lib/apt/lists/*
RUN pip install weasyprint
ただし、イメージサイズが増大するため、本番環境ではPDF APIへの切り替えを検討してください。
Pythonで日本語PDFが文字化けする場合は?
HTMLに<meta charset="UTF-8">を記述し、CSSでfont-family: 'Noto Sans JP', sans-serif;を指定してください。FUNBREW PDFはNoto Sans JPをプリインストール済みのため追加フォントは不要です。詳しくは日本語フォントガイドを参照してください。
ReportLabで日本語を使うには?
ReportLabはデフォルトで日本語フォントを持っていないため、.ttfまたは.otfファイルを登録する必要があります:
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
pdfmetrics.registerFont(TTFont("NotoSansJP", "/path/to/NotoSansCJKjp-Regular.otf"))
# 以降 fontName="NotoSansJP" で使用可能
pdfkitとWeasyPrint、どちらを選ぶべきか?
新規プロジェクトでは WeasyPrint を推奨します。pdfkitが依存するwkhtmltopdfは実質的にメンテナンスが停止しており、最新のCSSへの対応が不十分です。ただし、複雑なレイアウトや本番環境での安定性を重視するなら FUNBREW PDF API が最適です。
まとめ
PythonでのPDF生成手法をユースケース別にまとめます。
| ユースケース | 推奨手法 | 理由 |
|---|---|---|
| 請求書・証明書・帳票(HTMLデザインあり) | FUNBREW PDF API | 高品質・CSS完全対応・軽量 |
| データ分析レポート(グラフ中心) | ReportLab | matplotlib連携・プログラム生成 |
| 既存HTMLアーカイブのPDF変換 | WeasyPrint | CSS Paged Media対応 |
| シンプルな帳票(社内ツール) | xhtml2pdf | バイナリ不要・手軽 |
| E2Eテストとの兼用 | Playwright | ブラウザ制御も同時にできる |
| 大量バッチ生成・本番SaaS | FUNBREW PDF API | スケーラブル・インフラ不要 |
どのケースでも、まずプレイグラウンドでHTMLテンプレートを確認することをおすすめします。APIドキュメントでエンドポイントの詳細仕様も参照してください。
関連記事
- PDF生成APIクイックスタート — Python/Node.js/PHPの基本的なAPIコール
- Django・FastAPI・FlaskでのPDF API統合ガイド — Webフレームワーク別の実装パターン
- Node.js PDF生成完全ガイド — Node.js版の姉妹記事
- PDF一括生成ガイド — 数百件のPDFを効率的に処理
- HTML→PDF CSS tips — PDF専用CSSのベストプラクティス
- 日本語フォントガイド — 日本語PDF生成の完全対応
- Puppeteer移行ガイド — Playwrightからの移行を検討する場合
- PDF APIとライブラリの比較 — APIとOSSライブラリの詳細な比較
- PDF API本番運用チェックリスト — 本番環境での安定運用
- APIリファレンス — エンドポイントの詳細仕様