- Python で PDF を扱いたい!
- 分割や結合など自在に操作したい!
このような疑問にお答えします。
これまで Python で PDF ファイルを扱うには “PyPDF2” というライブラリが主に使われていました。
ところが最近になって長らくアップデートがされていなかった “PyPDF” が久しぶりにバージョンアップ。今後は PyPDF を使うのがスタンダードになっていくと思われます。
そこで本記事では、PyPDF を使った PDF 操作の方法をご紹介します。
Python で PyPDF を使った PDF 操作の方法
ここからは以下のような PyPDF で PDF 操作する方法をお伝えします。
- PyPDF のインストール
- PDF ファイルの読み込み
- テキストの抽出
- PDF の結合
- PDF の分割
- PDF のページ順を並べ替える
- 画像を読み込む
- メタデータにアクセスする
それぞれ、解説していきます。
PyPDF のインストール
PyPDF はサードバーティライブラリなので、pip などでインストールが必要です。
pip install pypdf
PyPDF2 というライブラリも存在しますが、全くの別物です。
間違えないよう注意しましょう。
PDF ファイルの読み込み
PDF の読み込みには、PdfReader を使います。
# ライブラリのインポート
from pypdf import PdfReader
# PDFファイルの読み込み
reader = PdfReader("sample.pdf")
上記では “sample.pdf” を読み込んで、reader という変数に格納しています。
今後の操作は、この reader に対してメソッド等を適用して操作を行っていきます。
テキストの抽出
PDF 内のテキストを抽出するには、以下のステップを踏みます。
- PDF のページ数を確認する
- 取得したいページ番号を指定する
- テキスト抽出
コード例は以下のようになります。
# ライブラリのインポート
from pypdf import PdfReader
# PDFファイルの読み込み
reader = PdfReader("sample.pdf")
# ページ数の取得
number_of_pages = len(reader.pages)
# 1ページ目を取得
page_no1 = reader.pages[0]
# テキストの抽出
text = page_no1.extract_text()
print(text)
テキストの抽出はextract_text()
メソッドを使えば簡単に行えます。
PDF の結合
PDF の結合には、PdfWriter を用います。
from pypdf import PdfWriter
# 結合したいPDFファイルのリスト
pdf_files = ["file1.pdf", "file2.pdf", "file3.pdf"]
merger = PdfWriter()
for pdf_file in pdf_files:
merger.append(pdf_file)
merger.write("merged.pdf")
merger.close()
merger という空の PDF を用意し、そこに結合したい PDF ファイルの内容を追加(append
)していく流れになります。
PDF の分割
PDF の分割を行う場合には、元となる PDF を読み込んだ後に新しく PDF を作成することになります。そのため、PdfWriter と PdfReader の2つを用いていきます。
以下にサンプルコードを掲載します。
# ライブラリのインポート
from pypdf import PdfReader, PdfWriter
# PDFの読み込み
reader = PdfReader("file1.pdf")
# 1ページ目を読み込み
page_no1 = reader.pages[0]
# PDFを出力用のオブジェクトを用意
writer = PdfWriter()
# 1ページ目を出力用オブジェクトに追加
writer.add_page(page_no1)
# "devide.pdf"としてファイルに書き出し
with open("devide.pdf", "wb") as pdf_file:
writer.write(pdf_file)
1ページ目だけを抽出し、新しい PDF ファイルとして出力するものになります。
PDF のページ順を並べ替える
これまでご紹介した PdfReader, PdfWriter をうまく使うことで、ページ順の入れ替えもできます。
こちらもサンプルコードで処理の流れを確認していきましょう。
from pypdf import PdfReader, PdfWriter
# 元データの読み込み
reader = PdfReader("source.pdf")
# 新しいページの順序を定義(3ページ目、1ページ目、2ページ目)
new_order = [2, 0, 1]
# PDFを出力用のオブジェクトを用意
writer = PdfWriter()
# 新しい順序でページを追加
for index in new_order:
writer.add_page(reader.pages[index])
# 並び替えられたPDFをファイルに保存
with open("sorted_example.pdf", "wb") as output_pdf:
writer.write(output_pdf)
reader.pages[index]
とすることで何ページ目かを指定できるので、これを利用して順番を入れ替える方法になります。
ここでは順番を[2, 0, 1]として定義しています。そのため、例えば元の PDF に4ページ目以降が存在する場合には4ページ目以降は出力対象から外れる点には注意してください。
大量のページがある PDF ファイルを自在に取り扱う場合には、ロジック面で少し工夫が必要になるかもしれません。
画像を読み込む
画像の読み込みも可能です。
from pypdf import PdfReader
# PDFの読み込み
reader = PdfReader("sample.pdf")
# 1ページ目を取得
page = reader.pages[0]
for count, image_file_object in enumerate(page.images):
with open(f"{count}_{image_file_object.name}", "wb") as image:
# 画像の書き出し
image.write(image_file_object.data)
画像もページ数と同様、インデックス番号で取得していく流れとなります。
大量の PDF ファイルから特定の情報を抽出する
大量の PDF から特定の文字列情報を取得するには、正規表現を上手に使うことが重要です。
正規表現をイチから説明すると長くなってしまうので、自信のない方は以下の別記事をご覧ください。
ここでは、簡単なサンプルコードを示します。
from pypdf import PdfReader
import re
def extract_information(pdf_path):
with open(pdf_path, "rb") as file:
reader = PdfReader(file)
text = ""
for page in reader.pages:
text += page.extract_text() + "\n"
return text
def search_information(text, pattern):
# 正規表現を使用して特定の情報を検索
matches = re.findall(pattern, text)
return matches
# 特定のパターンを定義(例:電話番号、メールアドレスなど)
pattern = r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"
# 抽出するPDFファイルのリスト
pdf_files = ["file1.pdf", "file2.pdf", "file3.pdf"]
# 情報抽出と検索の実行
for pdf_file in pdf_files:
text = extract_information(pdf_file)
matches = search_information(text, pattern)
print(f"Matches in {pdf_file}: {matches}")
最後に Pandasなどを利用して CSV 出力などすると良いかもしれません。
メタデータにアクセスする
PDF のメタデータとは、ファイルの内容とは直接関連しないデータのことです。
例えば以下のような情報があります。
- 作者名
- タイトル
- 主題
- キーワード
- 作成日
- 更新日
- PDFのバージョン
- PDFを生成したソフトウェア名
- 著作権情報
これらを取得するには、PdfReader オブジェクトに対してmetadataプロパティを指定して取得します。
# ライブラリのインポート
from pypdf import PdfReader
# PDFファイルの読み込み
reader = PdfReader("sample.pdf")
# メタデータを取得する
metadata = reader.metadata
print(metadata)
出力例は以下の通りです。
{
'/CreationDate': "D:20151127175214+09'00'",
'/ModDate': "D:20151127175215+09'00'",
'/Producer': 'JUST PDF 3'
}
上記の出力結果は、こちらのPDFから取得したものです。
PyPDF のパフォーマンスを最適化するヒント
PDF ファイルのページ数が膨大になってくると、読み込み等の速度が落ちてくる場合があります。
特に Web アプリケーション環境では、以下でご紹介するパフォーマンスアップの施策を取り入れてみてください。
必要なページのみを読み込む
読み込むページが決まっている場合には、対象のページのみを読み込むようにします。
これにより、不要なページを読み込むためのリソースを削減できます。
大量のデータを扱う場合は一時ファイルを使用する
大量のページを結合または操作する場合、全データをメモリに保持せずに「一時ファイル」にデータを書き出すことも検討しましょう。
メモリ使用量の削減が期待できます。
PDF の構造をできるだけシンプルに保つ
PDF は「埋め込みフォント」や「画像」「レイアウト」など、構造を複雑にしようと思えばいくらでも複雑になってしまうファイルフォーマットです。
ソースとなる PDF も作成している場合には、できるだけシンプルなフォーマットに保つようにしましょう。
これにより PyPDF で情報を抽出する手間が飛躍的に簡単になります。
プロファイリングツールを使ってみる
“cProfile” や “line_profiler” などのプロファイリングツールを使う方法もあります。
処理時間がかかっている箇所を可視化することで、どこを改善すればパフォーマンスアップが期待できるかを知ることができます。
まとめ
PDF は日常的に使われているファイルフォーマットなので、これをプログラミングで扱えるようになると大きなアドバンテージになります。
本記事でご紹介した内容をマスターして、ぜひ自在に PDF を扱えるようになってみてください。
本ブログの Python 関連の記事一覧は、以下からご覧いただけます。
ぜひ、ご覧になってみてください。
コメント