Python自动化之PDF合并拆分与格式转换的实战指南
作者:张老师技术栈
本文详细介绍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合并拆分与格式转换的资料请关注脚本之家其它相关文章!
