当前位置:首页>python>Python零基础入门(十四):Python操作PDF

Python零基础入门(十四):Python操作PDF

  • 2026-10-11 06:12:33
Python零基础入门(十四):Python操作PDF

Python操作PDF:别再手动复制粘贴了,20行代码搞定合并拆分

上周老板扔给我一个需求:把10份合同PDF合并成一个文件,还要给每页加上公司水印。

我问行政小妹之前怎么做的,她说手动用Adobe Acrobat一页页复制。

10个文件。手动。每次还要对齐。

我打开编辑器,写了不到20行代码,3秒跑完。她看我的眼神像看魔术师。

今天就把这套方法讲透,你也能做到。


为什么选 PyPDF2 和 pdfplumber?

Python 操作 PDF 的库有好几个,我直接说结论:根据需求选,别只认一个。

  • • PyPDF2:老牌库,擅长合并、拆分、旋转、加密等页面操作,轻量但文本提取较弱
  • • pdfplumber:文本提取神器,能精确定位文字、提取表格,适合数据抓取场景
  • • reportlab:生成PDF的王者,能从零创建带格式的文档,但读取能力一般
  • • pymupdf (fitz):全能型选手,读写、渲染、OCR都行,但安装稍复杂

新手建议先装两个:

pip install PyPDF2 pdfplumber

装完就能用,不需要额外配置。


先搞懂 PDF 的"术语"

操作 PDF 之前,得先知道代码里的东西对应文件里的哪个位置:

代码里的叫法
PDF 里对应什么
一句话解释
PdfReader
整个 PDF 文件
读取模式打开
PdfWriter
输出用的 PDF 容器
往里面塞页面再保存
PageObject
单页内容
一个页面对象,包含文字、图片、元数据
Page.extract_text()
提取文字
把一页的内容变成字符串
Page.merge_page()
合并页面
把两个页面的内容叠在一起

读写基础:5 分钟上手

读取 PDF 信息

from PyPDF2 import PdfReaderreader = PdfReader('合同.pdf')print(f'页数:{len(reader.pages)}')print(f'标题:{reader.metadata.title}')first_page = reader.pages[0]text = first_page.extract_text()print(text[:500])

提取所有页的文字

from PyPDF2 import PdfReaderreader = PdfReader('报告.pdf')all_text = []for i, page in enumerate(reader.pages):    text = page.extract_text()    all_text.append(f'--- 第 {i+1} 页 ---\n{text}')with open('报告全文.txt', 'w', encoding='utf-8') as f:    f.write('\n'.join(all_text))print('提取完成!')

extract_text() 这个方法很关键。不加它,你拿到的是 PageObject 对象,还得再处理才能拿到文字。直接调用省一半代码。


表格提取:用 pdfplumber 精准抓取

PyPDF2 提取文字还行,但表格数据经常乱成一锅粥。

这时候换 pdfplumber,它能识别表格结构:

import pdfplumberwith pdfplumber.open('财务报表.pdf') as pdf:    first_page = pdf.pages[0]    tables = first_page.extract_tables()    for row in tables[0]:        print(row)    # ['项目', '金额', '占比']    # ['工资', '50000', '50%']

extract_tables() 返回的是二维列表,每个子列表是一行。直接就是结构化数据,省得自己解析。


合并 PDF:最常用的操作

from PyPDF2 import PdfMergermerger = PdfMerger()merger.append('1月报告.pdf')merger.append('2月报告.pdf', pages=[0, 2])merger.append('3月报告.pdf', pages=(0, 5))merger.write('Q1报告汇总.pdf')merger.close()print('合并完成!')

封装成函数,合并整个文件夹:

from pathlib import Pathdef merge_pdfs_in_folder(folder, output='合并结果.pdf'):    merger = PdfMerger()    pdf_files = sorted(Path(folder).glob('*.pdf'))    for pdf in pdf_files:        if pdf.name == output:            continue        merger.append(str(pdf))    merger.write(output)    merger.close()    print(f'合并了 {len(pdf_files)} 个文件')merge_pdfs_in_folder('./合同文件夹/')

拆分 PDF:按页提取

把 100 页的报告拆成每 10 页一个文件:

from PyPDF2 import PdfReader, PdfWriterreader = PdfReader('年度报告.pdf')total_pages = len(reader.pages)for start in range(0, total_pages, 10):    writer = PdfWriter()    end = min(start + 10, total_pages)    for page_num in range(start, end):        writer.add_page(reader.pages[page_num])    filename = f'报告_第{start+1}-{end}页.pdf'    with open(filename, 'wb') as f:        writer.write(f)    print(f'已生成: {filename}')

踩坑提醒:PdfWriter 每次循环都要新建一个,不然页面会累加。


添加水印:保护文档

from PyPDF2 import PdfReader, PdfWriterdef add_watermark(input_pdf, watermark_pdf, output_pdf):    reader = PdfReader(input_pdf)    watermark_reader = PdfReader(watermark_pdf)    watermark_page = watermark_reader.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')

注意:水印 PDF 必须是透明背景的单页 PDF,不然会把原内容盖住。


加密解密:保护敏感信息

from PyPDF2 import PdfReader, PdfWriterreader = PdfReader('薪资表.pdf')writer = PdfWriter()for page in reader.pages:    writer.add_page(page)writer.encrypt('123456')with open('薪资表_加密.pdf', 'wb') as f:    writer.write(f)print('加密完成!密码是: 123456')

解密:

reader = PdfReader('薪资表_加密.pdf')if reader.is_encrypted:    reader.decrypt('123456')text = reader.pages[0].extract_text()print(text)

完整实战:批量处理合同

回到开头的需求——合并合同并加水印:

from PyPDF2 import PdfMerger, PdfReader, PdfWriterfrom pathlib import Pathdef process_contracts(folder, watermark_pdf, output='合同汇总.pdf'):    # 1. 合并所有合同    merger = PdfMerger()    pdf_files = sorted(Path(folder).glob('*.pdf'))    for pdf in pdf_files:        if pdf.name == output or pdf.name == watermark_pdf:            continue        merger.append(str(pdf))    merged_file = 'temp_merged.pdf'    merger.write(merged_file)    merger.close()    # 2. 添加水印    reader = PdfReader(merged_file)    watermark = PdfReader(watermark_pdf).pages[0]    writer = PdfWriter()    for page in reader.pages:        page.merge_page(watermark)        writer.add_page(page)    # 3. 保存最终文件    with open(output, 'wb') as f:        writer.write(f)    Path(merged_file).unlink()    print(f'处理完成,共 {len(pdf_files)-1} 份合同')process_contracts('./合同/', '水印.pdf')

写在最后

Python 操作 PDF 这件事,会了就是生产力翻倍,不会就是加班到头秃。

最新文章

随机文章