LoginSignup
2
1

More than 1 year has passed since last update.

【Python】2つのPDFファイルを交互に結合する

Last updated at Posted at 2021-11-28

はじめに

最近,A3,B4をスキャンできるスキャナを購入したが,
両面同時スキャン対応していなかった (´;ω;`)

両面プリントの束をスキャンするときに,
面倒だが片面ずつスキャンしてPDFファイルをマージする必要がある

10枚の両面プリントをスキャンしたとき(A:表面,B:裏面,数字は枚目)
1回目のスキャンでできたPDF:1A,2A,3A,・・・,10A
2回目のスキャンでできたPDF:1B,2B,3B,・・・,10B

これを,
マージしたPDF:1A,1B,2A,2B,・・・,10A,10B
とする必要がある

プログラム設計

書くべきほどのことではないが,簡単に書くとこんな感じであろう

  • 引数は,結合する2つのファイル名と出力するファイル名
  • 結合する2つのファイルの存在チェック
  • 結合する2つのページ数が同じかチェック
  • 1ページごと交互に新しいファイルに書いていく

PyPDF2

python で PDF ファイルを扱うなら PyPDF2 がよさそうだ

インストールは,conda なら

conda install PyPDF2

PDFファイルのページ数を得る

PdfFileReadergetNumPages を使えばよい
PdfFileReader の生成にはファイル名を渡す

PdfFileReader(stream, strict=True, warndest=None, overwriteWarnings=True)
## stream: Could also be a string representing a path to a PDF file.(抜粋)

getNumPages はただ呼ぶだけでよい

getNumPages()

つまり,これだけでページ数が取得できる

import PyPDF2
reader = PyPDF2.PdfFileReader('src.pdf')
page_num = reader.getNumPages()

PDFファイルの1ページを得る

PdfFileReadergetPage を使えばよい

getPage(pageNumber)

pageNumber は 0始まりだ

つまり,これだけで全ページが取得できる

import PyPDF2
reader = PyPDF2.PdfFileReader('src.pdf')
page_num = reader.getNumPages()
for page_number in range(page_num):
    page = reader.getPage(page_number)

PDFファイルに出力する

PdfFileWriter を生成し,addPage でページを追加,write で PDF へ書き込む

addPagewrite は次のようで

addPage(page)
write(stream)

addPagepage には PdfFileReader.getPage で取得した page を渡す
writestream はファイルオブジェクトを渡す

以下のソースで,src.pdf が dest.pdf にコピーされる

copy_pdf.py
import PyPDF2
reader = PyPDF2.PdfFileReader('src.pdf')
page_num = reader.getNumPages()
writer = PyPDF2.PdfFileWriter()
for page_number in range(page_num):
    page = reader.getPage(page_number)
    writer.addPage(page)
with open('dest.pdf', 'wb') as f:
    writer.write(f)

2つのPDFファイルを交互に結合する

two_file_merge.py
import os
import argparse
import PyPDF2 as pp

# 引数の解析
parser = argparse.ArgumentParser()
parser.add_argument('file1', help='元ファイル1', type=str)
parser.add_argument('file2', help='元ファイル2', type=str)
parser.add_argument('--output', '-o', help='出力ファイル名', type=str, default='output.pdf')
arg = parser.parse_args()

# 引数
file1 = arg.file1
file2 = arg.file2
output = arg.output

# 引数のチェック
if not os.path.exists(file1):
    print(f'{file1}が存在しません')
    quit()
if not os.path.exists(file2):
    print(f'{file2}が存在しません')
    quit()
reader1 = pp.PdfFileReader(file1)
reader2 = pp.PdfFileReader(file2)
if reader1.getNumPages() != reader2.getNumPages():
    print('ページ数が異なります')
    quit()

# 1ページずつ交互に新しいファイルに書き込む
writer = pp.PdfFileWriter()
for page in range(reader1.getNumPages()):
    writer.addPage(reader1.getPage(page))
    writer.addPage(reader2.getPage(page))
with open(output, 'wb') as f:
    writer.write(f)

おわりに

便利だな,PyPDF2
PDFファイルを扱うことが多いので,これから活用していきたい

追記

1回目のスキャンが完了した後,プリントの束をそのままひっくり返してスキャンする
通常このようにスキャンすると思うので,上のコードを修正をする

1回目のスキャンでできたPDF:1A,2A,3A,・・・,10A
2回目のスキャンでできたPDF:10B,9B,8B,・・・,1B
これをマージして,1A,1B,2A,2B,・・・,10A,10Bとしたい

2回目のスキャンファイルは逆順に読む必要がある

two_file_merge_kai.py
import os
import argparse
import PyPDF2 as pp

# 引数の解析
parser = argparse.ArgumentParser()
parser.add_argument('file1', help='元ファイル1', type=str)
parser.add_argument('file2', help='元ファイル2', type=str)
parser.add_argument('--output', '-o', help='出力ファイル名', type=str, default='output.pdf')
arg = parser.parse_args()

# 引数
file1 = arg.file1
file2 = arg.file2
output = arg.output

# 引数のチェック
if not os.path.exists(file1):
    print(f'{file1}が存在しません')
    quit()
if not os.path.exists(file2):
    print(f'{file2}が存在しません')
    quit()
reader1 = pp.PdfFileReader(file1)
reader2 = pp.PdfFileReader(file2)
if reader1.getNumPages() != reader2.getNumPages():
    print('ページ数が異なります')
    quit()

# 1ページずつ交互に新しいファイルに書き込む
writer = pp.PdfFileWriter()
num_pages = reader1.getNumPages()
for page_number in range(num_pages):
    writer.addPage(reader1.getPage(page_number))
    writer.addPage(reader2.getPage(num_pages-1-page_number)) ## 逆順に読む
with open(output, 'wb') as f:
    writer.write(f)
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1