LoginSignup
6
6

【メモ書き】無数のPDFをPythonで黒塗りする

Last updated at Posted at 2023-05-29

背景

所属している組織で数十枚の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)
6
6
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
6
6