【Python×PDF】PyPDF2はもう古い！PythonでPDFを扱うときにはpypdfを使おう

# はじめに

こんにちは、Ryutaroです。

さて、Pythonを使ってPDFを扱おうと思った時に、色々調べていると`PyPDF2`の記事ばかりでてきますが、`PyPDF2`の公式サイトを見ると、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/12d11204-04ef-69cf-a793-0ca5faf9d998.png)

https://pypi.org/project/PyPDF2/

> PyPDF2のプロジェクトはもともとあったプロジェクトのpypdfに戻ります。PyPDF2はバージョン3.0.xが最後のバージョンになります。開発はpypdfで続けていきます。

と書いてあります。

公式が`pypdf`で開発を続けていくと言ってるので、今回は`pypdf`の使い方をまとめます。

https://pypi.org/project/pypdf/

リリース日↓も超最近のもの（記事執筆日: 2023年3月10日）なので、開発が盛んに行われていそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/8c8df2ff-38a9-1f60-ea7f-eae0f683295f.png)

実際、リリース履歴を見てみると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/6d076525-91c6-eff3-4dbf-bb1dc4b9d1c2.png)

去年のクリスマスイブから頻繁にバージョンアップがされていることが分かります。

なので、これからは`PyPDF2`ではなく、`pypdf`を使うことをオススメしておきます。

それでは`pypdf`の使い方についてまとめていきます！

:::note info
2025/4/29追記
2024/1/19にアップデートされたVersion4.0.0では、新機能として「layoutモード」が追加されました。
これにより、テーブル検出や構造を維持したテキスト抽出ができるようになります。
PDFからテーブルっぽいものをヒューリスティックに見つけたいときに役立つよう設計されているようです。
:::

:::note info
2025/4/29追記
2024/9/17にアップデートされたVersion5.0.0では、いくつかの新機能が追加されましたが、その中でも「メタデータ削除機能」が便利そうだなと感じました。
応用例として、例えばサーバにアップロードされたPDFから著者情報や作成日時などを削除して匿名化することなどが挙げられます。
:::

# 環境設定

pipで`pypdf`をインストールします。
```
pip install pypdf
```

# pdfのモジュールを使ってみる

https://pypdf.readthedocs.io/en/stable/

このドキュメントを参考にして各モジュールの使い方をまとめていきます。


https://www.env.go.jp/guide/gyomu_pdf/index.html

今回は環境省のパンフレット↑の中の、`1. 気候変動対策`のPDF↓を例にしてみます。

https://www.env.go.jp/content/900473374.pdf

`1kankyosyo.pdf`として保存しておきます。

## 1. テキストの読み込み

PDF内のテキストを読み込んでみます。
読み込みのときには、`pypdf`の`PdfReader`というモジュールを使います。

```python
# ライブラリのインポート
from pypdf import PdfReader

# PDFファイルの読み込み
reader = PdfReader("1kankyosyo.pdf")

# ページ数の取得
number_of_pages = len(reader.pages)

# ページの取得。この場合は、1ページ目を取得する。
page = reader.pages[0]

# テキストの抽出
text = page.extract_text()
print(text)
```

結果↓
```
7気候変動対策
地球温暖化の進行によって 、異常気象の発生や
海面上昇の進行が起こるだけでなく、
農林水産業、金融業への経済影響、 災害、
難民の発生、安全保障の問題、健康への
影響など、 その影響は多岐に 渡ります 。
気候変動の原因となる温室効果ガスの
排出削減のための「緩和」対策、
気候変動の影響による被害の回避・軽減のための
「適応」対策を 両輪で取り組むことによって、
地球規模の解決を目指しています。
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/b83cd960-653d-043e-bdde-9eea5f5ea126.png)
PDFを見てみると、たしかに1ページ目に書かれているテキストが取得できていることが分かります。

[](----------------------------------------------------------------------------------------------------)

## 2. PDFの結合

結合のときには、`pypdf`の`PdfMerger`というモジュールを使います。

https://www.env.go.jp/content/900473374.pdf

https://www.env.go.jp/content/900473375.pdf

2つ目のPDFは`2kankyosyo.pdf`として保存しておいて、`1kankyosyo.pdf`と`2.kankyosyo.pdf`を結合してみます。

```python
# PDFの分割
from pypdf import PdfWriter

merger = PdfWriter()

for pdf in ["1kankyosyo.pdf", "2kankyosyo.pdf"]:
    merger.append(pdf)

merger.write("merged-pdf.pdf")
merger.close()
```

これで、`1kankyosyo.pdf`と`2.kankyosyo.pdf`の結合ができました。

## 3.PDFの分割

PDFを分割して複数ページあるPDFを分割してみます。
読み込みと書き込みの機能を組み合わせて使います。

```python
# ライブラリのインポート
from pypdf import PdfReader, PdfWriter

# PDFの読み込み
reader = PdfReader("1kankyosyo.pdf")
sourcepage = reader.pages[0]

# 書き込み用のオブジェクトを作成
writer = PdfWriter()

# 0番目の要素(1ページ目のPDF)を抜き出す
pdf = reader.pages[0]

# 書き込み用オブジェクトに追加
writer.add_page(pdf)

# ファイルに書き出し
with open("kankyosyo_p1.pdf", "wb") as fp:
    writer.write(fp)
```

これをすることで`kankyosyo_p1.pdf`に`1kankyosyo.pdf`の1ページ目だけを分割して保存することができました。

## 4.画像の読み込み

PDF内の画像を読み込んでみます。

```python
# モジュールのインポート
from pypdf import PdfReader

# PDFの読み込み
reader = PdfReader("1kankyosyo.pdf")

# ページの取得。こ場合は、1ページ目を取得する。
page = reader.pages[0]

count = 0
# ページ内の画像の個数でfor文を回す
for image_file_object in page.images:
    # pngファイルの新規作成
    with open(str(count) + image_file_object.name, "wb") as fp:
        # 画像の書き出し
        fp.write(image_file_object.data)
        count += 1
```

下のような画像を取得することができました。

![0Image113.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/0f9355ba-70a9-1d45-3a84-5c3783c80af7.png)

↓`1kankyosyo.pdf`の1ページ目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/b83cd960-653d-043e-bdde-9eea5f5ea126.png)

2つを比べてみると、たしかに1ページ目の画像を取得できていることが分かります。

# 最後に

`pypdf`の使い方についてまとめました。
詳細は下の公式ページを読んでみてください！

https://pypi.org/project/pypdf/

ここまで読んでいただきありがとうございました。

# おすすめ記事

https://qiita.com/ryutarom128/items/ff451cd57771a52f6599