你有没有遇到过这种场景——
老板甩过来20个PDF文件,让你合成一个?或者一个300页的PDF,你只需要其中第5到第12页?
手动操作?那可太折磨人了。
今天教大家用Python的 PyPDF2 库,10行代码搞定PDF的合并和拆分。学会之后,同事会把你当神仙的。
安装依赖
就这一行,完事。
场景一:合并多个PDF
这是最常见的场景。报销材料、合同附件、项目文档……一堆PDF要合并成一个。
from PyPDF2 import PdfMerger
# 创建合并器
merger = PdfMerger()
# 需要合并的PDF文件列表
pdf_files = ['report_part1.pdf', 'report_part2.pdf', 'appendix.pdf']
# 依次添加
for pdf in pdf_files:
merger.append(pdf)
# 输出合并后的文件
merger.write('merged_report.pdf')
merger.close()
print('合并完成!')
就这?就这。
运行完之后,三个文件就乖乖合并成一个了。
场景二:拆分PDF
有时候你只需要PDF里的一部分页面,比如一个大报告里只要某几个章节。
from PyPDF2 import PdfReader, PdfWriter
reader = PdfReader('big_report.pdf')
writer = PdfWriter()
# 提取第5页到第12页(索引从0开始)
for page_num in range(4, 12):
writer.add_page(reader.pages[page_num])
writer.write('extracted_pages.pdf')
print('拆分完成!')
注意一下,页码从0开始计数,所以第5页对应索引4。这个坑我踩过,别踩。
场景三:批量拆分(每一页单独保存)
有时候需要把PDF的每一页都拆成单独的文件,比如发票、证书之类的。
from PyPDF2 import PdfReader, PdfWriter
import os
reader = PdfReader('invoices.pdf')
# 创建输出目录
os.makedirs('invoices_split', exist_ok=True)
for i, page in enumerate(reader.pages):
writer = PdfWriter()
writer.add_page(page)
writer.write(f'invoices_split/page_{i + 1}.pdf')
print(f'共拆分出 {len(reader.pages)} 个文件')
100页的PDF,两秒钟全部拆完。
场景四:给PDF加水印
这个功能有点进阶,但实用得很。给合同加水印,防止被乱改。
from PyPDF2 import PdfReader, PdfWriter
from PyPDF2.generic import NameObject, ArrayObject, TextStringObject
reader = PdfReader('contract.pdf')
writer = PdfWriter()
for page in reader.pages:
# 合并水印页
page.merge_page(get_watermark_page())
writer.add_page(page)
writer.write('contract_watermarked.pdf')
def get_watermark_page():
"""创建水印页"""
from PyPDF2 import PdfWriter
wm_writer = PdfWriter()
wm_writer.add_blank_page(width=595, height=842)
# 在空白页上添加文字
page = wm_writer.pages[0]
page.merge_transformed_page(
page,
create_text_watermark('内部文件', opacity=0.3)
)
return page
这个稍微复杂一点,但效果绝了。
场景五:获取PDF信息
有时候你需要知道一个PDF有多少页、文件大小之类的信息。
from PyPDF2 import PdfReader
reader = PdfReader('document.pdf')
print(f'总页数: {len(reader.pages)}')
print(f'标题: {reader.metadata.title if reader.metadata else "无"}')
print(f'作者: {reader.metadata.author if reader.metadata else "无"}')
print(f'创建时间: {reader.metadata.creation_date if reader.metadata else "无"}')
一键查看PDF的基本信息,比右键属性靠谱多了。
进阶技巧:按书签拆分
如果你的PDF有书签(大纲),可以按书签来拆分。
from PyPDF2 import PdfReader, PdfWriter
reader = PdfReader('bookmarked_doc.pdf')
outlines = reader.outline
# outlines 就是一个树形结构,包含了所有书签
for item in outlines:
if isinstance(item, list):
for sub_item in item:
print(f' - {sub_item.title}')
else:
print(f'- {item.title}')
这样你就能看到PDF的完整目录结构,然后按需提取。
完整工具类
我把常用操作封装成了一个工具类,直接复制就能用:
from PyPDF2 import PdfReader, PdfWriter, PdfMerger
import os
class PDFToolkit:
"""PDF工具箱"""
@staticmethod
def merge(pdf_files, output_path):
"""合并多个PDF"""
merger = PdfMerger()
for pdf in pdf_files:
if os.path.exists(pdf):
merger.append(pdf)
else:
print(f'警告: 文件不存在 - {pdf}')
merger.write(output_path)
merger.close()
print(f'合并完成: {output_path}')
@staticmethod
def split(input_path, output_dir, pages=None):
"""拆分PDF,pages为None则逐页拆分"""
reader = PdfReader(input_path)
os.makedirs(output_dir, exist_ok=True)
if pages is None:
pages = range(len(reader.pages))
for i in pages:
writer = PdfWriter()
writer.add_page(reader.pages[i])
output = os.path.join(output_dir, f'page_{i + 1}.pdf')
writer.write(output)
print(f'拆分完成: 共{len(pages)}页')
@staticmethod
def extract(input_path, output_path, start, end):
"""提取指定范围的页面"""
reader = PdfReader(input_path)
writer = PdfWriter()
for i in range(start - 1, end):
writer.add_page(reader.pages[i])
writer.write(output_path)
print(f'提取完成: 第{start}页到第{end}页')
@staticmethod
def info(input_path):
"""获取PDF信息"""
reader = PdfReader(input_path)
meta = reader.metadata or {}
print(f'文件: {os.path.basename(input_path)}')
print(f'页数: {len(reader.pages)}')
print(f'标题: {meta.get("/Title", "无")}')
print(f'作者: {meta.get("/Author", "无")}')
@staticmethod
def rotate(input_path, output_path, angle):
"""旋转PDF页面"""
reader = PdfReader(input_path)
writer = PdfWriter()
for page in reader.pages:
page.rotate(angle)
writer.add_page(page)
writer.write(output_path)
print(f'旋转完成: {angle}度')
# 使用示例
if __name__ == '__main__':
toolkit = PDFToolkit()
# 合并
toolkit.merge(['part1.pdf', 'part2.pdf'], 'merged.pdf')
# 拆分
toolkit.split('big_file.pdf', 'output_dir')
# 提取第3-7页
toolkit.extract('big_file.pdf', 'pages_3_to_7.pdf', 3, 7)
# 查看信息
toolkit.info('any_file.pdf')
这个工具类覆盖了90%的PDF处理场景。
效果对比
| 操作 | 手动方式 | Python方式 |
|---|
| 合并20个PDF | 30分钟 | 3秒 |
| 拆分指定页 | 10分钟 | 1秒 |
| 批量逐页拆分 | 简直不可能 | 2秒 |
| 加水印 | 要开专业软件 | 5秒 |
效率提升不是一点半点,是降维打击。注意事项
1. PyPDF2 只能处理普通PDF,加密的PDF需要先解密
2. 处理超大PDF(几百MB)时注意内存占用
3. 某些特殊排版的PDF可能会丢失格式
4. 如果需要更高级的功能(比如编辑文字),建议用 pdfplumber 或 PyMuPDF
总结
PDF处理是办公自动化的刚需场景。用Python的PyPDF2库,几行代码就能搞定平时要折腾半天的事。
学编程不是为了写多牛的东西,是为了让自己少干点重复的活。觉得有用的话,点个赞再走吧。有问题评论区见。
点赞、在看、转发,你的支持是我持续输出的动力。关注「几行代码」,每天学点实用的编程技巧。