背景
所属している組織で数十枚のpdf形式のエントリーシート(ES)の黒塗りをする機会がありました。Adobe Acrobatでもpdfの黒塗りは手動できたのですが、黒塗りする箇所はpdfごとに変わらない & 枚数多すぎて手作業でやるのは面倒だったので黒塗り作業をPythonで自動化しました。統一された形式のPDFの特定箇所を黒塗りする需要は他にもありそうな気がしたので、その手順についてここで紹介していきます。
手順
以下でPython3で数枚のPDFの同じ箇所を黒塗りする方法について説明します。
Step1 PyMuPDFをインストール
$ pip3 install PyMuPDF
Step2 pdfの黒塗りしたい箇所の座標を決める
残念ながらPDF上の座標を簡単に取得できるツールはあまりありません。このため、「テキトウに座標を指定」→「黒塗り」を繰り返して座標を特定するのが一番速いかもしれません。
PDFは左上が原点(0,0)となっているはずなので、ページの高さや幅から、大まか座標を推定し、そこから微調整することをお勧めします。なお、座標は以下の形式で指定します。
#黒塗り箇所を2ヶ所指定
#座標形式:(右上のx座標、右上のy座標、左下のx座標、左下のy座標)
redact_coords = [(37,80,550,219),(37,220,289,242)]
Step3 黒塗り関数の定義
import fitz
class Redactor:
def __init__(self, path,outpath,redact_coords):
self.path = path
self.outpath = outpath
self.redact_coords = redact_coords
def redaction(self,page_nums):
# PDF開封
doc = fitz.open(self.path)
# 各ページをiterate
for i,page in enumerate(doc):
if i in page_nums:
areas = [fitz.Rect(coord) for coord in self.redact_coords]
[page.add_redact_annot(area, fill = (0, 0, 0)) for area in areas]
# 黒塗りする
page.apply_redactions()
# 新しいPDFとして保存
doc.save(self.outpath)
print("Successfully redacted")
Step4 1枚のPDFに対して黒塗り関数を実行
# 入力PDF
path = '<入力pdfへのパス>'
# 出力PDF
outpath = '<黒塗り済みpdfの書き出しパス>'
# 黒塗り座標
redact_coords = [(37,80,550,219),(37,220,289,242)]
# 黒塗りページ
pages_to_redact = [0,1]
redactor = Redactor(path,outpath,redact_coords)
redactor.redaction(pages_to_redact)
上のコードでは、test.pdf
というPDFの、0ページ目と1ページ目の両方の(37,80,550,219)
と(37,220,289,242)
が黒塗りされます。
Step5 複数枚のPDFに対して黒塗り関数を実行
directory
変数に黒塗りしたいpdfが入ったフォルダのパスを渡し、あとはfor文で処理します。
import os
import glob
# 黒塗り座標
redact_coords = [(37,80,550,219),(37,220,289,242)]
# 黒塗りページ
pages_to_redact = [0,1]
# 黒塗りしたいpdfが入ってるフォルダの指定
directory = '<pdfファイルが置かれたフォルダへのパス>'
pdf_files = glob.glob(os.path.join(directory, '*.pdf'))
for path in pdf_files:
outpath = f"{path[:-4]}_redacted.pdf"
redactor = Redactor(path,outpath,redact_coords)
redactor.redaction(pages_to_redact)
Step6 複数枚のPDFに対して、ページごとに異なる箇所を黒塗りする
import os
import glob
# 黒塗り座標
redact_coords_list = list(
[(37,80,550,219),(37,220,289,242)], #0ページ目で黒塗りしたい箇所
[(50,80,300,400)] #1,2ページ目で黒塗りしたい箇所
)
# 黒塗りページ
pages_to_redact_list = list(
[0], #0ページ目の指定
[1,2]#1,2ページ目の指定
)
# 黒塗りしたいpdfが入ってるフォルダの指定
directory = '<pdfファイルが置かれたフォルダへのパス>'
pdf_files = glob.glob(os.path.join(directory, '*.pdf'))
for path in pdf_files:
for redact_coords, pages_to_redact in zip(redact_coords_list,pages_to_redact_list):
outpath = f"{path[:-4]}_redacted.pdf"
redactor = Redactor(path,outpath,redact_coords)
redactor.redaction(pages_to_redact)