PDF 合并+添加页码 相关库、类、函数

PDF 合并加页码代码一共使用 PyPDF2、reportlab 两个第三方库,搭配 Python 内置io内存流、os文件库。

1 库总览

表格

|-------------------------|-------------------------------------|
| 库 | 作用 |
| PyPDF2 | PDF 读取、合并、页面叠加、写出 PDF 文件,处理已有 PDF |
| reportlab.pdfgen.canvas | 生成全新 PDF 图层(页码图层),绘制文字、字体,用来生成页码水印页 |
| io.BytesIO | 内存字节流,全部 PDF 操作在内存完成,不生成临时磁盘 PDF 文件 |
| os | 文件夹遍历、拼接文件路径、判断文件是否存在 |
| re | 文件名数字排序正则,和 PDF 编辑无关 |


2 PyPDF2 核心类 & 函数解析

① PdfMerger()

merger = PdfMerger()

merger.append(file)

merger.write(temp_memory)

merger.close()

PdfMerger:专门用于 PDF 合并的工具类

.append(file):追加一个 PDF 文件,按调用顺序把 PDF 全部拼在一起;支持磁盘路径 / 内存 BytesIO 对象

.write(temp_memory):将合并完成的完整 PDF 写入字节流(这里没有写磁盘,写到内存)

.close():关闭 merger,释放文件资源

② PdfReader()

merged_pdf = PdfReader(temp_memory)

num_layer = PdfReader(buf)

src_page = merged_pdf.pagesindex

PdfReader:读取 PDF 对象,可以读磁盘文件,也可以直接读 BytesIO 内存流

.pagesindex:PDF 所有页面列表,下标从 0 开始,获取第 index 页页面对象

src_page.mediabox:页面画布边界对象,.width、.height获取 PDF 页面宽高(新版本返回 Decimal,代码中强制float()转换)

③ PdfWriter()

pdf_writer = PdfWriter()

pdf_writer.add_page(src_page)

pdf_writer.write(f)

PdfWriter:用来组装、输出最终 PDF 的写入器

.add_page(src_page):把处理完成的一页加入输出队列

.write(f):把全部页面写入打开的磁盘二进制文件句柄,生成最终 pdf

④ 关键函数 src_page.merge_page(num_layer.pages0)

实现页码叠加的核心函数

src_page.merge_page(num_layer.pages0)

作用:把一个 PDF 页面图层叠加到当前页面上

逻辑:reportlab 生成只有页码的空白 PDF 页num_layer.pages0,叠加到原始 PDF 页面src_page底部,实现页码水印效果。

⚠注意:是图层叠加,不是修改原 PDF 文本;页码是画上去的图形文字。


3 reportlab 库(生成页码图层)

from reportlab.pdfgen import canvas

c = canvas.Canvas(buf, pagesize=(w, h))

c.setFont("Helvetica", font_size)

c.drawCentredString(w / 2, page_bottom_margin, page_text)

c.save()

canvas.Canvas(buf, pagesize=(w, h))

创建一个 PDF 画布对象,输出目标是内存buf(BytesIO),设置页面尺寸和原 PDF 页面宽高保持一致

.font("Helvetica", font_size)

设置画布绘制文字的字体、字号;你后续改成 Times New Roman 就修改这里字体名

.drawCentredString(x, y, text)

绘制居中文字

x:水平坐标;w/2就是页面水平中点

y:垂直坐标,PDF 坐标原点在页面左下角!! y=0 就是最底边;page_bottom_margin=20就是距离底边 20pt 的位置画页码

.save()

将画布内容输出到 BytesIO,完成页码图层 PDF 生成。

PDF 坐标关键点:

原点 (0,0):页面左下角

单位:pt(磅),1 英寸 = 72pt

4 io.BytesIO 内存流(非常关键)

temp_memory = io.BytesIO()

buf = io.BytesIO()

temp_memory.seek(0)

buf.seek(0)

BytesIO:内存里面的二进制文件,完全不读写磁盘

流程:

PdfMerger 合并 PDF → 写入temp_memory内存

seek(0):指针移动回到字节流开头,后面PdfReader才能从头读取内容

reportlab 生成页码图层写入buf内存流,再 seek (0) 供 PdfReader 读取

好处:全程无临时中间 PDF 文件,速度快;缺点大文件会占用内存。

5 整体完整数据流

磁盘多个PDF文件 → PdfMerger合并 → BytesIO内存合并PDF

→ PdfReader读取合并好的PDF,循环每一页

↓

reportlab Canvas(内存buf)生成只有页码的透明图层

↓

merge_page() 将页码图层叠加原始PDF页面

↓

PdfWriter收集全部叠加完页码的页面

→ write()写入磁盘输出文件【合并带页码.pdf】

补充:代码中两个模式说明

custom_file_list != None:手动指定文件名列表,严格按照列表顺序合并,只合并列表中写的 PDF;会校验文件是否存在。

custom_file_list = None:扫描文件夹全部.pdf文件,使用 sort_key 自定义排序。

常见坑总结

PyPDF2 新版本mediabox.width返回 Decimal 类型,和 reportlab float 运算报错,所以代码用float()强制转换。

reportlab 画布坐标原点左下角,y 值越小越靠近底边,太小会被 PDF 阅读器裁切。

merge_page是图层叠加,页码属于图形对象,不是 PDF 文本对象,不能复制选中页码文字。

reportlab 默认字体 Helvetica 不支持中文,需要注册 TTF 字体(Times New Roman / 中文字体)。

相关推荐
hudd6684 分钟前
JavaEE 初阶 - 多线程(进阶)
java·开发语言·java-ee
孟健11 分钟前
从单体失控到解耦管道:用 Unix 哲学重构 Anthropic 式多 Agent 动态工作流
人工智能·python·架构
小白快快跑哦20 分钟前
python-字符串全解(六):正则表达式-前后相断言
开发语言·python·正则表达式·前后相断言
kimnoic25 分钟前
Python数据分析中正则表达式匹配字符串与常用函数示例详解
开发语言·python
软件技术NINI26 分钟前
圣罗兰彩妆html+css 4页
前端·css·html
中屹指纹浏览器svip35 分钟前
打开账号环境网页报错,常见原因有哪些?
服务器·开发语言·php·中屹指纹浏览器
许墨の小蝴蝶36 分钟前
Pillow 替换图片文字后字号偏小的排查
python·pillow
朝朝辞暮i44 分钟前
第 01 讲:Python 变量、对象、数据类型与内存引用
开发语言·python
2601_951615201 小时前
网站模板 网站网页模板下载
前端·网络·html
外收内放1 小时前
Python基础语法练习题(69)
开发语言·python