PythonでPDFファイルの文書情報の取得と書き換え

PyPDF2モジュールを使って、PDFファイルの文書情報(メタデータ)を取得したり書き換えたりしてみました。

目次

  1. 文書情報の読み取りの手順
  2. 情報取得に使用するクラスとメソッド
  3. メタ情報の取得例
  4. 文書情報(メタデータ)の削除と書き換え
  5. 書き換えに使用するクラスとメソッド
  6. メタ情報書き換えの実施例

文書情報の読み取りの手順

PDFファイルには、文書として表示される情報の他に文書の著者などの情報(メタデータ)が入っています。こういった情報をPythonのPyPDF2モジュールを使って読み取ってみます。

PDFファイルのメタデータの格納方法は私の知る限りでは3種類あります。

  1. Document Information Dictionary
  2. Metadata stream
  3. Extensible Metadata Platform (XMP)

Extensible Metadata Platform は、PDF 2.0以降で採用された方法です。

ここで読み取るメタデータは、Document Information Dictionary に格納されているデータです。

おおまかな手順は下記です。

  1. PdfFileReaderでファイルを読み取る。
  2. getDocumentInfoメソッドでDocumentInformationクラスのオブジェクトを作る。
  3. DocumentInformationオブジェクトのプロパティにアクセスする。

情報取得に使用するクラスとメソッド

PdfFileReaderクラス

reader = PyPDF2.PdfFileReader(stream, [strict], [warndest], [overwriteWarnings])
名前 内容
stream   PDFファイルのパスを示す文字列、またはreadとseekに対応したオブジェクト。
strict bool 省略可。既定値はTrue。PDFファイルを読み取ったときの警告を表示するかどうか。
warndest   省略可。既定値はsys.stderr。警告の出力先。
overwriteWarnings bool 省略可。既定値はTrue。
reader   PdfFileReaderオブジェクト。

PdfFileReaderオブジェクトを作成します。

getDocumentInfoメソッド

docinfo = reader.getDocumentInfo()
名前 内容
reader   PdfFileReaderオブジェクト。
docinfo   PDFファイルの文書情報を格納したDocumentInformationオブジェクト。

DocumentInformationオブジェクトを作成するメソッドです。Document Information Dictionaryにメタデータが無い場合は、Noneが返ります。

DocumentInformationクラス

下表のプロパティがあります。

プロパティ 内容
author 文書の著者。
author_raw  
creator 文書の作成者。
creator_raw  
producer 文書ファイルの生成ソフトウェア。
producer_raw  
subject 文書の件名。
subject_raw  
title 文書のタイトル。
title_raw  

戻り値の型は、TextStringObjectというUnicode文字列です。プロパティの最後がrawになっているものは、ByteStringObjectが返ってきます。値が設定されていないプロパティを参照した場合は、Noneが返ります。

これらのプロパティは読み込み専用で、プロパティに値をセットすることはできません。値を代入しようとするとエラーになります。

メタ情報の取得例

青空文庫からダウンロードした「こころ」のテキストをワードパッドに貼り付けて、PDFファイルとしてプリントしたものを作ります。このPDFファイルのメタデータを表示してみます。

ちなみに、AcrobatでこのPDFファイルのプロパティを表示させると、こんな感じになっています。

プロパティの表示

では、下記のコードでPDFファイルのプロパティを表示してみましょう。

import PyPDF2

with open('kokoro.pdf', mode='rb') as f:
    reader = PyPDF2.PdfFileReader(f)
    docinfo = reader.getDocumentInfo()
    print(docinfo.title)   # プロパティを指定する方法

    for i in docinfo.keys():
        print(i + '\t' + docinfo[i])  # 全てのプロパティを表示

タイトルを表示した後に、forループを使って全てのプロパティを表示させました。実行すると下記のようになります。

> python pdf_test.py
PdfReadWarning: Superfluous whitespace found in object header b'484' b'0' [pdf.py:1666]
kokoro.rtf
/Author xxxxxx
/CreationDate   D:20200531094652+09'00'
/ModDate        D:20200531094652+09'00'
/Producer       Microsoft: Print To PDF
/Title  kokoro.rtf

Authorのところは、おそらくWindowsのログイン名が入るのではないかと思います。

変換元がワードパッドなので、Titleがrtfファイルのファイル名になっています。

PDFに印刷したので、Print To PDFがProducerになってますね。

文書情報(メタデータ)の削除と書き換え

DocumentInformationオブジェクトのプロパティは読み込み専用なので、ダイレクトに書き換えはできません。しかし、新しく値をセットすることはできます。

そこで、メタデータをいったん削除してから新しく書き込むことで、書き換えを実現してみます。

DocumentInformationは辞書なので、popやdelでアイテムの削除ができます。

上でメタデータを読み取ったPDFファイルから、Producerを削除して、Authoerをfooに書き換えてみます。

書き換えに使用するクラスとメソッド

PdfFileWriterクラス

writer = PyPDF2.PdfFileWriter()
名前 内容
writer   PdfFileWriterオブジェクト。

PdfFileWiterクラスは、ページオブジェクトをPDFファイルに書き込むためのクラスです。

cloneReaderDocumentRootメソッド

writer.cloneReaderDocumentRoot(reader)
名前 内容
writer   PdfFileWriterオブジェクト。
reader   コピー元となるPdfFileReaderオブジェクト。

PdfFileWriterオブジェクトにPdfFileReaderオブジェクトのドキュメントルートをコピーするメソッドです。

addMetadataメソッド

writer.addMetadata(infos)
名前 内容
writer   PdfFileWriterオブジェクト。
infos dict メタデータのフィールド名をキーにした辞書。

PdfFileWriterオブジェクトにメタデータを書き込むメソッドです。引数はメタデータの辞書です。

writeメソッド

writer.write(stream)
名前 内容
writer   PdfFileWriterオブジェクト。
stream   ファイルオブジェクト、またはwriteとtellに対応したオブジェクト。

ファイルオブジェクトに書き込みをします。withおよびopenと共に使うのが良いでしょう。

メタ情報書き換えの実施例

では下記のコードで試してみます。

import PyPDF2

reader = PyPDF2.PdfFileReader('kokoro.pdf', strict=False)
docinfo = reader.getDocumentInfo()

# 元ファイルのメタデータの表示
for i in docinfo.keys():
    print(i + '\t' + docinfo[i])

# メタデータを新しい辞書にコピー
modified_info = {k: docinfo[k] for k in docinfo.keys()}

# 書き出し用オブジェクトを生成して本体データをコピー
writer = PyPDF2.PdfFileWriter()
writer.cloneReaderDocumentRoot(reader)

# 辞書を加工してメタデータを書き込み
modified_info.pop('/Producer')
modified_info['/Author'] = 'foo'
writer.addMetadata(modified_info)
print('Modified meta data :')
for i in modified_info.keys():
    print(i + '\t' + modified_info[i])

# PDFファイル出力
with open('out.pdf', mode='wb') as f:
    writer.write(f)

出力はこうなります。

> python pdf_test.py
/Author xxxxxx
/CreationDate   D:20200531094652+09'00'
/ModDate        D:20200531094652+09'00'
/Producer       Microsoft: Print To PDF
/Title  kokoro.rtf
Modified meta data :
/Author foo
/CreationDate   D:20200531094652+09'00'
/ModDate        D:20200531094652+09'00'
/Title  kokoro.rtf

出力されたPDFファイルのプロパティをAcrobatで表示してみるとこうなります。

書き換え後のプロパティ

Authorは書き換わりました。

Titleは最初のままですね。

Producerは削除したのですが、PyPDF2になっています。Producerの指定をしないとPyPDF2が自動的に書き込まれるようですね。Producerを書き込まないようにしたい場合は、Producerを削除するのではなく、Producerに空の文字列を指定するとPyPDF2と書き込まれなくなります。

広告

PythonとPDFカテゴリの投稿