PythonでPDFを操作する方法

PythonでPDFを操作する方法

Portable Document FormatまたはPDFは、オペレーティングシステム間でドキュメントを確実に表示および交換するために使用できるファイル形式です。 PDFはもともとAdobeによって発明されましたが、現在は国際標準化機構(ISO)によって管理されているhttps://www.iso.org/standard/51502.html [オープンスタンダード]です。 + PyPDF2 + パッケージを使用して、Pythonで既存のPDFを操作できます。

`+ PyPDF2 +`はhttps://stackoverflow.com/questions/45976946/what-is-pure-python[pure-Python]パッケージであり、さまざまな種類のPDF操作に使用できます。

この記事の終わりまでに、次の方法を理解できます。

  • PythonでPDFからドキュメント情報を抽出する

  • ページを回転させる

  • PDFを結合する

  • PDFを分割する

  • 透かしを追加

  • PDFを暗号化する

始めましょう!

*無料ボーナス:*リンク:[Python Tricks:The Book]の章にアクセスするには、ここをクリックして、Pythonのベストプラクティスを簡単な例とともに示します。すぐに適用して、より美しい+ Pythonコードを記述できます。

「+ pyPdf 」、「 PyPDF2 」、および「 PyPDF4 +」の歴史

オリジナルのhttps://pypi.org/project/pyPdf/[+ pyPdf +]パッケージは2005年にリリースされました。 + pyPdf +`の最後の公式リリースは2010年でした。 約1年が経過した後、http://phaseit.net/[Phasit]という会社がhttps://pythonhosted.org/PyPDF2/[+ PyPDF2 `]という ` pyPdf +`のフォークを後援しました。 コードはオリジナルと後方互換性があるように書かれており、最後のリリースは2016年で、数年間非常によく機能しました。

+ PyPDF3 +と呼ばれるパッケージの短い一連のリリースがあり、その後プロジェクトの名前がhttps://pypi.org/project/PyPDF2/[ + PyPDF4 +]。 これらのプロジェクトはすべてほぼ同じことを行いますが、 + pyPdf +`とPyPDF2 +の最大の違いは、後者のバージョンがPython 3サポートを追加したことです。 オリジナルのhttp://github.com/mfenniak/pyPdf/tree/py3 [+ pyPdf +` for Python 3]とは異なるPython 3フォークがありますが、それは長年維持されていません。

「+ PyPDF2 」は最近廃止されましたが、新しいhttps://github.com/claird/PyPDF4 [` PyPDF4 `]には ` PyPDF2 `との完全な後方互換性がありません。 この記事の例の大部分は ` PyPDF4 `で完全に機能しますが、そうでないものもあります。そのため、この記事では ` PyPDF4 `をあまり取り上げません。 ` PyPDF2 `のインポートを ` PyPDF4 +`と入れ替えて、それがどのように機能するかを確認してください。

+ pdfrw +:代替

Patrick Maupinは、https://github.com/pmaupin/pdfrw [+ pdfrw +]というパッケージを作成しました。このパッケージは、 `+ PyPDF2 `と同じことの多くを実行できます。 この記事で ` PyPDF2 `の実行方法を学習するのと同じ種類のタスクのすべてに ` pdfrw +`を使用できますが、暗号化の顕著な例外があります。

`+ pdfrw +`の最大の違いは、https://www.reportlab.com/[ReportLab]パッケージと統合されているため、既存のPDFを取得して、一部またはすべてを使用してReportLabで新しいPDFを作成できることです。既存のPDFの。

インストール

通常のPythonの代わりにAnacondaを使用している場合は、 `+ PyPDF2 `を ` pip `または ` conda +`でインストールできます。

以下に、 `+ pip `で ` PyPDF2 +`をインストールする方法を示します。

$ pip install pypdf2

`+ PyPDF2 +`には依存関係がないため、インストールは非常に高速です。 パッケージをダウンロードする時間は、インストールする時間と同じくらいかかります。

次に、PDFから情報を抽出する方法を学びましょう。

PythonでPDFからドキュメント情報を抽出する方法

`+ PyPDF2 +`を使用して、PDFからメタデータと一部のテキストを抽出できます。 これは、既存のPDFファイルで特定の種類の自動化を行う場合に役立ちます。

以下は、抽出可能な現在のタイプのデータです。

  • 著者

  • クリエイター

  • プロデューサー

  • 件名

  • タイトル

  • ページ数

この例で使用するPDFを見つける必要があります。 マシンで手元にあるPDFを使用できます。 物事を簡単にするために、https://leanpub.com/reportlab [Leanpub]にアクセスし、この演習用に私の本のサンプルを入手しました。 ダウンロードするサンプルは「+ reportlab-sample.pdf +」と呼ばれます。

そのPDFを使用してコードを記述し、これらの属性にアクセスする方法を学びましょう。

# extract_doc_info.py

from PyPDF2 import PdfFileReader

def extract_information(pdf_path):
    with open(pdf_path, 'rb') as f:
        pdf = PdfFileReader(f)
        information = pdf.getDocumentInfo()
        number_of_pages = pdf.getNumPages()

    txt = f"""
    Information about {pdf_path}:

    Author: {information.author}
    Creator: {information.creator}
    Producer: {information.producer}
    Subject: {information.subject}
    Title: {information.title}
    Number of pages: {number_of_pages}
    """

    print(txt)
    return information

if __name__ == '__main__':
    path = 'reportlab-sample.pdf'
    extract_information(path)

ここでは、 `+ PyPDF2 `パッケージから ` PdfFileReader `をインポートします。 ` PdfFileReader `は、PDFファイルとやり取りするためのいくつかのメソッドを持つクラスです。 この例では、 ` .getDocumentInfo()`を呼び出して、 ` DocumentInformation `のインスタンスを返します。 これには、興味のある情報のほとんどが含まれています。 また、リーダーオブジェクトで ` .getNumPages()+`を呼び出します。これは、ドキュメント内のページ数を返します。

*注意:*最後のコードブロックは、文字列の書式設定にPython 3の新しいf-stringを使用します。 詳細については、https://realpython.com/python-f-strings/[Python 3のf-Strings:改良された文字列フォーマット構文(ガイド)]をご覧ください。

`+ information +`変数には、ドキュメントから必要な残りのメタデータを取得するために使用できるいくつかのインスタンス属性があります。 その情報を印刷し、将来の使用に備えてそれを返します。

+ PyPDF2 +`にはページオブジェクトで使用できる `+ .extractText()+`がありますが(この例には示されていません)、うまく機能しません。 一部のPDFはテキストを返し、一部のPDFは空の文字列を返します。 PDFからテキストを抽出する場合は、代わりにhttps://github.com/euske/pdfminer [+ PDFMiner `]プロジェクトをチェックアウトする必要があります。 *` PDFMiner +`* ははるかに堅牢で、PDFからテキストを抽出するために特別に設計されました。

これで、PDFページの回転について学ぶ準備ができました。

ページを回転させる方法

時折、ポートレートモードではなくhttps://techterms.com/definition/pageorientation[landscape mode]にあるページを含むPDFを受け取ることがあります。 または、逆さまになっている可能性もあります。 これは、誰かがドキュメントをスキャンしてPDFまたは電子メールに送信するときに発生する可能性があります。 ドキュメントを印刷して紙版を読むか、Pythonの力を使用して問題のあるページを回転させることができます。

この例では、実際のP​​ython articleを選択してPDFに印刷できます。

その記事のいくつかのページを `+ PyPDF2 +`で回転させる方法を学びましょう:

# rotate_pages.py

from PyPDF2 import PdfFileReader, PdfFileWriter

def rotate_pages(pdf_path):
    pdf_writer = PdfFileWriter()
    pdf_reader = PdfFileReader(path)
    # Rotate page 90 degrees to the right
    page_1 = pdf_reader.getPage(0).rotateClockwise(90)
    pdf_writer.addPage(page_1)
    # Rotate page 90 degrees to the left
    page_2 = pdf_reader.getPage(1).rotateCounterClockwise(90)
    pdf_writer.addPage(page_2)
    # Add a page in normal orientation
    pdf_writer.addPage(pdf_reader.getPage(2))

    with open('rotate_pages.pdf', 'wb') as fh:
        pdf_writer.write(fh)

if __name__ == '__main__':
    path = 'Jupyter_Notebook_An_Introduction.pdf'
    rotate_pages(path)

この例では、新しいPDFを書き出す必要があるため、「+ PdfFileReader 」に加えて「 PdfFileWriter 」をインポートする必要があります。 ` rotate_pages()`は、修正したいPDFへのパスを取り込みます。 その関数内で、 ` pdf_writer `という名前のライターオブジェクトと ` pdf_reader +`というリーダーオブジェクトを作成する必要があります。

次に、 `+ .GetPage()`を使用して目的のページを取得できます。 ここでは、最初のページであるページゼロを取得します。 次に、ページオブジェクトの ` .rotateClockwise()`メソッドを呼び出し、90度で渡します。 次に2ページ目で、 ` .rotateCounterClockwise()+`を呼び出して、90度も渡します。

*注意: *`+ PyPDF2 `パッケージでは、ページを90度単位でしか回転できません。 そうでなければ、 ` AssertionError +`を受け取ります。

回転メソッドを呼び出すたびに、 `+ .addPage()+`を呼び出します。 これにより、ページの回転バージョンがライターオブジェクトに追加されます。 ライターオブジェクトに追加する最後のページは、ページ3で、回転は行われていません。

最後に、 `+ .write()+`を使用して新しいPDFを書き出します。 file-like objectをパラメーターとして受け取ります。 この新しいPDFには3つのページが含まれます。 最初の2つは互いに反対方向に回転し、横向きになりますが、3番目のページは通常のページです。

それでは、複数のPDFを1つにマージする方法を学びましょう。

PDFを結合する方法

2つ以上のPDFを取得し、それらを1つのPDFにマージする場合が多くあります。 たとえば、多くの種類のレポートに進む必要がある標準のカバーページがあるとします。 Pythonを使用して、そのようなことを行うことができます。

この例では、PDFを開き、ページを個別のPDFとして印刷できます。 その後、別のページを使用して再度実行します。 これにより、例として使用するための入力がいくつか得られます。

先に進んで、PDFを結合するために使用できるコードを作成しましょう。

# pdf_merging.py

from PyPDF2 import PdfFileReader, PdfFileWriter

def merge_pdfs(paths, output):
    pdf_writer = PdfFileWriter()

    for path in paths:
        pdf_reader = PdfFileReader(path)
        for page in range(pdf_reader.getNumPages()):
            # Add each page to the writer object
            pdf_writer.addPage(pdf_reader.getPage(page))

    # Write out the merged PDF
    with open(output, 'wb') as out:
        pdf_writer.write(out)

if __name__ == '__main__':
    paths = ['document1.pdf', 'document2.pdf']
    merge_pdfs(paths, output='merged.pdf')

一緒にマージしたいPDFのリストがある場合、 `+ merge_pdfs()+`を使用できます。 また、結果を保存する場所を知る必要があるため、この関数は入力パスと出力パスのリストを取得します。

次に、入力をループ処理し、入力ごとにPDFリーダーオブジェクトを作成します。 次に、PDFファイル内のすべてのページを反復処理し、 `+ .addPage()+`を使用してそれらの各ページを自分自身に追加します。

リスト内のすべてのPDFのすべてのページを繰り返し処理し終わったら、最後に結果を書き出します。

私が指摘したい項目の1つは、各PDFのすべてのページをマージしたくない場合に、追加するページの範囲を追加することにより、このスクリプトを少し強化できることです。 チャレンジが必要な場合は、Pythonのhttps://docs.python.org/3/library/argparse.html [+ argparse +]モジュールを使用して、この関数のコマンドラインインターフェースを作成することもできます。

マージの反対を行う方法を見つけましょう!

PDFを分割する方法

PDFを複数のPDFに分割する必要がある場合があります。 これは、スキャンされたコンテンツを多く含むPDFに特に当てはまりますが、PDFを分割したい理由はたくさんあります。

「+ PyPDF2 +」を使用してPDFを複数のファイルに分割する方法は次のとおりです。

# pdf_splitting.py

from PyPDF2 import PdfFileReader, PdfFileWriter

def split(path, name_of_split):
    pdf = PdfFileReader(path)
    for page in range(pdf.getNumPages()):
        pdf_writer = PdfFileWriter()
        pdf_writer.addPage(pdf.getPage(page))

        output = f'{name_of_split}{page}.pdf'
        with open(output, 'wb') as output_pdf:
            pdf_writer.write(output_pdf)

if __name__ == '__main__':
    path = 'Jupyter_Notebook_An_Introduction.pdf'
    split(path, 'jupyter_page')

この例では、もう一度PDFリーダーオブジェクトを作成し、そのページをループします。 PDFの各ページに対して、新しいPDFライターインスタンスを作成し、1つのページを追加します。 次に、そのページを一意の名前のファイルに書き込みます。 スクリプトの実行が終了したら、元のPDFの各ページを個別のPDFに分割する必要があります。

ここで、PDFに透かしを追加する方法を少し見てみましょう。

透かしを追加する方法

透かしは、印刷文書やデジタル文書の画像またはパターンを識別します。 一部の透かしは、特殊な照明条件でのみ見ることができます。 透かしが重要な理由は、画像やPDFなどの知的財産を保護できるためです。 透かしの別の用語はオーバーレイです。

Pythonと `+ PyPDF2 +`を使用して、ドキュメントに透かしを入れることができます。 透かし画像またはテキストのみを含むPDFが必要です。

透かしを追加する方法を学びましょう。

# pdf_watermarker.py

from PyPDF2 import PdfFileWriter, PdfFileReader

def create_watermark(input_pdf, output, watermark):
    watermark_obj = PdfFileReader(watermark)
    watermark_page = watermark_obj.getPage(0)

    pdf_reader = PdfFileReader(input_pdf)
    pdf_writer = PdfFileWriter()

    # Watermark all the pages
    for page in range(pdf_reader.getNumPages()):
        page = pdf_reader.getPage(page)
        page.mergePage(watermark_page)
        pdf_writer.addPage(page)

    with open(output, 'wb') as out:
        pdf_writer.write(out)

if __name__ == '__main__':
    create_watermark(
        input_pdf='Jupyter_Notebook_An_Introduction.pdf',
        output='watermarked_notebook.pdf',
        watermark='watermark.pdf')

`+ create_watermark()+`は3つの引数を受け入れます:

* + input_pdf +:*透かしを入れるPDFファイルのパス
  1. * + output +:*透かし入りバージョンのPDFを保存するパス

  2. * + watermark +:*透かし画像またはテキストを含むPDF

このコードでは、ウォーターマークPDFを開き、ドキュメントの最初のページだけを取得します。これは、ウォーターマークが存在する場所です。 次に、 `+ input_pdf `と汎用の ` pdf_writer +`オブジェクトを使用して、透かし入りPDFを書き込むPDFリーダーオブジェクトを作成します。

次のステップは、 `+ input_pdf `のページを反復処理することです。 これが魔法が起こるところです。 ` .mergePage()`を呼び出して、 ` watermark_page `を渡す必要があります。 これを行うと、現在のページの上部に ` watermark_page `がオーバーレイされます。 次に、新しくマージしたページを ` pdf_writer +`オブジェクトに追加します。

最後に、新しく透かしを入れたPDFをディスクに書き込み、完了です!

最後に学習するトピックは、「+ PyPDF2 +」が暗号化を処理する方法です。

PDFを暗号化する方法

`+ PyPDF2 +`は現在、既存のPDFへのユーザーパスワードと所有者パスワードの追加のみをサポートしています。 PDFの土地では、所有者パスワードにより、基本的にPDFに対する管理者権限が与えられ、ドキュメントに権限を設定できます。 一方、ユーザーパスワードでは、ドキュメントを開くことができます。

私が知る限り、「+ PyPDF2 +」では、所有者のパスワードを設定することはできますが、実際にはドキュメントに権限を設定することはできません。

とにかく、これはパスワードを追加する方法です。これにより、本質的にPDFも暗号化されます。

# pdf_encrypt.py

from PyPDF2 import PdfFileWriter, PdfFileReader

def add_encryption(input_pdf, output_pdf, password):
    pdf_writer = PdfFileWriter()
    pdf_reader = PdfFileReader(input_pdf)

    for page in range(pdf_reader.getNumPages()):
        pdf_writer.addPage(pdf_reader.getPage(page))

    pdf_writer.encrypt(user_pwd=password, owner_pwd=None,
                       use_128bit=True)

    with open(output_pdf, 'wb') as fh:
        pdf_writer.write(fh)

if __name__ == '__main__':
    add_encryption(input_pdf='reportlab-sample.pdf',
                   output_pdf='reportlab-encrypted.pdf',
                   password='twofish')

`+ add_encryption()+`は、PDFに追加するパスワードだけでなく、入力および出力PDFのパスを取り込みます。 次に、以前と同様にPDFライターとリーダーオブジェクトを開きます。 入力PDF全体を暗号化する必要があるため、すべてのページをループしてライターに追加する必要があります。

最後のステップは、 `+ .encrypt()`を呼び出すことです。これは、ユーザーパスワード、所有者パスワード、および128ビット暗号化を追加するかどうかを受け取ります。 デフォルトでは、128ビット暗号化が有効になっています。 「 False +」に設定すると、代わりに40ビット暗号化が適用されます。

注意: PDF暗号化では、RC4またはAES(Advanced Encryption Standard)を使用して、https://www.pdflib.com/pdf-knowledge-base/pdf-password-security/encryption/[pdflib.comに従ってPDFを暗号化します。 ]。

PDFを暗号化したからといって、必ずしも安全であるとは限りません。 PDFからパスワードを削除するツールがあります。 詳細については、カーネギーメロン大学に興味深いhttps://www.cs.cmu.edu/~dst/Adobe/Gallery/PDFsecurity.pdf [トピックに関する論文]があります。

結論

`+ PyPDF2 `パッケージは非常に便利で、通常はかなり高速です。 「 PyPDF2 +」を使用して大規模なジョブを自動化し、その機能を活用して仕事を改善することができます!

このチュートリアルでは、次のことを行う方法を学びました。

  • PDFからメタデータを抽出する

  • ページを回転させる

  • PDFの結合と分割

  • 透かしを追加

  • 暗号化を追加

また、新しい + PyPDF4 +`パッケージは、間もなく `+ PyPDF2 +`に置き換わる可能性が高いため、注意してください。 また、https://github.com/pmaupin/pdfrw [+ pdfrw `]をチェックアウトすることもできます。これにより、 ` PyPDF2 +`と同じことができるようになります。

参考文献

PythonでPDFを操作する方法について詳しく知りたい場合は、次のリソースで詳細を確認してください。