もくじ
プログラム作成の動機
自分で作成したPDFファイルをホームページにアップする時にメタデータを削除したいと思いプログラムを作りました。プログラム本体ですが、cloneReaderDocumentRoot()ではメタデータはコピーされないことを利用して、メタデータをすべて削除して新規ファイルとして保存します。Producerの項目だけは削除できないようなので、空文字を上書きしています。
私自身が初心者なのでコマンドラインで動かすのではなく、tkinterでウィンドウ表示してPDFファイルを選択、別名で保存できるようにしました。あくまで自分で作ったPDFファイルのメタデータを削除することを目的としているため、他の環境ではエラーが出るかもしれませんが確認はしていません。
できないことやエラー
- 暗号化されたPDFに関すること全般
- WordでPDF変換したファイルの場合、メタデータを完全に削除できない
- ExcelでPDF変換したファイルの場合、別名で保存したファイルが破損している
- PDFによっては、警告が出るが一応メタデータを削除できる。(PdfReadWarning: Xref table not zero-indexed. ID numbers for objects will be corrected.)等
準備
まず、PyPDF2をインストールします。PyPDF2がないと動きません。
pip install PyPDF2
プログラム本体( python3 )
import os
import tkinter.filedialog
import tkinter.messagebox
import PyPDF2
# 余計なウィンドウを表示させなくする
root = tkinter.Tk()
root.withdraw()
# filedialogでPDFファイルを指定
ftype = [('','.pdf')]
# このプログラムがあるディレクトリのパス
initdir = os.path.abspath(os.path.dirname(__file__))
while True:
try:
# PDFファイルを選択
pdf = tkinter.filedialog.askopenfilename(filetypes=ftype, initialdir=initdir)
# PDFファイルからPdfFileReaderオブジェクトを作成
src_pdf = PyPDF2.PdfFileReader(pdf)
# PDFファイルが暗号化されているかチェック
if src_pdf.isEncrypted == False:
# 空のPdfFileWriterオブジェクトを作成
dst_pdf = PyPDF2.PdfFileWriter()
# 元PDFファイルをdst_pdfにコピー
# cloneReaderDocumentRoot()ではメタデータはコピーされない
dst_pdf.cloneReaderDocumentRoot(src_pdf)
# メタデータ編集
dst_pdf.addMetadata({'/Producer': ''})
# 書き込み用ファイル名を指定ダイアログ
tkinter.messagebox.showinfo('INPUT FILE NAME','ファイル名を入力してください')
while True:
# 書き込み用ファイル名を指定
path_dst_pdf = tkinter.filedialog.asksaveasfilename(defaultextension='.pdf', filetypes=ftype)
# 元ファイルと同じディレクトリで同名だと保存できないようにする
if pdf != path_dst_pdf:
break
else:
tkinter.messagebox.showerror('INPUT ANOTHER FILE NAME','元ファイルと別名で保存してください')
# 書き込み用バイナリファイルをオープンして書き込み
with open(path_dst_pdf, 'wb') as f:
dst_pdf.write(f)
break
# PDFファイルが暗号化されていると処理できないのでファイル選択を確認
else:
rty = tkinter.messagebox.askretrycancel('RETRY','暗号化されているため開けません。ファイルを選び直しますか?')
if rty == False:
break
# ファイルを選択orファイル名を入力せず、終了しない場合は繰り返し
except(FileNotFoundError):
stp = tkinter.messagebox.askyesno('CHECK', 'ファイルを選び直しますか?')
if stp == False:
break
# ファイルを選択せず、終了しない場合は繰り返し
except(AttributeError):
stp = tkinter.messagebox.askyesno('CHECK', 'ファイルを選び直しますか?')
if stp == False:
break