ARTICLE · 1006561
三份PDF合并成一个,我用30行脚本几秒搞定
月末把三个部门的PDF合同扫描件合成一整本,是我每个月都要做的活。
以前我用在线网站。把文件拖上去,转圈,下载。步骤不难,但每个文件都要过一遍外国服务器。有回客户文件里夹着报价单,我盯着"已上传"三个字想了十分钟——这东西到底传哪儿去了?没人能回答。
后来我换了全套本地的写法。30行脚本,合并、拆分、抽页一个脚本全包,文件不出我电脑。今天把这个脚本掰开讲清楚,你照着抄就能用。
先说结论
PDF合并、拆分、抽页这套操作,别用在线网站。本地用 Python 一个库就够:pypdf。
装它只要一行:
pip3 install pypdf装完写脚本就能跑。不联网、不上传、不排队。
场景一:把几个PDF合成一个
这是最常用的。我拿三个测试文件演示一下完整效果。
from pypdf import PdfReader, PdfWriter files = ["引1.pdf", "引2.pdf", "引3.pdf"] # 要合并的文件,按这个顺序 out = "合并.pdf" w = PdfWriter() for name in files: r = PdfReader(name) for p in r.pages: w.add_page(p) with open(out, "wb") as f: w.write(f) print("合并完成,共", len(PdfReader(out).pages), "页")跑完我的机器上是这么输出的:
合并完成,共 3 页三个文件合成一本,3页一个不少。
注意一个坑:合并的顺序,就是列表里文件的顺序。上面那份我一开始没排序,引3排到了引2前面,因为文件名按字典序排。真要按章节来,就把文件名在列表里写成想要的顺序,或者用 sorted() 加自己定的规则排好再进列表。
场景二:把一整本PDF拆回单页
这招常在要"只发某一页"的时候用。比如整本标书要拆出技术负责人那一页盖章再传。
from pypdf import PdfReader, PdfWriter r = PdfReader("合并.pdf") for i, page in enumerate(r.pages, 1): w = PdfWriter() w.add_page(page) with open(f"第{i:02d}页.pdf" , "wb") as f: # 输出形如 第01页.pdf、第02页.pdf w.write(f)跑完目录里会多出一堆单页文件:
第01页.pdf 1 页 第02页.pdf 1 页 第03页.pdf 1 页i:02d的意思是页码补成两位数——01、02,这样按文件名排序时不会出现"第10页排在第2页前面"这种乱序。
场景三:只要其中某几页
比如一本20页的PDF,我只要第1页和第3页做个附件。
from pypdf import PdfReader, PdfWriter r = PdfReader("合并.pdf") w = PdfWriter() for i in [1, 3]: # 注意这儿的1、3是"第1页"的意思 w.add_page(r.pages[i - 1]) # 页码从0数起,所以要减1 with open("抽取_第1和3页.pdf", "wb") as f: w.write(f)我实测输出的文件是2页,正好只留了要的两页。
全部三个场景拼一个脚本
上面是拆开讲,实际用的时候我拼成一个大脚本,一个命令全搞定:
import glob, os from pypdf import PdfReader, PdfWriter # 1) 合并 files = sorted(glob.glob("*.pdf")) w = PdfWriter() for name in files: r = PdfReader(name) for p in r.pages: w.add_page(p) with open("合并.pdf", "wb") as f: w.write(f) print("合并完成", len(PdfReader("合并.pdf").pages), "页") # 2) 拆单页 for i, page in enumerate(PdfReader("合并.pdf").pages, 1): w = PdfWriter() w.add_page(page) with open(f"分_{i:02d}.pdf", "wb") as f: w.write(f) # 3) 抽页 w = PdfWriter() for i in [1, 3]: w.add_page(PdfReader("合并.pdf").pages[i - 1]) with open("抽_1和3.pdf", "wb") as f: w.write(f)三个步骤共用一个合并.pdf中间文件,跑完桌面就齐了。
我踩过的三个坑
坑一:装错库。 网上教程有让装PyPDF2的,和pypdf是两拨维护者,一个库名拼法不对就报No module named。直接装pypdf,新版本就是它。这俩现在其实合并了,但认准pypdf最保险。
坑二:页码从0开始。 人眼看到的"第1页",在代码里是pages[0]。抽页时忘记减1,抽出来的永远错位一页。我把这点写进注释里防自己忘。
坑三:扫出来的"假PDF"。 有些扫描件其实是图片贴的,提取不了文字——这正常,pypdf只管页面处理,不管OCR。真要读里面的文字,得走OCR那套,那是另一篇文章的事,这里不展开。
文件一个没出我电脑
整套跑下来,所有PDF都在本地磁盘打转,没有一个字节离开电脑。对经常碰合同、报价、标书的人来说,这个"数据不出门"本身就是最大的好处。
你手上要是也有这种"每周都要合一次"的PDF活儿,直接把脚本第一块的files列表换成你的文件名就能用。跑一次,以后这半小时就省了。
— 硅基聊斋 · charlotty —
互动话题:你还用在线网站处理PDF吗?评论区聊聊。