← 返回工具清单 | 首页

Python 批量合并 PDF + 按原文件拆分还原

2026-10-09 · 本文所有输出均为作者在本机真实运行结果

报销季最常见的两件事:一是把十几张发票 PDF 合并成一个交上去;二是交完之后财务说"麻烦按每张发票拆回单独文件",而原文件已经被你删了、只剩那个大 PDF。手动拖拽既慢又容易错页。这篇把两个方向一次写清:合并 和 按页数拆回。

为什么"拆"比"合"更容易翻车

合并只是页的堆叠,无序无脑。难的是拆——你必须知道"哪些页属于哪份原文件"。有两种可靠依据:按已知页数切(你要先记录每份文件几页),或者 按书签/分隔页切。本文先给最通用的按页数切法,附完整可跑脚本。

完整脚本(pypdf)

from pypdf import PdfWriter, PdfReader
import json

def merge(files, out="merged.pdf"):
    w = PdfWriter()
    counts = []
    for f in files:
        r = PdfReader(f)
        for pg in r.pages:
            w.add_page(pg)
        counts.append(len(r.pages))          # 记录每份的页数,拆回时要用
    w.write(out)
    return counts

def split_by_counts(src, counts, names, out_dir="out"):
    import os
    os.makedirs(out_dir, exist_ok=True)
    r = PdfReader(src)
    start = 0
    for name, cnt in zip(names, counts):
        w = PdfWriter()
        for pg in r.pages[start:start + cnt]:
            w.add_page(pg)
        w.write(os.path.join(out_dir, name))
        start += cnt

counts = merge(["发票-1.pdf", "发票-2.pdf", "发票-3.pdf"])
print("每份页数:", counts)

实测:3 份共 9 页,合了再拆,逐页对齐

测试文件页数分别是 2、3、4 页,合并后总页数 9。按 counts 拆回后逐页检查内容:

made: ['发票-1.pdf', '发票-2.pdf', '发票-3.pdf']
merged pages: 9
split pages: 9
page1 text: ■■■■ 1
page2 text: doc1 page2
page4 text: doc2 page2

第 1 页来自原文件 1、第 2 页是原文件 1 的第 2 页、第 4 页正好是"文件 2 的第 2 页"——说明切的边界完全对上了(2 页 + 3 页 + 4 页)。第 1 页中文显示成方块是 reportlab 测试字体缺中文所致,与你合并的真实文件无关。

拆页的两个前提(否则会错页)

3 个真坑

💡 PDF 还有更刁钻的变体(按书签批量拆、扫描件加页码、提取指定页范围、合并后加书签),脚本类 19.9 元起,交付前先在你给的真实文件上跑通。
看看服务与价格 → 虚拟物品交付后不退款,未达承诺免费重做。