导入所需模块
import os
import re
from PyPDF2 import PdfReader, PdfWriter
为了防止你的 PDF 页面顺序乱套,定义natural_sort_key函数
defnatural_sort_key(s):
"""
用于自然排序的键函数。
它将字符串拆分为数字和非数字部分,并将数字部分转化为整数进行比较。
"""
# re.split('([0-9]+)', s): 使用正则将文件名按数字拆分。例如 'file10.pdf' -> ['file', '10', '.pdf']
# 列表推导式: 遍历拆分后的部分
# int(text) if text.isdigit(): 如果是数字字符,强制转为整数(这样 2 就小于 10)
# else text.lower(): 如果是文字,转小写(忽略大小写差异)
return [int(text) if text.isdigit() else text.lower()
for text in re.split('([0-9]+)', s)]
定义合并PDF的函数
defmerge_specific_pages():
work_dir = 'D:/Users/PDF'# 设置工作目录路径(即 PDF 文件所在的文件夹)
output_filename = '合并结果.pdf'# 设置输出文件的名称
os.chdir(work_dir) # 将当前 Python 运行环境的工作目录切换到指定文件夹
files = os.listdir(work_dir) # 获取该目录下所有文件和文件夹的名称列表
# 列表推导式筛选文件:
# 1. f.lower().endswith('.pdf'): 确保是 PDF 文件(忽略大小写,.PDF 也能识别)
# 2. f != output_filename: 排除掉输出文件自己(防止把上次生成的“合并结果.pdf”又读进去造成死循环)
pdf_files = [f for f in files if f.lower().endswith('.pdf') and f != output_filename]
# 使用之前定义的 natural_sort_key 函数对文件列表进行排序
# 效果:确保 1.pdf, 2.pdf ... 10.pdf 顺序正确,而不是 1, 10, 2
pdf_files.sort(key=natural_sort_key)
print(f"待处理文件列表: {pdf_files}") # 打印即将处理的文件列表,供用户确认
pdf_writer = PdfWriter() # 创建一个空白的 PDF 写入对象(相当于一个空白的 PDF 文档,准备往里贴页面)
# 遍历排序好的 PDF 文件列表
for pdf_file in pdf_files:
try:
reader = PdfReader(pdf_file) # 创建 PDF 读取对象,加载当前文件
total_pages = len(reader.pages) # 获取当前文件的总页数
print(f"正在处理: {pdf_file} (共 {total_pages} 页)") # 打印当前正在处理的文件名和页数
pages_to_extract = 2# 设定目标:想要提取每个文件的前几页?(这里设为 2,即前两页)
# 计算实际循环次数:
# min(2, total_pages): 取“预设页数”和“实际总页数”中较小的一个
# 如果文件有 10 页,min(2, 10) = 2 -> 循环 0, 1
# 如果文件只有 1 页,min(2, 1) = 1 -> 循环 0
# 这行代码完美防止了“数组越界”报错
for i in range(min(pages_to_extract, total_pages)):
# 获取第 i 页的内容(注意:PDF 页码索引从 0 开始)
page = reader.pages[i]
# 将这一页添加到写入对象(贴到新 PDF 中)
pdf_writer.add_page(page)
# 捕获异常:如果处理某个文件时出错(比如文件损坏),不中断程序
except Exception as e:
# 打印出错的文件名和具体错误信息
print(f"处理文件 {pdf_file} 时出错: {e}")
# 跳过当前文件,继续循环处理下一个文件
continue
try:
# 使用 'wb' (二进制写入模式) 打开(或创建)输出文件
# with open... 是上下文管理器,能确保文件使用后自动关闭,防止损坏
with open(output_filename, 'wb') as out_file:
# 将内存中拼接好的所有页面写入硬盘
pdf_writer.write(out_file)
# 打印成功信息,显示完整路径
print(f"\n成功!文件已保存至: {os.path.join(work_dir, output_filename)}")
# 捕获保存阶段可能出现的错误(如文件被占用、无权限等)
except Exception as e:
print(f"保存失败: {e}")
如果想要合并所有的页,只需要做如下修改
# 修改后:直接使用总页数,意味着“循环所有页”
for i in range(total_pages):
page = reader.pages[i]
pdf_writer.add_page(page)
运行函数
merge_specific_pages()