ARTICLE · 1136559
PDF批量合并,用Python一键搞定!再也不用逐个复制了
工作中经常要把几十个PDF合并成一个?手动拖拽太慢,在线工具又担心隐私。今天教你用Python批量合并,几十行代码,安全高效,还能自动加书签。
今天聊一个很实用的小技能:PDF批量合并。
比如:
每个月的发票PDF要合成一个;
一个项目的几十份资料要按顺序合并;
每个子文件夹里的PDF要分别合并成一个文件;
合并后还想自动生成书签目录。
这些用 Python 都能轻松搞定。
一、准备工作
只需要一个库:pypdf。
它是纯 Python 库,安装简单,跨平台。
打开终端或命令行,输入:
pip install pypdf如果你还没装 Python,先去官网下载安装:https://www.python.org/
安装时记得勾选 Add Python to PATH。
二、基础版:合并一个文件夹下所有PDF
先来看最小可运行版本。
from pathlib import Pathfrom pypdf import PdfWriter, PdfReaderimport redef natural_key(path):"""自然排序:file2.pdf 排在 file10.pdf 前面"""return [int(t) if t.isdigit() else t.lower()for t in re.split(r'(\d+)', path.name)]def merge_pdfs(input_dir, output_file):input_path = Path(input_dir)pdf_files = sorted(input_path.glob("*.pdf"), key=natural_key)if not pdf_files:print("没有找到PDF文件")returnwriter = PdfWriter()for pdf in pdf_files:reader = PdfReader(str(pdf))for page in reader.pages:writer.add_page(page)print(f"已添加:{pdf.name}")with open(output_file, "wb") as f:writer.write(f)print(f"合并完成:{output_file},共 {len(pdf_files)} 个文件")if __name__ == "__main__":merge_pdfs("./pdfs", "./合并结果.pdf")
pdfs 文件夹里,然后运行:python merge_pdf.py就会生成一个 合并结果.pdf。
注意这里用了自然排序,否则 file10.pdf 可能会排在 file2.pdf 前面。
三、进阶版:批量合并多个子文件夹
如果你有这样的目录结构:
pdfs/├── 项目A/│ ├── 01.pdf│ ├── 02.pdf│ └── 03.pdf├── 项目B/│ ├── 01.pdf│ └── 02.pdf└── 项目C/└── 01.pdf
from pathlib import Pathfrom pypdf import PdfWriter, PdfReaderimport redef natural_key(path):return [int(t) if t.isdigit() else t.lower()for t in re.split(r'(\d+)', path.name)]def merge_folder(folder, output_file):pdf_files = sorted(folder.glob("*.pdf"), key=natural_key)if not pdf_files:returnwriter = PdfWriter()for pdf in pdf_files:reader = PdfReader(str(pdf))for page in reader.pages:writer.add_page(page)with open(output_file, "wb") as f:writer.write(f)print(f"合并完成:{output_file}")def merge_subfolders(root_dir, output_dir):root = Path(root_dir)out = Path(output_dir)out.mkdir(parents=True, exist_ok=True)for folder in sorted(root.iterdir(), key=natural_key):if folder.is_dir():output_file = out / f"{folder.name}.pdf"merge_folder(folder, output_file)if __name__ == "__main__":merge_subfolders("./pdfs", "./output")
output 文件夹里会生成:output/├── 项目A.pdf├── 项目B.pdf└── 项目C.pdf
每个子文件夹一个合并文件,互不干扰。
四、给合并后的PDF加书签
合并几十个文件后,如果没有书签,找内容很痛苦。
pypdf 支持添加大纲书签:
writer = PdfWriter()for pdf in pdf_files:reader = PdfReader(str(pdf))start_page = len(writer.pages)for page in reader.pages:writer.add_page(page)# 添加书签,标题用文件名writer.add_outline_item(pdf.stem, start_page)
这样合并后的PDF左侧会有一个目录,点击就能跳到对应文件的第一页。
五、完整脚本:直接复制就能用
下面这个版本整合了:
自然排序
自动加书签
加密PDF跳过
单个文件夹合并
多个子文件夹批量合并
异常处理
# -*- coding: utf-8 -*-"""PDF批量合并工具功能:1. 合并指定文件夹下所有PDF2. 批量合并多个子文件夹,每个子文件夹生成一个PDF3. 自动按文件名自然排序4. 为每个源文件添加书签"""from pathlib import Pathfrom pypdf import PdfWriter, PdfReaderimport redef natural_key(path):"""自然排序:file2.pdf 排在 file10.pdf 前面"""return [int(t) if t.isdigit() else t.lower()for t in re.split(r'(\d+)', path.name)]def merge_pdf_files(pdf_files, output_file, add_bookmark=True):"""合并PDF文件列表"""writer = PdfWriter()for pdf in pdf_files:try:reader = PdfReader(str(pdf))# 尝试处理加密PDF(空密码)if reader.is_encrypted:try:reader.decrypt("")except Exception:print(f"跳过加密文件:{pdf.name}")continuestart_page = len(writer.pages)for page in reader.pages:writer.add_page(page)if add_bookmark:writer.add_outline_item(pdf.stem, start_page)print(f"已添加:{pdf.name}({len(reader.pages)}页)")except Exception as e:print(f"处理失败:{pdf.name},原因:{e}")if len(writer.pages) == 0:print("没有可合并的页面")returnoutput_file = Path(output_file)output_file.parent.mkdir(parents=True, exist_ok=True)with open(output_file, "wb") as f:writer.write(f)print(f"✅ 合并完成:{output_file},总页数:{len(writer.pages)}")def merge_folder(input_dir, output_file, add_bookmark=True):"""合并一个文件夹下的所有PDF"""input_dir = Path(input_dir)pdf_files = sorted(input_dir.glob("*.pdf"), key=natural_key)if not pdf_files:print(f"文件夹中没有PDF:{input_dir}")returnmerge_pdf_files(pdf_files, output_file, add_bookmark)def merge_subfolders(root_dir, output_dir, add_bookmark=True):"""每个子文件夹合并成一个PDF"""root_dir = Path(root_dir)output_dir = Path(output_dir)output_dir.mkdir(parents=True, exist_ok=True)for folder in sorted(root_dir.iterdir(), key=natural_key):if folder.is_dir():pdf_files = sorted(folder.glob("*.pdf"), key=natural_key)if pdf_files:output_file = output_dir / f"{folder.name}.pdf"print(f"\n📂 处理文件夹:{folder.name}")merge_pdf_files(pdf_files, output_file, add_bookmark)if __name__ == "__main__":# ====== 修改这里 ======MODE = "subfolders" # "single" 合并单个文件夹;"subfolders" 批量合并子文件夹INPUT_DIR = "./pdfs" # 输入目录OUTPUT = "./output" # 输出目录if MODE == "single":merge_folder(INPUT_DIR, Path(OUTPUT) / "合并结果.pdf")else:merge_subfolders(INPUT_DIR, OUTPUT)
使用步骤:
安装
pypdf:pip install pypdf把代码保存为
merge_pdf.py修改
INPUT_DIR和OUTPUT运行
python merge_pdf.py
六、常见问题
1. 提示没有 pypdf?
运行:
pip install pypdf如果用了虚拟环境,确认在对应环境中安装。
2. 合并顺序不对?
代码里已经用了自然排序。如果还不够,可以在文件名前加数字:
01_合同.pdf02_附件.pdf03_发票.pdf
3. PDF有密码怎么办?
脚本会先尝试空密码解密。如果不行,会跳过并提示。
4. 文件太多,内存不够?
pypdf 是纯 Python 库,合并超大文件时内存占用会高一些。可以分批合并,或者改用 PyMuPDF。
5. 想打包成 exe 给同事用?
可以安装:
pip install pyinstallerpyinstaller -F merge_pdf.py生成的 exe 在 dist 文件夹里。不过路径配置需要提前写好。
七、总结
今天实现了:
单个文件夹PDF批量合并
多个子文件夹分别合并
自然排序,避免 10 排在 2 前面
自动添加书签
加密文件跳过
异常处理
Python 处理办公自动化,最大的好处就是:一次写好,重复使用,安全可控。
如果你经常处理 PDF,不妨把脚本收藏起来,改改路径就能用。