【2025年版】pypdf実践:PDFの結合・分割、ページ操作でドキュメントを効率化する

手作業のPDF編集に終止符を!Pythonでドキュメント管理を自動化する

日々の業務でPDFファイルを扱う際、こんな経験はありませんか?

  • 複数のPDFレポートを一つにまとめるために、手作業で結合ツールをポチポチ…
  • 分厚いPDF資料から必要なページだけを抜き出すのに、毎回コピー&ペースト…
  • 社外秘の資料に「社外秘」の透かしを入れる作業が、地味に面倒…

これらの作業、一つ一つは些細なものかもしれませんが、積み重なると膨大な時間と労力を消費します。特に、定期的に発生するドキュメント管理業務では、その非効率性が顕著に現れるでしょう。

「もっとスマートに、もっと効率的にPDFを扱いたい!」

そう願うあなたに朗報です。Pythonの強力なPDFライブラリ「pypdf」(またはその後継であるpypdf)を使えば、これらの煩雑なPDF操作をコードで自動化し、ドキュメント管理の効率を劇的に向上させることができます。

本記事は、前回の記事pypdf入門:PythonでPDFの基本操作とテキスト抽出をマスターする」pypdfの基本を学んだ方を対象に、さらに一歩踏み込んだ実践的なPDF操作テクニックを解説します。PDFの結合、分割、そしてページ単位での詳細な操作まで、具体的なコード例を交えながら、あなたのドキュメント管理を自動化する道筋を示します。

この記事を読み終える頃には、あなたは手作業でのPDF編集から解放され、Pythonの力でドキュメントを自在に操るスキルを身につけていることでしょう。さあ、pypdfを使ったPDF自動化の世界へ飛び込みましょう!


対象読者

  • PythonでPDFファイルの結合、分割、ページ操作を自動化したい開発者
  • pypdf(またはpypdf)の基本的な使い方を理解しているエンジニア
  • ドキュメント管理の効率化に課題を感じているビジネスパーソン

動作検証環境

この記事で紹介するPythonを使ったPDF動作は、以下の環境で検証しています。

  • OS : macOS Tahoe Version 26.0
  • ハードウェア : MacBook Air 2024 M3 24GB
  • uv : 0.8.22 (ade2bdbd2 2025-09-23)
  • python : 3.13.7
  • pypdf : 6.1.1

目次

  1. pypdfでPDFを結合する
    • 複数のPDFファイルを結合する基本
    • 結合時のページの順序制御
  2. pypdfでPDFを分割する
    • 単一PDFを複数ファイルに分割
    • 特定のページ範囲を抽出して新しいPDFを作成
  3. PDFのページを操作する
    • ページの削除
    • ページの並べ替え
    • 透かし(ウォーターマーク)の追加
  4. 実践例:レポートの自動生成と整理
  5. まとめ:pypdfによるPDFドキュメントの効率的な管理
  6. FAQ
    • Q1: PyPDF2とpypdfの違いは何ですか?どちらを使うべきですか?
    • Q2: 大量のPDFファイルを結合・分割する際のパフォーマンスが心配です。何か対策はありますか?
    • Q3: 暗号化されたPDFやパスワード保護されたPDFを結合・分割できますか?
    • Q4: 透かし(ウォーターマーク)の画像はどのように用意すれば良いですか?
  7. 参考文献
  8. 免責事項

1. pypdfでPDFを結合する

複数のPDFファイルを一つにまとめる作業は、レポート作成や資料整理において頻繁に発生します。pypdfを使えば、この作業を驚くほど簡単かつ柔軟に自動化できます。


複数のPDFファイルを結合する基本

まずは、最も基本的なPDFファイルの結合方法を見ていきましょう。PdfWriterオブジェクトを使用します。

from pypdf import PdfWriter


def merge_pdfs(input_paths: list[str], output_path: str) -> None:
    """
    複数のPDFファイルを結合し、新しいPDFファイルとして保存する。

    Args:
        input_paths (list): 結合するPDFファイルのパスのリスト。
        output_path (str): 結合後のPDFファイルの保存パス。
    """
    writer = PdfWriter()
    for pdf_path in input_paths:
        writer.append(pdf_path)
    _ = writer.write(output_path)
    writer.close()
    print(f"PDFファイルを結合しました: {output_path}")


if __name__ == "__main__":
    # サンプルPDFファイルを作成(実際には既存のPDFファイルを使用)
    # NOTE: このコードは`pypdf`の機能を示すためのものであり、
    # 実際のPDFファイル生成はReportLabなどのライブラリが適しています。
    # ここでは、結合・分割のテスト用にダミーファイルを作成します。
    from pypdf import PdfWriter, PdfReader

    writer1 = PdfWriter()
    _ = writer1.add_blank_page(width=72 * 8.5, height=72 * 11)
    _ = writer1.add_blank_page(width=72 * 8.5, height=72 * 11)
    with open("sample1.pdf", "wb") as fp:
        _ = writer1.write(fp)

    writer2 = PdfWriter()
    _ = writer2.add_blank_page(width=72 * 8.5, height=72 * 11)
    with open("sample2.pdf", "wb") as fp:
        _ = writer2.write(fp)

    input_files = ["sample1.pdf", "sample2.pdf"]
    output_file = "merged_document.pdf"
    merge_pdfs(input_files, output_file)

    # 結合されたPDFのページ数を確認
    reader = PdfReader(output_file)
    print(f"結合後のPDFのページ数: {len(reader.pages)}")

上記のコードでは、PdfWriterappend()メソッドを使って、結合したいPDFファイルを次々と追加していきます。最後にwrite()で結合されたPDFを新しいファイルとして出力します。


結合時のページの順序制御

append()メソッドは、単にPDFファイル全体を追加するだけでなく、特定のページ範囲を指定して結合することも可能です。これにより、結合時のページの順序を細かく制御できます。

from collections.abc import Sequence
from pypdf import PdfWriter


def merge_pdfs_with_page_selection(
    input_paths_and_pages: Sequence[tuple[str, tuple[int, int] | None]],
    output_path: str,
) -> None:
    """
    複数のPDFファイルから特定のページを選択して結合し、新しいPDFファイルとして保存する。

    Args:
        input_paths_and_pages (list): (PDFファイルのパス, ページ範囲のタプル) のリスト。
                                      ページ範囲は (開始ページ, 終了ページ) で指定。
                                      例: [("file1.pdf", (0, 2)), ("file2.pdf", (1, 3))]
                                      終了ページは含まれない(Pythonのスライスと同様)。
        output_path (str): 結合後のPDFファイルの保存パス。
    """
    writer = PdfWriter()
    for pdf_path, page_range in input_paths_and_pages:
        writer.append(pdf_path, pages=page_range)
    _ = writer.write(output_path)
    writer.close()
    print(f"選択したページを結合しました: {output_path}")


if __name__ == "__main__":
    # sample1.pdf (2ページ), sample2.pdf (1ページ) が存在すると仮定
    # sample1.pdfの1ページ目(インデックス0)とsample2.pdfの全ページを結合
    input_config = [
        (
            "sample1.pdf",
            (0, 1),
        ),  # sample1.pdfの0ページ目から1ページ目まで(1ページ目のみ)
        ("sample2.pdf", None),  # sample2.pdfの全ページ
    ]
    output_file_selective = "merged_selective.pdf"
    merge_pdfs_with_page_selection(input_config, output_file_selective)

    # 結合されたPDFのページ数を確認
    from pypdf import PdfReader

    reader = PdfReader(output_file_selective)
    print(f"選択結合後のPDFのページ数: {len(reader.pages)}")

pages=(start, end)のようにタプルでページ範囲を指定します。startは0始まりのインデックスで、endは含まれません。Noneを指定すると、そのPDFの全ページが対象となります。

[!TIP]
PdfWriterは、insert_page()メソッドを使って、既存のPDFの特定の位置に新しいページを挿入することもできます。より柔軟なドキュメント構築が可能です。

2. pypdfでPDFを分割する

巨大なPDFファイルから必要な情報だけを抜き出したい場合や、一つのPDFを複数の小さなファイルに分けたい場合に、PDFの分割機能は非常に役立ちます。pypdfは、この分割作業も効率的に行えます。


単一PDFを複数ファイルに分割

一つのPDFファイルを、ページごとに複数のファイルに分割する例です。

from pypdf import PdfReader, PdfWriter


def split_pdf_into_pages(input_path: str, output_prefix: str = "page_") -> None:
    """
    単一のPDFファイルをページごとに分割し、個別のPDFファイルとして保存する。

    Args:
        input_path (str): 分割するPDFファイルのパス。
        output_prefix (str): 分割後のファイル名のプレフィックス。
    """
    reader = PdfReader(input_path)
    for i, page in enumerate(reader.pages):
        writer = PdfWriter()
        _ = writer.add_page(page)
        output_path = f"{output_prefix}{i + 1}.pdf"
        with open(output_path, "wb") as fp:
            _ = writer.write(fp)
        print(f"ページ {i + 1} を分割しました: {output_path}")


if __name__ == "__main__":
    # sample1.pdf (2ページ) が存在すると仮定
    split_pdf_into_pages("sample1.pdf", "split_sample1_")

PdfReaderでPDFを読み込み、reader.pagesで各ページにアクセスします。それぞれのページを新しいPdfWriterに追加し、個別のファイルとして保存します。


特定のページ範囲を抽出して新しいPDFを作成

特定のページ範囲だけを抜き出して、新しいPDFファイルを作成することもできます。これは、資料の一部を共有したい場合などに便利です。

from pypdf import PdfReader, PdfWriter


def extract_pages_to_new_pdf(
    input_path: str, output_path: str, start_page: int, end_page: int
) -> None:
    """
    PDFファイルから指定されたページ範囲を抽出し、新しいPDFファイルとして保存する。

    Args:
        input_path (str): 抽出元のPDFファイルのパス。
        output_path (str): 抽出後のPDFファイルの保存パス。
        start_page (int): 抽出を開始するページ番号(1始まり)。
        end_page (int): 抽出を終了するページ番号(1始まり、このページも含む)。
    """
    reader = PdfReader(input_path)
    writer = PdfWriter()

    # ページ番号は1始まりなので、インデックスに変換
    for i in range(start_page - 1, end_page):
        if i < len(reader.pages):
            _ = writer.add_page(reader.pages[i])
        else:
            print(f"警告: 指定されたページ {i + 1} は存在しません。")
            break

    with open(output_path, "wb") as fp:
        _ = writer.write(fp)
    print(f"ページ {start_page} から {end_page} を抽出しました: {output_path}")


if __name__ == "__main__":
    # sample1.pdf (2ページ) が存在すると仮定
    # sample1.pdfの1ページ目のみを抽出
    extract_pages_to_new_pdf("sample1.pdf", "extracted_page1.pdf", 1, 1)

start_pageend_pageは1始まりのページ番号で指定し、内部で0始まりのインデックスに変換して処理しています。


3. PDFのページを操作する

pypdfは、PDFの結合や分割だけでなく、個々のページに対してより詳細な操作を行う機能も提供しています。ここでは、ページの削除、並べ替え、そして透かしの追加方法を見ていきましょう。


ページの削除

不要なページをPDFから削除することができます。

from pypdf import PdfReader, PdfWriter


def remove_pages_from_pdf(
    input_path: str, output_path: str, pages_to_remove: list[int]
) -> None:
    """
    PDFファイルから指定されたページを削除し、新しいPDFファイルとして保存する。

    Args:
        input_path (str): 編集元のPDFファイルのパス。
        output_path (str): 編集後のPDFファイルの保存パス。
        pages_to_remove (list): 削除するページ番号のリスト(1始まり)。
    """
    reader = PdfReader(input_path)
    writer = PdfWriter()

    # 削除するページ番号をセットに変換して高速化
    remove_set = set(p - 1 for p in pages_to_remove)  # 0始まりインデックスに変換

    for i, page in enumerate(reader.pages):
        if i not in remove_set:
            _ = writer.add_page(page)

    with open(output_path, "wb") as fp:
        _ = writer.write(fp)
    print(f"指定されたページを削除しました: {output_path}")


if __name__ == "__main__":
    # サンプルPDFファイルを作成
    writer1 = PdfWriter()
    _ = writer1.add_blank_page(width=72 * 8.5, height=72 * 11)
    _ = writer1.add_blank_page(width=72 * 8.5, height=72 * 11)
    with open("sample1.pdf", "wb") as fp:
        _ = writer1.write(fp)

    # sample1.pdfの2ページ目を削除
    remove_pages_from_pdf("sample1.pdf", "sample1_page1_only.pdf", [2])

    # 処理後のPDFのページ数を確認
    reader = PdfReader("sample1_page1_only.pdf")
    print(f"処理後のPDFのページ数: {len(reader.pages)}")

pages_to_removeで指定されたページ(1始まり)をスキップして、新しいPdfWriterにページを追加することで、実質的にページを削除しています。


ページの並べ替え

PDF内のページの順序を変更することも可能です。

from pypdf import PdfReader, PdfWriter


def reorder_pdf_pages(input_path: str, output_path: str, new_order: list[int]) -> None:
    """
    PDFファイルのページ順序を変更し、新しいPDFファイルとして保存する。

    Args:
        input_path (str): 編集元のPDFファイルのパス。
        output_path (str): 編集後のPDFファイルの保存パス。
        new_order (list): 新しいページ順序を指定する0始まりのインデックスのリスト。
                          例: [2, 0, 1] は元の3ページ目を1ページ目に、1ページ目を2ページ目に、2ページ目を3ページ目にする。
    """
    reader = PdfReader(input_path)
    writer = PdfWriter()

    if len(new_order) != len(reader.pages):
        raise ValueError("新しい順序のリストの長さが元のPDFのページ数と一致しません。")

    for index in new_order:
        if 0 <= index < len(reader.pages):
            _ = writer.add_page(reader.pages[index])
        else:
            raise IndexError(f"無効なページインデックスが指定されました: {index}")

    with open(output_path, "wb") as fp:
        _ = writer.write(fp)
    print(f"ページの順序を変更しました: {output_path}")


if __name__ == "__main__":
    # 3ページのダミーPDFを作成
    writer_reorder = PdfWriter()
    _ = writer_reorder.add_blank_page(width=72 * 8.5, height=72 * 11)  # Page 1
    _ = writer_reorder.add_blank_page(width=72 * 8.5, height=72 * 11)  # Page 2
    _ = writer_reorder.add_blank_page(width=72 * 8.5, height=72 * 11)  # Page 3
    with open("sample_reorder.pdf", "wb") as fp:
        _ = writer_reorder.write(fp)

    # ページ順序を [3ページ目, 1ページ目, 2ページ目] に変更
    reorder_pdf_pages("sample_reorder.pdf", "sample_reordered.pdf", [2, 0, 1])

new_orderリストで、元のPDFの0始まりのページインデックスを指定することで、自由にページの並べ替えが可能です。


透かし(ウォーターマーク)の追加

PDFに透かしを追加することは、ドキュメントの機密性を示すためや、ブランドロゴを埋め込むためによく行われます。pypdfでは、別のPDFファイルを透かしとして重ね合わせることで、この機能を実現します。

from pypdf import PdfReader, PdfWriter


def add_watermark_to_pdf(
    input_path: str, watermark_path: str, output_path: str
) -> None:
    """
    PDFファイルに透かし(ウォーターマーク)を追加し、新しいPDFファイルとして保存する。

    Args:
        input_path (str): 透かしを追加する元のPDFファイルのパス。
        watermark_path (str): 透かしとして使用するPDFファイルのパス(通常は1ページ)。
        output_path (str): 透かしが追加されたPDFファイルの保存パス。
    """
    reader = PdfReader(input_path)
    watermark_reader = PdfReader(watermark_path)
    watermark_page = watermark_reader.pages[0]  # 透かしは通常1ページ目を使用

    writer = PdfWriter()
    for page in reader.pages:
        _ = page.merge_page(watermark_page)  # 各ページに透かしをマージ
        _ = writer.add_page(page)

    with open(output_path, "wb") as fp:
        _ = writer.write(fp)
    print(f"透かしを追加しました: {output_path}")


if __name__ == "__main__":
    # サンプルPDFファイルを作成
    writer1 = PdfWriter()
    _ = writer1.add_blank_page(width=72 * 8.5, height=72 * 11)
    _ = writer1.add_blank_page(width=72 * 8.5, height=72 * 11)
    with open("sample1.pdf", "wb") as fp:
        _ = writer1.write(fp)

    # 透かし用のダミーPDFを作成
    writer_wm = PdfWriter()
    _ = writer_wm.add_blank_page(width=72 * 8.5, height=72 * 11)
    # NOTE: 実際には、透かし用のPDFには「CONFIDENTIAL」などのテキストや画像が描画されている必要があります。
    # ReportLabなどのライブラリで作成するか、既存のPDFを使用してください。
    with open("watermark.pdf", "wb") as fp:
        _ = writer_wm.write(fp)

    # sample1.pdf (2ページ) に透かしを追加
    add_watermark_to_pdf("sample1.pdf", "watermark.pdf", "sample1_watermarked.pdf")

merge_page()メソッドを使って、透かし用のPDFのページを元のPDFの各ページに重ね合わせます。透かし用のPDFは、通常、テキストや画像が配置された1ページのPDFとして作成します。

[!NOTE]
merge_page()は、既存のコンテンツの上に新しいコンテンツを重ねるため、透かしのPDFのコンテンツが元のPDFのコンテンツを隠してしまう可能性があります。透かしの透明度や位置を細かく制御したい場合は、より高度なPDF操作ライブラリ(例: PyMuPDF)や、透かしを生成する際に透明度を設定できるライブラリ(例: ReportLab)と連携することを検討してください。

4. 実践例:レポートの自動生成と整理

これまでに学んだpypdfの機能を組み合わせて、実際の業務シナリオを想定した「レポートの自動生成と整理」のワークフローを構築してみましょう。

例えば、毎月生成される複数の部門別レポート(PDF)を結合し、特定のページを抜き出してサマリーレポートを作成し、さらに機密情報を含むページには透かしを追加するといった一連の作業を自動化できます。

import os
from pypdf import PdfReader, PdfWriter


def automate_report_management(
    department_reports_dir: str,
    summary_output_path: str,
    confidential_output_path: str,
    watermark_path: str,
) -> None:
    """
    部門別レポートの結合、サマリー抽出、機密ページへの透かし追加を自動化する。

    Args:
        department_reports_dir (str): 部門別レポートPDFが格納されているディレクトリのパス。
        summary_output_path (str): サマリーレポートの出力パス。
        confidential_output_path (str): 機密情報を含むレポートの出力パス(透かし入り)。
        watermark_path (str): 透かしとして使用するPDFファイルのパス。
    """
    # 1. 部門別レポートを結合
    all_reports_path = os.path.join(
        department_reports_dir, "all_department_reports.pdf"
    )
    merger = PdfWriter()
    pdf_files = [
        os.path.join(department_reports_dir, f)
        for f in os.listdir(department_reports_dir)
        if f.endswith(".pdf")
    ]
    for pdf_file in sorted(pdf_files):  # ファイル名をソートして結合順序を制御
        merger.append(pdf_file)
    _ = merger.write(all_reports_path)
    merger.close()
    print(f"全部門レポートを結合しました: {all_reports_path}")

    # 2. 結合されたレポートからサマリーページを抽出(例: 各レポートの1ページ目のみ)
    summary_writer = PdfWriter()
    reader_all = PdfReader(all_reports_path)
    # [著者の経験談]: 実際の業務では、サマリーページは特定のキーワードやレイアウトで識別できることが多いです。
    # その場合は、テキスト抽出機能(前回の記事参照)と組み合わせて自動的にサマリーページを特定できます。
    # ここでは簡略化のため、各PDFの最初のページがサマリーであると仮定します。

    # NOTE: この例では、結合されたPDFの各元のPDFの最初のページを抽出するロジックは複雑になるため、
    # 簡略化して「結合されたPDFの最初の数ページをサマリーとする」と仮定します。
    # より高度な抽出は、PyMuPDFなどのライブラリと連携することで実現可能です。
    num_summary_pages = min(3, len(reader_all.pages))  # 最初の3ページをサマリーとする
    for i in range(num_summary_pages):
        _ = summary_writer.add_page(reader_all.pages[i])
    with open(summary_output_path, "wb") as fp:
        _ = summary_writer.write(fp)
    print(f"サマリーレポートを生成しました: {summary_output_path}")

    # 3. 機密情報を含むレポートに透かしを追加(例: 全部門レポート全体に透かし)
    reader_confidential = PdfReader(all_reports_path)
    watermark_reader = PdfReader(watermark_path)
    watermark_page = watermark_reader.pages[0]

    confidential_writer = PdfWriter()
    for page in reader_confidential.pages:
        _ = page.merge_page(watermark_page)
        _ = confidential_writer.add_page(page)
    with open(confidential_output_path, "wb") as fp:
        _ = confidential_writer.write(fp)
    print(f"機密レポートに透かしを追加しました: {confidential_output_path}")


if __name__ == "__main__":
    # ダミーの部門別レポートディレクトリとファイルを作成
    if not os.path.exists("department_reports"):
        os.makedirs("department_reports")

    writer_dept1 = PdfWriter()
    _ = writer_dept1.add_blank_page(width=72 * 8.5, height=72 * 11)
    _ = writer_dept1.add_blank_page(width=72 * 8.5, height=72 * 11)
    with open("department_reports/dept_a_report.pdf", "wb") as fp:
        _ = writer_dept1.write(fp)

    writer_dept2 = PdfWriter()
    _ = writer_dept2.add_blank_page(width=72 * 8.5, height=72 * 11)
    with open("department_reports/dept_b_report.pdf", "wb") as fp:
        _ = writer_dept2.write(fp)

    # 透かし用のダミーPDFを作成
    writer_wm = PdfWriter()
    _ = writer_wm.add_blank_page(width=72 * 8.5, height=72 * 11)
    with open("watermark.pdf", "wb") as fp:
        _ = writer_wm.write(fp)

    automate_report_management(
        department_reports_dir="department_reports",
        summary_output_path="monthly_summary_report.pdf",
        confidential_output_path="monthly_confidential_report.pdf",
        watermark_path="watermark.pdf",
    )

この実践例では、osモジュールと組み合わせてファイルシステム上のPDFファイルを扱い、結合、抽出、透かし追加の一連の処理を自動化しています。このように、pypdfの機能を組み合わせることで、複雑なドキュメント管理タスクもPythonで効率的に解決できます。


5. まとめ:pypdfによるPDFドキュメントの効率的な管理

本記事では、Pythonのpypdfライブラリを活用したPDFファイルの結合、分割、そしてページ単位での詳細な操作方法について、具体的なコード例を交えながら解説しました。

pypdfは、以下のような実用的なPDFドキュメント管理タスクを効率化するための強力なツールです。

  • PDFの結合: 複数のPDFファイルを一つにまとめたり、特定のページ範囲を選択して結合したりすることで、資料作成や整理の時間を大幅に短縮できます。
  • PDFの分割: 巨大なPDFから必要なページだけを抜き出したり、ページごとにファイルを分割したりすることで、情報の共有や管理が容易になります。
  • ページの操作: 不要なページの削除、ページの並べ替え、そして透かしの追加といった操作により、ドキュメントの内容を柔軟に編集・保護できます。

これらの機能を組み合わせることで、手作業では時間と手間がかかるPDF関連の業務をPythonで自動化し、あなたの生産性を飛躍的に向上させることが可能です。

この記事が役に立ったら、ぜひチームに共有したり、X(旧Twitter)で感想をポストしてください!

さらに高度なpypdfの活用術を学び、PDF自動化の可能性を広げましょう!


FAQ

Q1: PyPDF2とpypdfの違いは何ですか?どちらを使うべきですか?

A1: PyPDF2は長らくPythonの主要なPDF操作ライブラリでしたが、現在は開発が停滞しており、後継としてpypdfが活発に開発されています。pypdfはPyPDF2のフォークであり、より高速で、多くのバグ修正や新機能が追加されています。本記事のコード例ではpypdfを使用しており、今から始めるのであればpypdfを使用することを強く推奨します。 インストールはpip install pypdfで行えます。

Q2: 大量のPDFファイルを結合・分割する際のパフォーマンスが心配です。何か対策はありますか?

A2: pypdfはPythonで書かれているため、非常に大量のPDF(数百MB以上、数千ページ以上)を扱う際にはメモリ使用量や処理速度が問題になることがあります。対策としては、以下の点が挙げられます。

  • メモリ効率の良い処理: ページを一度にすべてメモリに読み込むのではなく、必要なページだけを処理するようにコードを最適化します。
  • バッチ処理: 大量のファイルを一度に処理するのではなく、小さなバッチに分けて処理することで、メモリ負荷を軽減できます。
  • より高速なライブラリの検討: 処理速度が最優先される場合は、C++で書かれたPDFライブラリのPythonバインディングである PyMuPDF の利用を検討してください。PyMuPDFは非常に高速で、大規模なPDF処理に適しています。

Q3: 暗号化されたPDFやパスワード保護されたPDFを結合・分割できますか?

A3: はい、可能です。pypdfは、パスワードで保護されたPDFの読み込みと、新しいPDFへのパスワード設定をサポートしています。ただし、読み込みには正しいパスワードが必要です。パスワードなしで暗号化されたPDFを直接操作することはできません。

from pypdf import PdfReader, PdfWriter
from pypdf.errors import DependencyError


def decrypt_and_merge(
    encrypted_pdf_path: str, password: str, other_pdf_path: str, output_path: str
) -> None:
    """
    暗号化されたPDFを復号し、別のPDFと結合する。

    Args:
        encrypted_pdf_path (str): 暗号化されたPDFのパス。
        password (str): PDFのパスワード。
        other_pdf_path (str): 結合するもう一方のPDFのパス。
        output_path (str): 出力するPDFのパス。
    """
    try:
        reader_encrypted = PdfReader(encrypted_pdf_path)
        if reader_encrypted.is_encrypted:
            if reader_encrypted.decrypt(password):
                print(f"'{encrypted_pdf_path}' の復号に成功しました。")
            else:
                print(
                    f"'{encrypted_pdf_path}' の復号に失敗しました。パスワードが違う可能性があります。"
                )
                return

        writer = PdfWriter()
        writer.append(reader_encrypted)
        writer.append(other_pdf_path)
        with open(output_path, "wb") as fp:
            _ = writer.write(fp)
        print(f"暗号化解除後、PDFを結合しました: {output_path}")

    except DependencyError:
        print("エラー: この機能にはPyCryptodomeが必要です。")
        print("pip install pypdf[crypto] を実行してください。")


if __name__ == "__main__":
    # ダミーの暗号化PDFを作成
    writer_encrypted = PdfWriter()
    _ = writer_encrypted.add_blank_page(width=72 * 8.5, height=72 * 11)
    password = "password123"
    writer_encrypted.encrypt(password)
    with open("encrypted.pdf", "wb") as fp:
        _ = writer_encrypted.write(fp)

    # 結合するもう一方のダミーPDFを作成
    writer_other = PdfWriter()
    _ = writer_other.add_blank_page(width=72 * 8.5, height=72 * 11)
    with open("other.pdf", "wb") as fp:
        _ = writer_other.write(fp)

    decrypt_and_merge(
        "encrypted.pdf", password, "other.pdf", "decrypted_and_merged.pdf"
    )

Q4: 透かし(ウォーターマーク)の画像はどのように用意すれば良いですか?

A4: 透かし用のPDFは、通常、画像編集ソフトウェア(Photoshop, GIMPなど)で作成した画像(PNG形式で透明背景が推奨)を、ReportLabなどのPDF生成ライブラリでPDFに変換して作成します。ReportLabを使えば、Pythonコードで「CONFIDENTIAL」といったテキストやロゴを配置し、透明度を設定した透かしPDFを生成できます。


参考文献


免責事項

本記事で提供される情報は、一般的な教育目的のみを意図しており、特定の状況における専門的なアドバイスを構成するものではありません。コード例は動作確認を行っていますが、実際の運用環境での使用にあたっては、十分なテストと検証を行ってください。本情報の利用によって生じたいかなる損害についても、著者は一切の責任を負いません。


SNSでもご購読できます。

コメントを残す

*