Python PDF 操作:PyPDF2 和 reportlab 的高级用法
大家好,今天我们深入探讨 Python 中处理 PDF 文件的两个强大库:PyPDF2 和 reportlab。PyPDF2 主要用于读取、分割、合并和修改现有的 PDF 文件,而 reportlab 则侧重于从头开始创建 PDF 文档。我们将介绍它们的高级用法,包括加密解密、水印添加、复杂布局设计以及动态内容生成。
一、PyPDF2 的高级用法
PyPDF2 是一个纯 Python 库,可以轻松地处理 PDF 文件。它提供了 Reader 和 Writer 对象,分别用于读取和写入 PDF 文件。
1. PDF 加密与解密
PyPDF2 可以对 PDF 文件进行加密和解密,保护敏感信息。
- 加密 PDF 文件:
import PyPDF2
def encrypt_pdf(input_path, output_path, password):
"""
加密 PDF 文件。
Args:
input_path: 输入 PDF 文件路径。
output_path: 输出加密后的 PDF 文件路径。
password: 加密密码。
"""
with open(input_path, 'rb') as input_file:
reader = PyPDF2.PdfReader(input_file)
writer = PyPDF2.PdfWriter()
for page in reader.pages:
writer.add_page(page)
writer.encrypt(password)
with open(output_path, 'wb') as output_file:
writer.write(output_file)
# 示例
encrypt_pdf('input.pdf', 'encrypted.pdf', 'secret_password')
- 解密 PDF 文件:
import PyPDF2
def decrypt_pdf(input_path, output_path, password):
"""
解密 PDF 文件。
Args:
input_path: 输入加密的 PDF 文件路径。
output_path: 输出解密后的 PDF 文件路径。
password: 解密密码。
"""
with open(input_path, 'rb') as input_file:
reader = PyPDF2.PdfReader(input_file)
if reader.is_encrypted:
reader.decrypt(password)
writer = PyPDF2.PdfWriter()
for page in reader.pages:
writer.add_page(page)
with open(output_path, 'wb') as output_file:
writer.write(output_file)
else:
print("PDF is not encrypted.")
# 示例
decrypt_pdf('encrypted.pdf', 'decrypted.pdf', 'secret_password')
2. 添加水印
在 PDF 文件中添加水印可以保护版权或标识文件。
import PyPDF2
def add_watermark(input_path, watermark_path, output_path):
"""
向 PDF 文件添加水印。
Args:
input_path: 输入 PDF 文件路径。
watermark_path: 水印 PDF 文件路径。
output_path: 输出添加水印后的 PDF 文件路径。
"""
with open(input_path, 'rb') as input_file, open(watermark_path, 'rb') as watermark_file:
input_reader = PyPDF2.PdfReader(input_file)
watermark_reader = PyPDF2.PdfReader(watermark_file)
watermark_page = watermark_reader.pages[0]
writer = PyPDF2.PdfWriter()
for page in input_reader.pages:
page.merge_page(watermark_page)
writer.add_page(page)
with open(output_path, 'wb') as output_file:
writer.write(output_file)
# 示例
add_watermark('input.pdf', 'watermark.pdf', 'watermarked.pdf')
其中 watermark.pdf
应该是一个包含单个页面的 PDF 文件,该页面包含水印内容。
3. 从 PDF 中提取文本
PyPDF2 可以提取 PDF 文件中的文本内容。
import PyPDF2
def extract_text_from_pdf(pdf_path):
"""
从 PDF 文件中提取文本。
Args:
pdf_path: PDF 文件路径。
Returns:
提取的文本内容。
"""
text = ""
with open(pdf_path, 'rb') as file:
reader = PyPDF2.PdfReader(file)
for page in reader.pages:
text += page.extract_text()
return text
# 示例
text = extract_text_from_pdf('input.pdf')
print(text)
4. PDF 文件分割
将一个 PDF 文件分割成多个文件。
import PyPDF2
def split_pdf(input_path, output_prefix):
"""
将 PDF 文件分割成多个文件。
Args:
input_path: 输入 PDF 文件路径。
output_prefix: 输出文件名前缀。
"""
with open(input_path, 'rb') as input_file:
reader = PyPDF2.PdfReader(input_file)
for i, page in enumerate(reader.pages):
writer = PyPDF2.PdfWriter()
writer.add_page(page)
output_path = f"{output_prefix}_{i+1}.pdf"
with open(output_path, 'wb') as output_file:
writer.write(output_file)
# 示例
split_pdf('input.pdf', 'split_page')
二、reportlab 的高级用法
reportlab 是一个强大的库,用于从头开始创建复杂的 PDF 文档。它提供了丰富的 API,可以控制文档的布局、字体、颜色和图像。
1. 创建基本 PDF 文档
首先,我们创建一个简单的 PDF 文档。
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
def create_basic_pdf(output_path):
"""
创建一个基本的 PDF 文档。
Args:
output_path: 输出 PDF 文件路径。
"""
c = canvas.Canvas(output_path, pagesize=letter)
c.drawString(inch, 10.5 * inch, "Hello, ReportLab!")
c.save()
# 示例
create_basic_pdf('basic.pdf')
2. 使用 Paragraph 进行文本排版
Paragraph 对象可以处理更复杂的文本排版,例如换行、对齐和样式。
from reportlab.platypus import SimpleDocTemplate, Paragraph
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import inch
def create_paragraph_pdf(output_path):
"""
使用 Paragraph 创建 PDF 文档。
Args:
output_path: 输出 PDF 文件路径。
"""
doc = SimpleDocTemplate(output_path, pagesize='A4')
styles = getSampleStyleSheet()
story = []
text = "This is a long paragraph of text that will be wrapped automatically. " * 20
p = Paragraph(text, styles['Normal'])
story.append(p)
doc.build(story)
# 示例
create_paragraph_pdf('paragraph.pdf')
3. 使用 Table 创建表格
Table 对象可以创建表格,并控制单元格的样式和内容。
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle
from reportlab.lib import colors
def create_table_pdf(output_path):
"""
使用 Table 创建 PDF 文档。
Args:
output_path: 输出 PDF 文件路径。
"""
doc = SimpleDocTemplate(output_path, pagesize='A4')
story = []
data = [
['Header 1', 'Header 2', 'Header 3'],
['Row 1, Col 1', 'Row 1, Col 2', 'Row 1, Col 3'],
['Row 2, Col 1', 'Row 2, Col 2', 'Row 2, Col 3']
]
table = Table(data)
table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
('GRID', (0, 0), (-1, -1), 1, colors.black)
]))
story.append(table)
doc.build(story)
# 示例
create_table_pdf('table.pdf')
4. 使用 Canvas 进行绘图
Canvas 对象允许直接在 PDF 页面上进行绘图,可以创建各种图形和图表。
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
def create_drawing_pdf(output_path):
"""
使用 Canvas 进行绘图创建 PDF 文档。
Args:
output_path: 输出 PDF 文件路径。
"""
c = canvas.Canvas(output_path, pagesize=letter)
c.setFillColor(colors.blue)
c.rect(100, 100, 200, 100, fill=1) # x, y, width, height
c.setFillColor(colors.red)
c.circle(200, 300, 50, fill=1) # x, y, radius
c.save()
# 示例
create_drawing_pdf('drawing.pdf')
5. 添加图像
将图像添加到 PDF 文件中。
from reportlab.platypus import SimpleDocTemplate, Image
from reportlab.lib.pagesizes import letter
def create_image_pdf(output_path, image_path):
"""
添加图像到 PDF 文档。
Args:
output_path: 输出 PDF 文件路径。
image_path: 图像文件路径。
"""
doc = SimpleDocTemplate(output_path, pagesize=letter)
story = []
img = Image(image_path, width=200, height=100) # 调整图像大小
story.append(img)
doc.build(story)
# 示例
create_image_pdf('image.pdf', 'image.jpg') # 替换为你的图像文件路径
6. 生成动态内容
reportlab 可以根据数据动态生成 PDF 文档。例如,从数据库或 CSV 文件中读取数据,并将其添加到 PDF 表格中。
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle
from reportlab.lib import colors
def create_dynamic_table_pdf(output_path, data):
"""
使用动态数据创建 PDF 表格。
Args:
output_path: 输出 PDF 文件路径。
data: 表格数据,列表的列表。
"""
doc = SimpleDocTemplate(output_path, pagesize='A4')
story = []
table = Table(data)
table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
('GRID', (0, 0), (-1, -1), 1, colors.black)
]))
story.append(table)
doc.build(story)
# 示例:从 CSV 文件读取数据
import csv
def create_pdf_from_csv(csv_path, pdf_path):
"""
从 CSV 文件读取数据并创建 PDF 文件。
Args:
csv_path: CSV 文件路径。
pdf_path: 输出 PDF 文件路径。
"""
data = []
with open(csv_path, 'r') as csvfile:
reader = csv.reader(csvfile)
for row in reader:
data.append(row)
create_dynamic_table_pdf(pdf_path, data)
create_pdf_from_csv('data.csv', 'dynamic_table.pdf') # 确保 data.csv 文件存在
三、PyPDF2 和 reportlab 的结合使用
可以将 PyPDF2 和 reportlab 结合起来使用,例如,使用 PyPDF2 读取现有 PDF 文件的内容,然后使用 reportlab 创建新的 PDF 文件,并将读取的内容添加到新文件中。或者在用ReportLab生成的内容中,加入已经存在的PDF文件作为背景。
import PyPDF2
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
def combine_pypdf2_and_reportlab(input_pdf_path, output_pdf_path):
"""
结合 PyPDF2 和 reportlab 创建 PDF 文档。
Args:
input_pdf_path: 输入 PDF 文件路径。
output_pdf_path: 输出 PDF 文件路径。
"""
# 1. 使用 PyPDF2 读取现有 PDF 文件
with open(input_pdf_path, 'rb') as input_file:
reader = PyPDF2.PdfReader(input_file)
first_page = reader.pages[0] # 读取第一页
# 2. 使用 reportlab 创建新的 PDF 文件
c = canvas.Canvas(output_pdf_path, pagesize=letter)
# 添加文本
c.drawString(100, 750, "This text is generated by ReportLab.")
# 从现有 PDF 复制内容到新的 PDF (将读取到的第一页画到reportlab的canvas上)
c.saveState() #保存当前Canvas状态
c.translate(50,50) #将原点平移到(50,50)
c.scale(0.5,0.5) #缩放0.5倍
c.doFormXobj(first_page) #绘制PDF页面的内容。
c.restoreState() #恢复Canvas状态
# 3. 保存 PDF 文件
c.save()
# 示例
combine_pypdf2_and_reportlab('input.pdf', 'combined.pdf')
这段代码首先使用 PyPDF2
读取 input.pdf
的第一页。然后,它使用 reportlab
创建一个新的 PDF 文件 combined.pdf
,并在其中添加一些文本。 最关键的是c.doFormXobj(first_page)
这句,它将读取的PyPDF2
的Page对象渲染到reportlab的Canvas上。
四、实际应用案例
- 自动生成报告: 从数据库中读取数据,使用 reportlab 创建包含表格、图表和文本的 PDF 报告。
- 批量添加水印: 使用 PyPDF2 批量向 PDF 文件添加公司 logo 或版权声明。
- PDF 文档加密: 使用 PyPDF2 对包含敏感信息的 PDF 文件进行加密,防止未经授权的访问。
- 电子发票生成: 利用ReportLab精确控制布局的能力,结合数据库中的发票数据,生成符合规范的电子发票。
- 简历生成器: 用户填写信息后,利用ReportLab动态生成个性化简历PDF。
五、总结与展望
通过本讲座,我们深入了解了 PyPDF2 和 reportlab 的高级用法,包括加密解密、水印添加、复杂布局设计以及动态内容生成。这两个库在 PDF 处理方面各有优势,可以根据实际需求选择合适的工具。它们的应用场景非常广泛,可以帮助我们自动化生成各种 PDF 文档,提高工作效率。 在未来,随着人工智能和机器学习技术的发展,PDF 处理将更加智能化,例如,自动识别 PDF 文档中的文本和表格,并进行数据提取和分析。
总结
- PyPDF2 擅长处理现有 PDF 文件,如合并、分割、加密等。
- reportlab 擅长从头创建 PDF 文档,可以精细控制页面布局和内容。
- 两者结合使用,可以满足更复杂的 PDF 处理需求。