PythonでPDFファイルの読み書きマージやパスワード解除したりする。

# はじめに
PythonのPDF処理ライブラリ```pypdf```についてまとめる。


# 目次
+ [pypdfライブラリ取得](#pypdfライブラリ取得)
+ [PDF読み込みとテキスト出力](#pdf読み込みとテキスト出力)
+ [PDF図の出力](#pdf図の出力)
+ [PDF書き込み](#pdf書き込み)
+ [PDFマージ](#pdfマージ)
+ [PDF分割](#pdf分割)
+ [PDFパスワード解除](#pdfパスワード解除)


## pypdfライブラリ取得
pypdfのライブラリは下記で取得。パスワードがかかっているファイルを復号化する場合は```pypdf[crypto]```も必要。
```cmd:
$ pip install pypdf
$ pip install pypdf[crypto]
```

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

[戻る](#目次)

## PDF読み込みとテキスト出力
PDFファイルは```pypdf.PdfReader()```で読み出す。テキスト出力はページを指定して```.extract_text()```でできる。スライスを使えないので複数ページ出力したい場合は、```for```等で出力する必要がある。
コマンド|内容
--|--
pdf = pypdf.PdfReader('ファイル名')|ファイルを読み出しpdfへ出力
len(pdf.pages)|ページ数
pdf.pages[0].extract_text()|1ページ目をテキスト出力

```python:
import pypdf

# pdf読み出し
in_file = input('PDFファイル名：')
pdf = pypdf.PdfReader(in_file)

# ページ数読み出し
print(f'# {len(pdf.pages)=}')

# 1ページ目読み出し
print(pdf.pages[0].extract_text())

# 全ぺージ読み出し
for i in pdf.pages:
	print(i.extract_text())
```

[戻る](#目次)

## PDF図の出力
PDFの図の出力は```.images```で取り出せる。

下記は、```./fig```フォルダに図を保存する例。図名は、ページごとに被る可能性があるので```cnt```をファイル名に付けて保存している。

```python:
import pypdf
import os

# pdf読み出し
in_file = input('PDFファイル名：')
pdf = pypdf.PdfReader(in_file)


# 図の格納フォルダ作成
if not os.path.isdir('fig'):
	os.mkdir('fig')
cnt=0
for page in pdf.pages:
	#各ページ内の図を取り出し、ファイルとして保存する。
	for image in page.images:
		print(f'{cnt:04d}_{image.name},{image}')
		
		with open(f'fig/{cnt:04d}_{image.name}', 'wb') as f:
			f.write(image.data)
		cnt=cnt+1

# print(f'{cnt:04d}_{image.name},{image}')
# 0000_Im0.jpg,ImageFile(name=Im0.jpg, data: 28.5 kB)
```

[戻る](#目次)

## PDF書き込み

コマンド|内容
--|--
pdf = pypdf.PdfWriter()|PDF生成
pdf.clone_reader_document_root()|特定のPDFを先頭からコピーしてクローンを作る
pdf.add_page()|pdfを1ページ追加
pdf.write('出力ファイル名.pdf')|ファイルとして書き出し


```python:ファイルをクローン
import pypdf

# PDF生成
new_pdf = pypdf.PdfWriter()

# あるPDF読み出し
in_file = input('PDFファイル名：')
pdf = pypdf.PdfReader(in_file)

# クローン生成
new_pdf.clone_reader_document_root(pdf)

#ファイル出力
new_pdf.write('出力ファイル名.pdf')
new_pdf.close()
```

```python:特定のページをコピー
import pypdf

# PDF生成
new_pdf = pypdf.PdfWriter()

# あるPDF読み出し
in_file = input('PDFファイル名：')
pdf = pypdf.PdfReader(in_file)

#6ページ目(0オリジン)～最後のページまで抜き出し
for i in pdf.pages[5:]:
	pdf_div.add_page(i)
new_pdf.write('出力ファイル名.pdf')
new_pdf.close()
```
[戻る](#目次)

## PDFマージ
```.append()```と```.merge()```を使えば、PDFファイル全てをマージしたり、特定のページをマージしたりすることができる。
コマンド|内容
--|--
mpdf = pypdf.PdfWriter()|マージ用PDF作成(書き込みと同じ)
mpdf.append('マージファイル名')|ファイルをすべてマージ
mpdf.merge(page, file ,pages=pypdf.PageRange('start:stop:step'))|fileの特定のpageから　start/stop/stepで指定したページを挿入する

```python:PDFマージ
import pypdf

mpdf = pypdf.PdfWriter()
mpdf.append('A.pdf')	#A.pdf全て
mpdf.append('B.pdf')	#B.pdf全て
mpdf.write('AB.pdf')
mpdf.close()
```

```python:PDFをページ指定してマージ
import pypdf

mpdf = pypdf.PdfWriter()
mpdf.append('A.pdf')	#A.pdf全て
mpdf.merge(10,'B.pdf',pages=pypdf.PageRange('0:5'))	#B.pdfの1～5ページを 10ページ目に挿入する
mpdf.write('AB.pdf')
mpdf.close()
```
[戻る](#目次)

## PDF分割
```.append()```を使えば、PDFを分割することもできる。

コマンド|内容
--|--
divpdf = pypdf.PdfWriter()|分割用PDF作成(書き込みと同じ)
divpdf.append(file,pages=pypdf.PageRange('start:stop:step'))|fileをstart/stop/stepで指定したページ抜き出す

```python:PDF分割
import pypdf

div1_pdf = pypdf.PdfWriter()
div2_pdf = pypdf.PdfWriter()
div1_pdf.append('A.pdf',pages=pypdf.PageRange(':5'))	#5ページ目まで
div2_pdf.append('A.pdf',pages=pypdf.PageRange('5:'))	#5ページ以降
div1_pdf.write('A1.pdf')
div2_pdf.write('A2.pdf')
```

[戻る](#目次)

## PDFパスワード解除
```pdf.is_encrypted```でpdfの暗号化状態を確認できる。```True```であれば、パスワードがかかっている。パスワード解除は```pdf.decrypt('パスワード')```でできる。このライブラリでパスワード解読できるわけではないので、パスワードはわかっている必要はある。
下記例は、パスワード解除して、解除したファイルを新たに作成する関数。```def pdf_unlock(in_file, password, out_file):```

```python:
import pypdf

# PDFファイル読み込み
in_file = input('PDFファイル名：')
pdf = pypdf.PdfReader(in_file)
# 暗号状態確認
print(f'# {pdf.is_encrypted=}')

# pdf.is_encrypted=True

#-------------------------------------------
# PDF解除処理
#-------------------------------------------
def pdf_unlock(in_file, password, out_file):
	#PDF読み込み
	pdf = pypdf.PdfReader(in_file)

	#PDFパスワード解除
	pdf.decrypt(password)

	#新PDFファイルを準備
	pdf_unlock = pypdf.PdfWriter()

	#新PDFにコピー
	pdf_unlock.clone_reader_document_root(pdf)

	#パスワード解除された状態でPDF保存
	pdf_unlock.write(out_file)
    pdf_unlock.close()


# PDFファイル読み込み
password = input('PDFのパスワード：')
out_file = 'unlock'+in_file

# PDF解除処理
pdf_unlock(in_file, password, out_file)

```

[戻る](#目次)