Python代码实现将多个PDF合并为单个文档并添加页码

 更新时间:2026年08月27日 08:20:19   作者:小庄-Python办公  
本文将教你使用Python的pypdf和reportlab库,一行代码实现合并多个PDF文件,并自动添加页码、书签,解决中文乱码和文件加密问题,希望对大家有所帮助

场景引入

年终汇报需要将 15 份部门报告(PDF 格式)合并成一个总文件,并且添加统一的页码。手动操作需要打开每个 PDF,复制页面,粘贴到总文件——不仅慢,而且可能丢失格式。

本节教你用 Python 一行代码完成合并,还能自动添加页码。

技术原理

使用 PyPDF2 或 pypdf 库操作 PDF:

多个 PDF 文件
  ↓
PdfMerger 逐个追加
  ↓
添加页码(可选)
  ↓
输出合并后的单个 PDF

合并方式

方式说明适用场景
简单拼接按文件顺序追加章节报告合并
指定顺序按列表顺序合并按部门/日期排序
插入页码在每页底部添加页码正式文档
添加书签在每个文件开始处添加书签方便跳转

环境准备

pip install pypdf reportlab
  • pypdf:PDF 合并核心库(PyPDF2 的继任者)
  • reportlab:用于添加页码水印

完整代码

import os
from pathlib import Path
from pypdf import PdfReader, PdfWriter, PdfMerger

# ==================== 方案 1:简单合并 ====================
def merge_pdfs_simple(pdf_files, output_file="合并结果.pdf"):
    """
    将多个 PDF 文件按顺序合并为一个

    参数:
        pdf_files: PDF 文件路径列表
        output_file: 输出文件名
    """
    merger = PdfMerger()

    for pdf_file in pdf_files:
        if os.path.exists(pdf_file):
            merger.append(pdf_file)
            print(f"已添加: {os.path.basename(pdf_file)}")
        else:
            print(f"[跳过] 文件不存在: {pdf_file}")

    merger.write(output_file)
    merger.close()
    print(f"\n合并完成: {output_file}")


# ==================== 方案 2:带书签的合并 ====================
def merge_pdfs_with_bookmarks(pdf_files, output_file="合并结果_带书签.pdf"):
    """
    合并 PDF 并添加书签(每个文件一个书签)
    """
    merger = PdfMerger()

    for pdf_file in pdf_files:
        if not os.path.exists(pdf_file):
            continue

        bookmark_name = Path(pdf_file).stem
        merger.append(pdf_file)

        # 获取此文件在合并文件中的起始页码
        total_pages = sum(PdfReader(f).get_num_pages() for f in pdf_files[:pdf_files.index(pdf_file) + 1] if os.path.exists(f))
        start_page = total_pages - PdfReader(pdf_file).get_num_pages()

        # 添加书签
        merger.add_outline_item(bookmark_name, start_page)
        print(f"已添加书签: {bookmark_name} (第 {start_page + 1} 页)")

    merger.write(output_file)
    merger.close()
    print(f"\n合并完成: {output_file}")


# ==================== 方案 3:批量合并文件夹中的所有 PDF ====================
def merge_folder_pdfs(folder_path, output_file="合并结果.pdf", sorted_by='name'):
    """
    自动合并文件夹中的所有 PDF

    参数:
        folder_path: PDF 文件所在文件夹
        output_file: 输出文件名
        sorted_by: 排序方式 'name'(文件名) / 'date'(修改日期)
    """
    folder = Path(folder_path)
    pdf_files = sorted(
        folder.glob('*.pdf'),
        key=lambda f: f.stat().st_mtime if sorted_by == 'date' else f.name
    )

    if not pdf_files:
        print(f"文件夹 {folder_path} 中没有 PDF 文件!")
        return

    print(f"找到 {len(pdf_files)} 个 PDF 文件:")
    for f in pdf_files:
        print(f"  - {f.name}")

    merge_pdfs_with_bookmarks(
        [str(f) for f in pdf_files],
        output_file
    )


# ==================== 方案 4:添加页码 ====================
def add_page_numbers(input_pdf, output_file="带页码版本.pdf"):
    """
    为 PDF 添加页码(每页底部居中)
    """
    from reportlab.lib.pagesizes import A4
    from reportlab.pdfgen import canvas
    import io

    reader = PdfReader(input_pdf)
    writer = PdfWriter()

    total_pages = len(reader.pages)

    for i, page in enumerate(reader.pages):
        # 创建页码水印
        packet = io.BytesIO()
        c = canvas.Canvas(packet, pagesize=A4)
        width, height = A4

        # 绘制页码
        c.setFont("Helvetica", 9)
        page_number = f"- {i + 1} -"
        text_width = c.stringWidth(page_number, "Helvetica", 9)
        c.drawString((width - text_width) / 2, 30, page_number)

        c.save()
        packet.seek(0)

        # 叠加水印到原页面
        watermark = PdfReader(packet)
        page.merge_page(watermark.pages[0])
        writer.add_page(page)

    with open(output_file, 'wb') as f:
        writer.write(f)

    print(f"页码已添加: {output_file}")


# ==================== 使用示例 ====================
if __name__ == "__main__":
    # 方案 1:手动指定文件列表
    # pdf_files = [
    #     "第1章.pdf",
    #     "第2章.pdf",
    #     "第3章.pdf",
    # ]
    # merge_pdfs_simple(pdf_files, "完整手册.pdf")

    # 方案 2:批量合并文件夹
    merge_folder_pdfs(
        r"D:\部门报告",
        output_file="年度总报告.pdf",
        sorted_by='name'
    )

    # 方案 3:添加页码
    # add_page_numbers("年度总报告.pdf", "年度总报告_带页码.pdf")

常见问题

Q1:合并后中文显示为乱码?

reportlab 默认不支持中文。需要使用中文字体:

from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

pdfmetrics.registerFont(TTFont('SimSun', 'C:/Windows/Fonts/simsun.ttc'))
c.setFont('SimSun', 9)

Q2:合并后文件很大?

PDF 中可能包含大量内嵌字体和图片。可以尝试压缩:

pip install pypdf

pypdf 在合并时不会重复嵌入相同字体,文件体积通常比预期小。

Q3:加密的 PDF 无法合并?

需要先解密:

reader = PdfReader("encrypted.pdf")
if reader.is_encrypted:
    reader.decrypt("password")

总结

功能核心类/函数说明
合并PdfMerger()追加多个 PDF
书签add_outline_item()添加跳转标记
页码reportlab + merge_page()底部叠加页码水印
排序sorted(glob(), key=...)按名称或日期排序

到此这篇关于Python代码实现将多个PDF合并为单个文档并添加页码的文章就介绍到这了,更多相关Python合并多个PDF内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用TensorFlow直接获取处理MNIST数据方式

    使用TensorFlow直接获取处理MNIST数据方式

    今天小编就为大家分享一篇使用TensorFlow直接获取处理MNIST数据方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-02-02
  • 使用Python为PowerPoint幻灯片添加演讲者备注

    使用Python为PowerPoint幻灯片添加演讲者备注

    在制作演示文稿时,演讲者备注是一个非常有用的功能,它允许演讲者在幻灯片下方添加注释、提示或详细说明,这些内容在演示模式下对观众不可见,但可以帮助演讲者更好地组织思路和掌握演讲节奏,本文将介绍如何使用Python为PowerPoint幻灯片添加演讲者备注
    2026-06-06
  • python中数据库like模糊查询方式

    python中数据库like模糊查询方式

    这篇文章主要介绍了python中数据库like模糊查询方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-03-03
  • Python常用的文件及文件路径、目录操作方法汇总介绍

    Python常用的文件及文件路径、目录操作方法汇总介绍

    这篇文章主要介绍了Python常用的文件及文件路径、目录操作方法汇总介绍,本文集合了最常用的一些文件和目录操作函数,并一一介绍它们的作用,需要的朋友可以参考下
    2015-05-05
  • flask上使用websocket的方法示例

    flask上使用websocket的方法示例

    本文主要介绍了flask上使用websocket的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • Python中过滤字符串列表的方法

    Python中过滤字符串列表的方法

    这篇文章主要介绍了Python中过滤字符串列表的方法,帮助大家更好的理解和使用python,感兴趣的朋友可以了解下
    2020-12-12
  • python数据库如何连接SQLite详解

    python数据库如何连接SQLite详解

    这篇文章主要介绍了Python实现连接SQLite数据库的方法,在Python数据库编程中有着广泛的应用,需要的朋友可以参考下,希望能给你带来帮助
    2021-08-08
  • python判断字符串以什么结尾的实例方法

    python判断字符串以什么结尾的实例方法

    在本篇文章里小编给大家整理了关于python判断字符串以什么结尾的实例方法 ,需要的朋友们可以学习参考下。
    2020-09-09
  • Python简单实现网页内容抓取功能示例

    Python简单实现网页内容抓取功能示例

    这篇文章主要介绍了Python简单实现网页内容抓取功能,结合实例形式分析了Python基于urllib模块的网页请求、内容读取等相关操作技巧,需要的朋友可以参考下
    2018-06-06
  • Python 中 yeild 的用法详解

    Python 中 yeild 的用法详解

    yield 是 Python 中的关键字,用于生成器函数中,可以将函数变成一个迭代器,实现惰性计算,节省内存空间。本文将介绍 yield 的基本用法和实现原理,以及与 yield 相关的注意事项和常见问题。
    2023-06-06

最新评论