Python:コマンドラインで指定したPDFファイル同士を結合させる

Python

コマンドラインから

python mergepdf.py abc.pdf def.pdf outfile.pdf

などと入力すると、abc.pdfdef.pdfを結合したoutfile.pdfを出力してくれるようなスクリプトを紹介します。

動作イメージ

ちなみに今回紹介するスクリプトは、結合元ファイル名を2つ以上指定可能です。
最後に指定したファイル名が結合される出力ファイルとなる仕組みです。

準備

PythonからPDFファイルを扱うことができるpypdfライブラリを利用します。
pipコマンドでインストールしてください。ちなみにpypdfはPyPDF2の後継版です。

pip install pypdf

pypdfの機能のうちPDFを結合させる機能のみ使います。
結合には、pypdfライブラリのPdfMergerオブジェクトを生成して利用する形となります。

コマンドラインで指定したPDFファイルを結合するスクリプト

mergepdf.py

# -*- coding: utf-8 -*-
import os, sys
from pypdf import PdfMerger

# --- PDFファイル結合処理をする関数
def merge_pdf(input_files, output_file):
	# PDF結合用のPdfMergerオブジェクトを生成
	merger = PdfMerger()

	# 結合ファイルをPdfMergerに追加
	for input_file in input_files:
		merger.append(input_file)
		print(" .....{}".format(input_file))

	# 結合ファイル名(出力ファイル名)を指定してPDFファイル生成
	merger.write(output_file)
	merger.close()

	print("{} を出力しました".format(output_file))

if __name__ == "__main__":
	# コマンドライン引数を取得
	args = sys.argv		# コマンドライン引数に指定した文字列
	argc = len(args)	# コマンドライン引数の数

	# 引数に結合する2つのファイル名なければ終了(引数は4つ以上必要)
	if argc < 4:
		print("引数の数が違います\n")
		print("【使い方】python mergepdf.py <FILE1> <FILE2> ... <OUTFILE>")
		sys.exit()

	# 入力ファイル(結合元ファイル名)をリスト(配列)に取り出す
	input_files = args[1:-1]	# 先頭と末尾を除いた要素

	# 出力ファイル(結合ファイル名)を取り出す
	output_file = args[-1]		# 末尾の要素

	# 出力ファイルが存在する場合は、上書き確認する
	if(os.path.exists(output_file)):
		result = input("{} がすでに存在します。上書きしますか?(y/n) ".format(output_file))
		if(result == "y" or result == "Y"):
			merge_pdf(input_files, output_file)	# 結合したPDFファイルを出力
	else:
		merge_pdf(input_files, output_file)		# 結合したPDFファイルを出力

実行方法

例として、abc.pdfdef.pdfの2つのファイルをoutfile.pdfとして結合させたい場合は以下のようにコマンドラインから打ち込みます。

python mergepdf.py abc.pdf def.pdf outfile.pdf

最後に入力したファイル名が結合させて出力されるファイル名(上記例ではoutfile.pdf)となります。
ちなみにコマンドラインに入力したファイル名順(例だと abc.pdf def.pdf の順)に結合されます。
また、同じファイル名をつづけて入力ファイル名として指定した場合は、そのまま同じファイルが結合されます。

実行イメージ

> python mergepdf.py abc.pdf def.pdf outfile.pdf
 .....abc.pdf
 .....def.pdf
outfile.pdf を出力しました

実行イメージ(結合ファイル名が存在する場合)

出力ファイル名と同名のファイルが存在する場合は、上書き確認をします。(ただし、結合元ファイル名の方はチェックしていません)

> python mergepdf.py abc.pdf def.pdf outfile.pdf
outfile.pdf がすでに存在します。上書きしますか?(y/n) y
 .....abc.pdf
 .....abc.pdf
outfile.pdf を出力しました

実行イメージ(引数が少ない場合)

実行には、入力ファイル名2つ、出力ファイル名1つのあわせて3つのファイル名が最低限必要になります。
指定するコマンドライン引数が少ない場合メッセージ使い方を出力して終了します。

> python mergepdf.py abc.pdf outfile.pdf
引数の数が違います

【使い方】python mergepdf.py <FILE1> <FILE2> ... <OUTFILE>

解説

コマンドライン引数取得部分

コマンドライン引数は、sysをインポートし、sys.argvで取得できます。
ファイル名が少ないと結合できないため、コマンドライン引数の数チェック用にargcに引数の数を代入しています。

import sys
	:
	:
# コマンドライン引数を取得
args = sys.argv		# コマンドライン引数に指定した文字列
argc = len(args)	# コマンドライン引数の数

結合には、入力ファイル名と出力ファイル名をそれぞれ分けて取り出す必要があります。
リスト(配列)におけるPythonのスライス記法を使うと入力ファイル名と出力ファイル名は以下のように取り出せます。(入力ファイル名はリスト形式、出力ファイル名は文字列です)

# 入力ファイル(結合元ファイル名)をリスト(配列)に取り出す
input_files = args[1:-1]	# 先頭と末尾を除いた要素

# 出力ファイル(結合ファイル名)を取り出す
output_file = args[-1]		# 末尾の要素

例えば、実行に以下を指定したとします。

python mergepdf.py abc.def def.pdf output.pdf

その際、args(sys.argv)の中身はこうなっています。

args[0] = "mergerpdf.py"	# 利用しない
args[1] = "abc.pdf"		# input_filesに入る
args[2] = "def.pdf"		# input_filesに入る
args[3] = "outfile.pdf"		# output_fileに入る

input_files = args[1:-1] を実行した後の input_files の中身はこうなります。

input_files[0] = "abc.pdf"
input_files[1] = "def.pdf"

output_file = args[-1] を実行した後の output_file の中身はこうです。

output_file = "outfile.pdf"

input_files(リスト)とoutput_file(文字列)は、この後の処理で関数merge_pdf()に引数として受け渡しています。

Pythonリストのスライス記法とは?

[-1]リストの末尾を表します。
したがってargs[-1]末尾の要素を表しますが、args[1:-1]は、args[1]~末尾の手前までという意味になっています。

詳しくは以下のサイトが参考になります。

参考

【Python】スライスの使いかたの基本
スライスは、リストや文字列、タプル等のシーケンス型の一部をインデックスを指定して取り出す操作のことです。うまく使うとリストの要素の反転も簡単に書けます。本記事では、このようなスライス操作の基本について...

PDF結合部分:関数merge_pdf()

PDFファイルの結合部分は、すべて関数merge_pdf()に集約してあります。

def merge_pdf(<入力ファイル(リスト)>, <出力ファイル(文字列変数)>)

PDFファイルの結合には、まずpypdfモジュールのPdfMergerオブジェクトが必要になります。

merger = PdfMerger()

PdfMergerオブジェクトの次のメソッドを順に使ってPDFファイルの結合を行います。

  • append(結合前のファイルを指定)
  • write(結合したファイルの書き出し)
  • close(書き出したファイルを閉じる)

まず、appedメソッドを使って、結合前のPDFファイルを指定します。

例えば、abc.pdfdef.pdfファイルを結合ファイルに指定する場合はこうなります。

merger.append("abc.pdf")
merger.append("def.pdf")

結合後のファイルをoutfile.pdfという名前で保存する場合は、writeメソッドを使います。

merger.write("output.pdf")

最後にcloseメソッドでファイルを閉じて完了となります。

merger.close()

実際のスクリプトでは、入力ファイルはリスト(配列)となっているため、appendの部分は、forループで結合前のファイルを追加しています。

# 結合ファイルをPdfMergerに追加
for input_file in input_files:
	merger.append(input_file)

ファイル上書きチェック部分

PdfMergerオブジェクトのwriteメソッドは既存のファイルを上書きしてしまうため、出力ファイルがすでに存在していないかをチェックしています。

これには、osモジュールのpath.exists()を利用します。
既存のファイルが存在する場合は、上書きするかどうか確認してからmerge_pdf()関数を呼び出すようにして、勝手に上書きしないようにしています。

if(os.path.exists(output_file)):
	result = input("{} がすでに存在します。上書きしますか?(y/n)".format(output_file))
	if(result == "y" or result == "Y"):
		merge_pdf(input_files, output_file)

以上、Python:コマンドラインで指定したPDFファイル同士を結合させるでした。

コメント

タイトルとURLをコピーしました