按章节拆分 PDF 文档的 Python 实现

在日常工作中,我们经常需要将一本 PDF 文档按章节进行拆分,比如将一本电子书拆分为单独的章节文件。本文将为大家分享一个使用 Python 和 PyPDF2 库实现按章节拆分 PDF 文档的完整代码。

实现原理

PDF 文档中的章节信息通常由 书签(Outline) 标识。通过读取书签信息,我们可以获得每个章节的起始页码,然后根据这些页码将 PDF 文档拆分成多个小文件。

本文使用 PyPDF2 库来完成以下工作:

  1. 读取 PDF 文档中的书签。
  2. 根据书签的起止页码,提取对应章节内容。
  3. 将每个章节保存为独立的 PDF 文件。

环境准备

安装 PyPDF2

在运行代码之前,需要先安装 PyPDF2 库。使用以下命令即可完成安装:

pip install PyPDF2

项目结构

假设我们有一个名为 input.pdf 的 PDF 文件,并希望将拆分后的文件保存到 output/ 文件夹中。

project/
├── book-test/
│   ├── input.pdf  # 输入文件
│   ├── output/    # 输出文件夹

代码实现

以下是完整的 Python 代码:

import os
from PyPDF2 import PdfReader, PdfWriter

def split_pdf_by_chapters(input_pdf_path, output_folder):
    """
    按章节(书签)拆分 PDF 文档。

    :param input_pdf_path: 输入的 PDF 文件路径
    :param output_folder: 输出的文件夹路径
    """
    # 确保输出文件夹存在
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)

    # 读取 PDF 文档
    reader = PdfReader(input_pdf_path)
    outlines = reader.outline  # 获取书签信息
    total_pages = len(reader.pages)

    print(f"正在解析书签,共 {total_pages} 页...")

    # 解析书签
    chapters = []
    for outline in outlines:
        if isinstance(outline, list):
            # 书签嵌套时跳过(只取顶层书签)
            continue
        try:
            page_number = reader.get_destination_page_number(outline)
            chapters.append((outline.title, page_number))
        except Exception as e:
            print(f"跳过无效书签:{outline}")

    # 按章节拆分
    for i, (title, start_page) in enumerate(chapters):
        # 获取章节的起始页和结束页
        end_page = chapters[i + 1][1] if i + 1 < len(chapters) else total_pages
        output_file = os.path.join(output_folder, f"{title.strip().replace('/', '_')}.pdf")

        # 写入章节内容
        writer = PdfWriter()
        for page_num in range(start_page, end_page):
            writer.add_page(reader.pages[page_num])

        # 保存章节 PDF
        with open(output_file, "wb") as output_pdf:
            writer.write(output_pdf)

        print(f"章节 {title} 已保存为 {output_file}")

    print("按章节拆分完成!")

# 使用示例
input_pdf = "book-test/input.pdf"  # 替换为你的 PDF 文件路径
output_dir = "book-test/output/"  # 输出文件夹路径
split_pdf_by_chapters(input_pdf, output_dir)

代码解析

1. 获取书签

代码中使用 PdfReaderoutline 属性获取书签列表:

outlines = reader.outline

通过 get_destination_page_number(outline) 方法,可以获得每个书签对应的页码:

page_number = reader.get_destination_page_number(outline)

如果书签嵌套(例如子章节),代码会跳过这些嵌套书签:

if isinstance(outline, list):
    continue

2. 按页码拆分章节

根据每个书签的起始页和下一个书签的起始页,可以计算每个章节的页码范围:

start_page = chapters[i][1]  # 当前章节起始页
end_page = chapters[i + 1][1] if i + 1 < len(chapters) else total_pages  # 下一章节起始页

然后将这些页添加到新的 PDF 文件中:

for page_num in range(start_page, end_page):
    writer.add_page(reader.pages[page_num])

3. 保存文件

将每个章节保存为独立的 PDF 文件,文件名使用书签的标题:

output_file = os.path.join(output_folder, f"{title.strip().replace('/', '_')}.pdf")
with open(output_file, "wb") as output_pdf:
    writer.write(output_pdf)

运行结果

运行代码后,程序会在 output/ 文件夹中生成以下文件(假设输入 PDF 包含 3 个章节书签):

output/
├── Chapter 1.pdf
├── Chapter 2.pdf
├── Chapter 3.pdf

注意事项

  1. 书签有效性

    • 如果 PDF 文件没有书签,程序将无法正确运行。
    • 可以手动检查书签是否存在,或者为 PDF 添加书签。
  2. 文件名特殊字符

    • 书签标题可能包含非法字符(如 /),需要替换为下划线 _,以防保存失败。
  3. 大文件性能

    • 对于页数较多的 PDF 文件,可能需要较长时间处理。

总结

本文介绍了如何使用 Python 和 PyPDF2 库按章节拆分 PDF 文档的完整过程。通过书签解析和页码范围计算,我们可以轻松将 PDF 文档按章节保存为独立的文件。

希望这篇文章对你有所帮助!如果你有任何问题或改进建议,欢迎在评论区留言交流!

你可能感兴趣的:(pdf,python)