PDF操作の定番であるPyPDF2のモジュールを利用してフォルダ配下のPDFを連結し、pdfrwでページ番号を付与する手順をまとめました。 pdf の連結には関数を定義することで、汎用性のあるコードです。ひとつにまとめたPDFにページ番号を付与し使いやすくしています。 PythonでのPDF操作の参考になれば幸いです。
PyPDF2とpdfrw をインストールする
PDF 連結にはPyPDF2を利用します。
また、ページ番号の付番にはpdfrwを利用します。
いずれも、通常のPIPコマンド pip install PyPDF2
及び
pip install pdfrw
でインストール可能です。
ブログにまとめるにあたり、以下の環境で記事を書いています。
- PyPDF2 3.0.1
- pdfrw 0.4
- python 3.9.13
- Windows 11
PyCharm 2022.3.1 (Community Edition) を利用しています。
完成形のイメージ
このブログで作成するアウトプットの完成形のイメージは以下のとおりです。 2ステップで作成しています。
Input 及び Output file
サンプルコードで連結するpdfファイルは以下のsource
フォルダに存在します。
C:/Users/usr/sample/data/source
連結、ページ番号が付与されたpdfファイル
は以下になります。
C:/Users/usr/sample/data/output/concatenated.pdf
サンプルコード
以下がサンプルコードになります。まず連結部分のサンプルコードをご紹介します。
Python, pypdfでPDFを結合・分割(ファイル全体・個別ページ)を参考に本コードでは本サイトで紹介したPyPDF2を使ったPDFからのテキストファイルの抽出で利用したPyPDF2
使っています。
連結するpdfが置いてあるpdfのフォルダと連結後のpdfの二つを引数とする関数(merge_pdf)は同様です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from PyPDF2 import PdfWriter
from PyPDF2 import PdfReader
import glob
import os
merger = PdfWriter()
def merge_pdf(src_path, dst_file):
lst = glob.glob(os.path.join(src_path, '*.pdf'))
lst.sort()
for p in lst:
merger.append(p)
merger.write(dst_file)
merger.close()
merge_pdf('C://Users//usr//sample//data//source',
'C://Users//usr//sample//data//output//concatenated.pdf')
各ステップの説明
PyPDF2
からPdfWriter
をインポートします。PyPDF2
からPdfReader
をインポートします。glob
をインポートします。os
をインポートします。PdfWriter()
を mergerというオブジェクト名で定義します。- 関数名
merge_pdf
を定義します。引数は2つでsrc_path
が入力となるpdfが格納されているフォルダ名(絶対パスを想定しています)とその出力となる pdf名が引数です。 - リスト型式の変数
lst
にsrc_path
配下の拡張子pdf
のすべてのファイルをglob
で代入します。 - ファイル名を昇順でソートします * 読み込むファイル名を管理しやすいように命名しておくといいですね。
lst
の中身を一つずつ取り出します。取り出すファイルをそれぞれp
としています。merger
オブジェクトで取り出した順にappend
(追加)します。dst_file
という名前でWriteします。- close して終了します。 ここまでが、関数の中身です。
'C://Users//usr//sample//data//source'
と'C://Users//usr//sample//data//output//concatenated.pdf'
を引数としたmerge_pdf
関数を実行し、pdfファイルを連結します。
ページ番号を追加する
ページ番号をフッターに追加するには、pdfrwを利用します。
reportlab-how-to-add-a-footer-to-a-pdf-fileを参考にしています。
アウトプットイメージは以下のとおりです。
サンプルコード
以下がサンプルコードになります。殆どreportlab-how-to-add-a-footer-to-a-pdf-fileのままを載せています。
ページ数を付与するファイルを置いているディレクトリをカレントディレクトリとしているため、ファイル名のみを指定しています。
ステップ1で連結したconcatenated.pdf
をinput_file にしています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from reportlab.pdfgen.canvas import Canvas
from pdfrw import PdfReader
from pdfrw.toreportlab import makerl
from pdfrw.buildxobj import pagexobj
import sys
import os
input_file = "concatenated.pdf"
output_file = "concatenated_pgn.pdf"
# Get pages
reader = PdfReader(input_file)
pages = [pagexobj(p) for p in reader.pages]
# Compose new pdf
canvas = Canvas(output_file)
for page_num, page in enumerate(pages, start=1):
# Add page
canvas.setPageSize((page.BBox[2], page.BBox[3]))
canvas.doForm(makerl(canvas, page))
# Draw footer
footer_text = "Page %s of %s" % (page_num, len(pages))
x = 128
canvas.saveState()
canvas.setStrokeColorRGB(0.941, 0.694, 0.024) # line color : gold
canvas.setFillColorRGB(0.02, 0.412, 0.58) # character color : blue
canvas.setLineWidth(2.0)
canvas.line(66, 78, page.BBox[2] - 66, 78)
canvas.setFont('Helvetica', 10.5)
#canvas.setFont('Times-Roman', 10.5)
canvas.drawString(page.BBox[2]-x, 65, footer_text)
canvas.restoreState()
canvas.showPage()
canvas.save()
[ここがポイント!]
- ディレクトリの指定は
'C://Users//usr//sample//data//source'
のとおり、本環境では//
とスラッシュを重ねないと上手く稼働しませんでした。- 線の色と字の色の指定はRGB(各々0~1までの値)で行っています。
- フォントは、’Helvetica’と’Times-Roman’のいずれかが指定可能です。
参照ページ一覧
このブログを作成するにあたり、以下のページを参考にさせていただきました。併せてご覧ください。
1) Python, pypdfでPDFを結合・分割(ファイル全体・個別ページ)
2) reportlab-how-to-add-a-footer-to-a-pdf-file
3) PyPDF2を使ったPDFからのテキストファイルの抽出