Python自动化之PDF合并拆分与格式转换的实战指南

 更新时间:2026年07月01日 08:47:45   作者:张老师技术栈  
本文详细介绍PDF的进阶操作,包括合并、拆分、格式互转(PDF转Word、Excel)及批量压缩等user本文详细介绍PDF的进阶操作,包括合并、拆分、格式互转(PDF转Word、Excel)、批量压缩、提取图片及添加水印等功能,帮助处理数百个PDF文件,一键搞定,需要的朋友可以参考下

这篇讲 PDF 的进阶操作——合并、拆分、格式互转(PDF→Word、PDF→Excel)、批量压缩。

一、PDF 合并

把多个 PDF 合并成一个,适合用来汇总报告、合并扫描件。

批量合并整个文件夹

from PyPDF2 import PdfMerger
import os

def merge_all_pdfs(input_dir, output_file):
    """合并整个文件夹下的所有 PDF"""
    merger = PdfMerger()

    # 按文件名排序(保证合并顺序)
    files = sorted([
        f for f in os.listdir(input_dir)
        if f.lower().endswith(".pdf")
    ])

    if not files:
        print("没有找到 PDF 文件")
        return

    for f in files:
        filepath = os.path.join(input_dir, f)
        merger.append(filepath)
        print(f"已添加: {f}")

    merger.write(output_file)
    merger.close()
    print(f"合并完成!共 {len(files)} 个文件 → {output_file}")

# 使用
merge_all_pdfs("待合并的PDF", "汇总结果.pdf")

按指定顺序合并

def merge_selected_pdfs(file_list, output_file):
    """按指定顺序合并 PDF"""
    merger = PdfMerger()

    for f in file_list:
        if os.path.exists(f):
            merger.append(f)
            print(f"已添加: {os.path.basename(f)}")

    merger.write(output_file)
    merger.close()
    print(f"合并完成 → {output_file}")

# 使用:顺序自定义
merge_selected_pdfs([
    "封面.pdf",
    "目录.pdf",
    "正文.pdf",
    "附录.pdf",
], "完整报告.pdf")

二、PDF 拆分

1. 按页数拆分(每 N 页一份)

from PyPDF2 import PdfReader, PdfWriter
import os

def split_by_pages(input_file, output_dir, pages_per_file=10):
    """
    按每 N 页一组拆分 PDF
    适合:把几百页的 PDF 拆成多份小文件
    """
    os.makedirs(output_dir, exist_ok=True)
    reader = PdfReader(input_file)
    total = len(reader.pages)
    file_index = 1

    for start in range(0, total, pages_per_file):
        writer = PdfWriter()
        end = min(start + pages_per_file, total)

        for i in range(start, end):
            writer.add_page(reader.pages[i])

        output = os.path.join(
            output_dir,
            f"第{file_index}部分_第{start+1}-{end}页.pdf"
        )

        with open(output, "wb") as f:
            writer.write(f)

        print(f"已生成: {os.path.basename(output)} ({end-start}页)")
        file_index += 1

    print(f"拆分完成,共 {file_index - 1} 个文件")

# 使用:每 20 页拆一份
split_by_pages("大文件.pdf", "拆分输出", pages_per_file=20)

2. 提取指定页面

def extract_pages(input_file, output_file, page_numbers):
    """
    提取 PDF 中的指定页码范围
    page_numbers: 从 1 开始的页号列表,如 [1, 3, 5] 或 range(1, 6)
    """
    reader = PdfReader(input_file)
    writer = PdfWriter()

    for i in page_numbers:
        # page_numbers 从 1 开始,reader 从 0 开始
        writer.add_page(reader.pages[i - 1])

    with open(output_file, "wb") as f:
        writer.write(f)

    print(f"已提取 {len(page_numbers)} 页 → {output_file}")

# 使用
extract_pages("报告.pdf", "摘要.pdf", [1, 2, 3])     # 提取前 3 页
extract_pages("报告.pdf", "附录.pdf", range(48, 55))  # 提取第 48-54 页

三、PDF 转 Word

方法一:pdfplumber + python-docx(文字型 PDF)

import pdfplumber
from docx import Document

def pdf_to_word(pdf_path, word_path):
    """文字型 PDF 转 Word(保留文本)"""
    doc = Document()

    with pdfplumber.open(pdf_path) as pdf:
        for page in pdf.pages:
            text = page.extract_text()
            if text:
                doc.add_paragraph(text.strip())

    doc.save(word_path)
    print(f"转换完成: {word_path}")

# 使用
pdf_to_word("报告.pdf", "报告.docx")

方法二:pdf2docx(保留格式,推荐)

pip install pdf2docx
from pdf2docx import Converter

def pdf_to_word_with_format(pdf_path, word_path):
    """PDF 转 Word(保留表格、排版)"""
    cv = Converter(pdf_path)
    cv.convert(word_path, start=0, end=None)
    cv.close()
    print(f"转换完成: {word_path}")

# 使用
pdf_to_word_with_format("报告.pdf", "报告.docx")

pdf2docx 的转换质量更高,能保留表格和基本排版。如果遇到表格多的 PDF,优先用这个。

四、PDF 转 Excel(提取表格)

import pdfplumber
import pandas as pd

def pdf_tables_to_excel(pdf_path, excel_path):
    """从 PDF 中提取所有表格并导出到 Excel"""
    with pdfplumber.open(pdf_path) as pdf:
        all_tables = []

        for page_num, page in enumerate(pdf.pages, 1):
            tables = page.extract_tables()
            for table_idx, table in enumerate(tables, 1):
                # 第一行为表头
                df = pd.DataFrame(
                    table[1:],
                    columns=table[0] if table else None
                )
                all_tables.append({
                    "sheet_name": f"第{page_num}页_表格{table_idx}",
                    "data": df
                })
                print(f"第 {page_num} 页找到表格{table_idx},{len(table)}行×{len(table[0])}列")

    # 写入 Excel(每个表格一个 sheet)
    with pd.ExcelWriter(excel_path) as writer:
        for t in all_tables:
            sheet = t["sheet_name"][:31]  # Excel sheet 名最长 31 字符
            t["data"].to_excel(writer, sheet_name=sheet, index=False)

    print(f"导出完成,共 {len(all_tables)} 个表格 → {excel_path}")

# 使用
pdf_tables_to_excel("财务报表.pdf", "财务报表数据.xlsx")

五、PDF 压缩

pip install pypdf
from pypdf import PdfReader, PdfWriter

def compress_pdf(input_path, output_path):
    """压缩 PDF 文件大小"""
    reader = PdfReader(input_path)
    writer = PdfWriter()

    for page in reader.pages:
        writer.add_page(page)

    # 压缩内容流
    for page in writer.pages:
        page.compress_content_streams()

    with open(output_path, "wb") as f:
        writer.write(f)

    original_size = os.path.getsize(input_path)
    compressed_size = os.path.getsize(output_path)
    ratio = (1 - compressed_size / original_size) * 100

    print(f"压缩完成: {original_size//1024}KB → {compressed_size//1024}KB (压缩 {ratio:.0f}%)")

def batch_compress(input_dir, output_dir):
    """批量压缩 PDF"""
    os.makedirs(output_dir, exist_ok=True)

    for f in os.listdir(input_dir):
        if not f.lower().endswith(".pdf"):
            continue

        input_path = os.path.join(input_dir, f)
        output_path = os.path.join(output_dir, f)
        compress_pdf(input_path, output_path)

# 使用
batch_compress("原始PDF", "压缩后PDF")

六、PDF 提取图片

import zipfile
import os
from PIL import Image

def extract_images_from_pdf(pdf_path, output_dir):
    """从 PDF 中提取所有图片"""
    os.makedirs(output_dir, exist_ok=True)

    # PDF 本质上是 ZIP 文件,图片在 word/media 目录下
    with zipfile.ZipFile(pdf_path, "r") as z:
        image_count = 0
        for name in z.namelist():
            if name.startswith("word/media/") or name.startswith("media/"):
                ext = os.path.splitext(name)[1].lower()
                if ext in (".png", ".jpg", ".jpeg", ".gif", ".tiff"):
                    # 提取图片
                    z.extract(name, output_dir)
                    # 重命名到根目录
                    src = os.path.join(output_dir, name)
                    dst = os.path.join(output_dir, f"image_{image_count}{ext}")
                    os.rename(src, dst)
                    image_count += 1

    # 清理空目录
    for root, dirs, files in os.walk(output_dir, topdown=False):
        if not files and not dirs:
            os.rmdir(root)

    print(f"提取完成,共 {image_count} 张图片 → {output_dir}")

# 使用
extract_images_from_pdf("带图片的文档.pdf", "提取的图片")

七、PDF 添加水印

from PyPDF2 import PdfReader, PdfWriter

def add_watermark(input_pdf, watermark_pdf, output_pdf):
    """给 PDF 每一页添加水印"""
    reader = PdfReader(input_pdf)
    watermark = PdfReader(watermark_pdf)
    watermark_page = watermark.pages[0]

    writer = PdfWriter()

    for page in reader.pages:
        page.merge_page(watermark_page)
        writer.add_page(page)

    with open(output_pdf, "wb") as f:
        writer.write(f)

    print(f"水印添加完成 → {output_pdf}")

# 使用
add_watermark("合同.pdf", "水印.pdf", "合同_带水印.pdf")

八、批处理完整模板

import os
from PyPDF2 import PdfReader, PdfWriter, PdfMerger

class PDFBatchProcessor:
    """PDF 批量处理器"""

    def __init__(self, input_dir, output_dir):
        self.input_dir = input_dir
        self.output_dir = output_dir
        os.makedirs(output_dir, exist_ok=True)

    def get_pdf_files(self):
        """获取所有 PDF 文件"""
        return [
            f for f in os.listdir(self.input_dir)
            if f.lower().endswith(".pdf")
        ]

    def merge_all(self, output="合并结果.pdf"):
        """合并所有 PDF"""
        files = self.get_pdf_files()
        merger = PdfMerger()
        for f in sorted(files):
            merger.append(os.path.join(self.input_dir, f))
        merger.write(os.path.join(self.output_dir, output))
        merger.close()
        print(f"合并 {len(files)} 个文件 → {output}")

    def split_all(self, pages_per_file=10):
        """批量拆分每个 PDF"""
        for f in self.get_pdf_files():
            input_path = os.path.join(self.input_dir, f)
            name = os.path.splitext(f)[0]
            sub_dir = os.path.join(self.output_dir, name)
            os.makedirs(sub_dir, exist_ok=True)

            reader = PdfReader(input_path)
            total = len(reader.pages)

            for start in range(0, total, pages_per_file):
                writer = PdfWriter()
                end = min(start + pages_per_file, total)
                for i in range(start, end):
                    writer.add_page(reader.pages[i])

                output = os.path.join(
                    sub_dir,
                    f"{name}_p{start+1}-{end}.pdf"
                )
                with open(output, "wb") as f_out:
                    writer.write(f_out)

            print(f"{f}: {total}页 → {sub_dir}/")

    def rotate_all(self, rotation=90):
        """批量旋转所有 PDF 页面"""
        for f in self.get_pdf_files():
            input_path = os.path.join(self.input_dir, f)
            output_path = os.path.join(self.output_dir, f"rotated_{f}")

            reader = PdfReader(input_path)
            writer = PdfWriter()

            for page in reader.pages:
                page.rotate(rotation)
                writer.add_page(page)

            with open(output_path, "wb") as f_out:
                writer.write(f_out)

            print(f"旋转完成: {f}")

# 使用
processor = PDFBatchProcessor("输入PDF", "输出PDF")
processor.merge_all()        # 合并
# processor.split_all(5)     # 拆分(每5页一份)
# processor.rotate_all(90)   # 旋转(顺时针90度)

总结

PDF 处理的常见需求基本都覆盖了:

合并 → PdfMerger.append()
拆分 → PdfWriter 按页提取
转Word → pdf2docx
转Excel → pdfplumber 提取表格
压缩 → pypdf compress_content_streams
水印 → merge_page()
提取图片 → zipfile 解压

遇到批量处理时,把需要的功能组合成一个函数,一条命令搞定几百个 PDF。

以上就是Python自动化之PDF合并拆分与格式转换的实战指南的详细内容,更多关于Python PDF合并拆分与格式转换的资料请关注脚本之家其它相关文章!

相关文章

  • Python实现简单飞机大战

    Python实现简单飞机大战

    这篇文章主要为大家详细介绍了Python实现简单飞机大战,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • python+selenium的web自动化上传操作的实现

    python+selenium的web自动化上传操作的实现

    这篇文章主要介绍了python+selenium的web自动化上传操作的实现,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-08-08
  • 简单示例入门了解WxPython教程

    简单示例入门了解WxPython教程

    这篇文章主要通过演示简单示例带大家入门了解WxPython,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • Python中pyCirclize包的使用教程详解

    Python中pyCirclize包的使用教程详解

    pyCirclize 是一个 Python 包,用于绘制环形图,这篇文章将将提供更丰富的示例代码,以更全面地展示 pyCirclize 包的功能和用法,感兴趣的小伙伴可以了解一下
    2023-11-11
  • python Django框架实现自定义表单提交

    python Django框架实现自定义表单提交

    这篇文章主要为大家详细介绍了Django框架实现自定义表单提交,针对"表单提交"和"Ajax提交"两种方式来解决CSRF带来的错误进行讲解,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • Python测试函数出现AssertionError:None != ‘Janis Joplin‘问题及解决

    Python测试函数出现AssertionError:None != ‘Janis Joplin‘问题及解决

    这篇文章主要介绍了Python测试函数出现AssertionError:None != ‘Janis Joplin‘问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • 使用Python的requests库来发送HTTP请求的操作指南

    使用Python的requests库来发送HTTP请求的操作指南

    使用 Python 的 requests 库发送 HTTP 请求是非常简单和直观的,requests 库提供了丰富的 API,可以发送各种类型的 HTTP 请求,下面我会介绍一些常用的 HTTP 请求方式,并提供实际的代码示例,需要的朋友可以参考下
    2025-08-08
  • Python文本相似度计算的方法大全

    Python文本相似度计算的方法大全

    文本相似度是指两个文本在内容、结构或语义上的相近程度,通常用0到1之间的数值表示,0表示完全不同,1表示完全相同,本文将深入解析多种文本相似度计算方法,帮助您选择最适合的算法,需要的朋友可以参考下
    2025-08-08
  • 浅析python中的二元嵌套列表分组

    浅析python中的二元嵌套列表分组

    这篇文章主要来和大家一起讨论一下Python中的二元嵌套列表,并将每个嵌套列表元素相对于其其他索引元素进行分组,感兴趣的小伙伴可以学习一下
    2023-09-09
  • 利用Python为女神制作一个专属网站

    利用Python为女神制作一个专属网站

    520不知道送什么礼物?快跟随小编一起学习一下如何利用Python语言制作一个专属的网站送给女神吧!文中的示例代码讲解详细,需要的可以参考一下
    2022-05-05

最新评论