■ はじめに
前々からやろうと思っていたPythonのPDF化について 纏めてみる。 (半自動的にドキュメントを作れるようにしておくために)
目次
【1】PythonでのPDF化 【2】インストール 【3】API仕様 1)cell 2)image 【4】サンプル 例1:Hello World 例2:With DOT 例3:クラス化 例4:日本語対応
【1】PythonでのPDF化
* いくつかライブラリがありそうだが、以下を扱う + PyFPDF (Python Free-PDF)
https://pyfpdf.readthedocs.io/en/latest/
【2】インストール
pip install fpdf
【3】API仕様
* 分からなかったら、以下から漁ればよさげ
https://pyfpdf.readthedocs.io/en/latest/ReferenceManual/index.html
1)cell
fpdf.cell(w, h = 0, txt = '', border = 0, ln = 0, align = '', fill = False, link = '')
https://pyfpdf.readthedocs.io/en/latest/reference/cell/index.html
2)image
fpdf.image(name, x = None, y = None, w = 0, h = 0, type = '', link = '')
https://pyfpdf.readthedocs.io/en/latest/reference/image/index.html
【4】サンプル
例1:Hello World
from fpdf import FPDF pdf = FPDF() pdf.add_page() pdf.set_font("Arial", size=25) # create a cell pdf.cell(200, 10, txt="Hello world!", ln=1, align='C') pdf.cell(200, 10, txt="Hi, PDF!", ln=2, align='C') pdf.output("output.pdf") print("Done")
例2:With DOT
import graphviz from fpdf import FPDF # 画像処理ライブラリPillow(PIL) # => pip install Pillow from PIL import Image pdf = FPDF() pdf.add_page() pdf.set_font("Arial", size=25) # create a cell pdf.cell(200, 10, txt="Hello world!", ln=1, align='C') pdf.cell(200, 10, txt="Hi, PDF!", ln=2, align='C') # DOT graph = graphviz.Source.from_file('sample.dot', format='png') graph.render(filename="output1", cleanup=True) dot_image = Image.open('output1.png') width, height = dot_image.size # この辺のサイズは、まじめに計算した方がいい pdf.image('output1.png', x=20, y=pdf.get_y(), w=30) pdf.output("output.pdf") print("Done")
例3:クラス化
import graphviz from fpdf import FPDF from PIL import Image class PdfCreator(): def __init__(self): self.pdf = FPDF() self.pdf.add_page() self.pdf.set_font("Arial", size=10) def add_text(self, text): self.pdf.cell(200, 10, txt=text, ln=1, align='L') def add_dot_image(self, dot): # DOT format = 'png' graph = graphviz.Source.from_file(dot, format=format) file_name = 'temp1' graph.render(filename=file_name, cleanup=True) image_file = f'{file_name}.{format}' dot_image = Image.open(image_file) width, height = dot_image.size pdf_image_width = self.calculate_width( width, height, self.pdf.get_y()) self.pdf.image(image_file, x=20, y=self.pdf.get_y(), w=pdf_image_width) def calculate_width(self, width, height, y): # width:height = x : y # => x = (width * y) / height return (int)((width * y) / height) def output_pdf(self, output): self.pdf.output(output) if __name__ == "__main__": pdf = PdfCreator() pdf.add_text('Add DOT Image:') pdf.add_dot_image('demo1.dot') pdf.output_pdf('output_ex.pdf') print("Done")
demo1.dot
digraph { graph [rankdir=LR] node [fontname="MS Gothic"] table1 table2 table3 table4 table1 -> table2 table2 -> table3 table2 -> table4 # ADD HERE, IF YOU WANT table2[shape = box, style = "dashed,rounded,filled" color = "#9BD4A3"]; }
例4:日本語対応
generate_samples.py
from fpdf import FPDF, XPos, YPos ######### # To create a PDF with Japanese text ######### pdf = FPDF() pdf.add_page() pdf.add_font('Noto', '', '/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc') pdf.set_font('Noto', '', 14) lines = [ "会社名:株式会社テスト", "職種:ソフトウェアエンジニア", "勤務地:東京都渋谷区", "給与:年収500万円〜700万円" ] for line in lines: pdf.cell(200, 10, text=line, new_x=XPos.LMARGIN, new_y=YPos.NEXT) pdf.output("sample.pdf") print("✅ sample.pdf created")
Dockerfile
FROM python:3.13-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
fonts-noto-cjk \
build-essential \
gcc \
libgl1 \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
WORKDIR /app
# For generate_samples.py
RUN pip install --no-cache-dir fpdf2
実行例
# Building Docker image completed. docker build -t demo-env . # Generating sample files... docker run --rm -v "$PWD":/app demo-env python generate_samples.py
参考文献
https://pymori.xyz/fawbgg4yx8/
https://blog.imind.jp/entry/2020/03/07/230101
関連記事
Python ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2014/08/07/231242
Python ~ 基本編 / 文字列 ~
https://dk521123.hatenablog.com/entry/2019/10/12/075251
Python 〜 PDF to TEXT 〜
https://dk521123.hatenablog.com/entry/2025/10/04/214922
Python ~ 画像処理 / Pillow ~
https://dk521123.hatenablog.com/entry/2023/07/10/000000
Python 〜 Tesseract OCR 〜
https://dk521123.hatenablog.com/entry/2025/10/03/141326