Python 处理 PDF 文件(PyPDF2, ReportLab)

2024-08-29 11:04

本文主要是介绍Python 处理 PDF 文件(PyPDF2, ReportLab),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Python 是一门强大的编程语言,在处理PDF文件方面有着丰富的库支持,其中最常用的两个库是 PyPDF2ReportLabPyPDF2 主要用于读取、拆分、合并和修改已有的PDF文件,而 ReportLab 则擅长生成新的PDF文件。

一、PyPDF2

1. PyPDF2 概述

PyPDF2 是一个纯 Python 库,主要用于操作已有的 PDF 文件。它的功能包括从 PDF 中提取文本、合并多个 PDF 文件、拆分 PDF 文件、旋转页面、添加书签和注释等。然而,由于 PDF 文件格式复杂,PyPDF2 在处理某些复杂或加密的 PDF 文件时可能会遇到限制。

2. 安装 PyPDF2

在使用 PyPDF2 之前,你需要确保已安装它。可以通过 pip 安装:

pip install PyPDF2

3. PyPDF2 的基本操作

3.1 读取 PDF 文件

PyPDF2 提供了 PdfReader 类来读取 PDF 文件。你可以通过以下代码读取一个 PDF 文件:

from PyPDF2 import PdfReader# 打开 PDF 文件
with open('example.pdf', 'rb') as file:reader = PdfReader(file)# 获取 PDF 文件的总页数num_pages = len(reader.pages)print(f"Total pages: {num_pages}")# 提取第1页的文本内容page = reader.pages[0]text = page.extract_text()print(text)
3.2 合并 PDF 文件

PyPDF2 可以将多个 PDF 文件合并为一个新文件。使用 PdfWriter 类来完成此操作:

from PyPDF2 import PdfReader, PdfWriter# 创建 PdfWriter 对象
writer = PdfWriter()# 读取并添加 PDF 文件
pdf_files = ['file1.pdf', 'file2.pdf']
for pdf_file in pdf_files:reader = PdfReader(pdf_file)for page in reader.pages:writer.add_page(page)# 输出合并后的文件
with open('merged.pdf', 'wb') as output_file:writer.write(output_file)
3.3 拆分 PDF 文件

拆分 PDF 文件意味着将一个 PDF 文件的每一页保存为单独的文件:

from PyPDF2 import PdfReader, PdfWriter# 读取 PDF 文件
with open('example.pdf', 'rb') as file:reader = PdfReader(file)# 循环遍历每一页并创建一个新的 PDF 文件for i, page in enumerate(reader.pages):writer = PdfWriter()writer.add_page(page)# 保存单独的页面为新 PDF 文件output_filename = f'page_{i + 1}.pdf'with open(output_filename, 'wb') as output_file:writer.write(output_file)
3.4 旋转 PDF 页面

有时你可能需要旋转 PDF 文件中的某一页或所有页面。以下是旋转 PDF 页面的方法:

from PyPDF2 import PdfReader, PdfWriter# 打开 PDF 文件
with open('example.pdf', 'rb') as file:reader = PdfReader(file)writer = PdfWriter()# 旋转第一页 90 度page = reader.pages[0]rotated_page = page.rotate_clockwise(90)# 添加旋转后的页面到 PdfWriterwriter.add_page(rotated_page)# 保存新的 PDF 文件with open('rotated.pdf', 'wb') as output_file:writer.write(output_file)
3.5 添加书签和注释

虽然 PyPDF2 支持添加书签和注释,但其功能较为有限,而且操作相对复杂。PyPDF2 能够处理简单的书签和注释添加,但对于更复杂的需求,可能需要结合其他库。

4. PyPDF2 的局限性

尽管 PyPDF2 提供了丰富的功能,但它在处理一些复杂的 PDF 文件时可能会遇到问题,例如无法正确提取嵌入图像或复杂布局中的文本。此外,PyPDF2 的文本提取功能也有其局限性,尤其是在处理非英文文本时,可能无法准确提取。

二、ReportLab

1. ReportLab 概述

ReportLab 是一个强大的 Python 库,用于生成 PDF 文档。与 PyPDF2 侧重于操作已有的 PDF 文件不同,ReportLab 主要用于创建新 PDF 文件。它可以生成高质量的文档,支持丰富的文本样式、图表、图像和其他元素的插入。

2. 安装 ReportLab

PyPDF2 类似,你可以使用 pip 来安装 ReportLab

pip install reportlab

3. ReportLab 的基本操作

3.1 创建一个简单的 PDF 文件

使用 ReportLab 创建 PDF 文件通常涉及到 canvas.Canvas 类。以下是一个简单的例子,创建一个包含文本和图像的 PDF 文件:

from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas# 创建一个 PDF 文件
pdf_file = "example.pdf"
c = canvas.Canvas(pdf_file, pagesize=A4)# 添加文本
c.drawString(100, 800, "Hello, World!")# 添加图像
c.drawImage("example.jpg", 100, 700, width=200, height=100)# 保存 PDF
c.save()
3.2 创建复杂的文档

除了基本的文本和图像,ReportLab 还支持创建复杂的文档,例如带有多种字体、表格、图形、分栏布局等的文档。以下是一个创建带表格的 PDF 的例子:

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import inch
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle# 创建 PDF 文件
pdf_file = "table_example.pdf"
doc = SimpleDocTemplate(pdf_file, pagesize=A4)# 创建表格数据
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)# 添加样式
style = 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),
])
table.setStyle(style)# 构建 PDF
doc.build([table])
3.3 添加不同的字体和样式

ReportLab 提供了丰富的字体和样式选择,使得你可以创建具有各种排版效果的 PDF 文件:

from reportlab.lib import colors
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer# 创建 PDF 文件
pdf_file = "styled_text.pdf"
doc = SimpleDocTemplate(pdf_file, pagesize=letter)# 获取样式表
styles = getSampleStyleSheet()# 自定义样式
custom_style = ParagraphStyle(name="CustomStyle",fontName="Helvetica-Bold",fontSize=14,leading=16,textColor=colors.red,alignment=1,  # 中心对齐
)# 创建带样式的文本段落
story = []
text = "This is a styled paragraph."
story.append(Paragraph(text, custom_style))
story.append(Spacer(1, 12))  # 添加间隔# 构建 PDF
doc.build(story)
3.4 插入图表

ReportLab 还支持生成和插入各种类型的图表,例如柱状图、饼图等。这些图表可以与其他文档元素无缝集成在一起:

from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate
from reportlab.graphics.shapes import Drawing
from reportlab.graphics.charts.barcharts import VerticalBarChart
from reportlab.graphics.charts.textlabels import Label# 创建 PDF 文件
pdf_file = "chart_example.pdf"
doc = SimpleDocTemplate(pdf_file, pagesize=letter)# 创建图表数据
data = [(13, 5, 20, 22, 37, 45, 19, 4),(14, 6, 21, 23, 38, 46, 20, 5),
]# 创建绘图对象
drawing = Drawing(400, 200)# 创建柱状图
chart = VerticalBarChart()
chart.x = 50
chart.y = 50
chart.height = 125
chart.width = 300
chart.data = data
chart.strokeColor = colors.black# 添加标签
chart.valueAxis.valueMin = 0
chart.valueAxis.valueMax = 50
chart.valueAxis.valueStep = 10
chart.categoryAxis.labels.boxAnchor = 'ne'
chart.categoryAxis.labels.dx = 8
chart.categoryAxis.labels.dy = -2
chart.categoryAxis.labels.angle = 30
chart.categoryAxis.categoryNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug']# 添加标题
title = Label()
title.setOrigin(200, 180)
title.setText("Monthly Data")
drawing.add(title)drawing.add(chart)# 构建 PDF
doc.build([drawing])

4. ReportLab 的扩展与高级功能

ReportLab 还提供了许多扩展功能和高级特性,使得它成为生成复杂 PDF 报告的强大工具。以下是一些 ReportLab 更高级的功能和技巧。

4.1 流式布局(Flowable)

ReportLab 中,流式布局(Flowable)是一种用于在 PDF 文档中插入内容的机制。流式布局元素可以包括段落、图片、表格、图表等。Platypus(Page Layout and Typography Using Scripts)是 ReportLab 提供的一个强大工具,用于将这些流式布局元素组合在一起,生成复杂的文档。

以下是一个包含多个流式布局元素的例子:

from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image
from reportlab.lib.styles import getSampleStyleSheet# 创建 PDF 文件
pdf_file = "flowable_example.pdf"
doc = SimpleDocTemplate(pdf_file, pagesize=letter)# 获取样式表
styles = getSampleStyleSheet()# 创建文档元素
story = []# 添加段落
paragraph = Paragraph("This is a paragraph.", styles['Normal'])
story.append(paragraph)
story.append(Spacer(1, 12))# 添加图片
image = Image("example.jpg")
story.append(image)
story.append(Spacer(1, 12))# 添加另一段落
paragraph = Paragraph("This is another paragraph after the image.", styles['Normal'])
story.append(paragraph)# 构建 PDF
doc.build(story)
4.2 自定义报表生成

在企业环境中,经常需要生成包含公司标志、表格、图表等元素的定制报告。ReportLab 可以通过组合不同的流式布局元素、添加页眉页脚以及插入公司标志来生成此类报告。

以下是一个包含页眉和页脚的自定义报告例子:

from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.platypus.frames import Frame
from reportlab.platypus.doctemplate import PageTemplate
from reportlab.lib.styles import getSampleStyleSheet# 页眉页脚的生成函数
def add_page_number(canvas, doc):page_number_text = f"Page {doc.page}"canvas.drawRightString(200 * mm, 10 * mm, page_number_text)# 自定义的页眉
def header_footer(canvas, doc):canvas.saveState()canvas.setFont('Helvetica', 10)canvas.drawString(inch, 11 * inch, "Company Header")canvas.line(inch, 10.75 * inch, 7.5 * inch, 10.75 * inch)add_page_number(canvas, doc)canvas.restoreState()# 创建 PDF 文件
pdf_file = "custom_report.pdf"
doc = SimpleDocTemplate(pdf_file, pagesize=letter)# 设置页眉页脚模板
frame = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id='normal')
template = PageTemplate(id='test', frames=frame, onPage=header_footer)
doc.addPageTemplates([template])# 获取样式表
styles = getSampleStyleSheet()# 创建内容
story = [Paragraph("This is the content of the report.", styles['Normal']),Spacer(1, 12),Paragraph("More content on the next line.", styles['Normal'])]# 构建 PDF
doc.build(story)

在这个例子中,我们使用 header_footer 函数为每一页添加页眉和页脚。这种方法非常灵活,可以根据具体需求定制不同的页面布局。

4.3 生成图表和插入动态数据

ReportLab 提供的 reportlab.graphics 模块可以生成各种图表,包括柱状图、饼图、折线图等。这些图表可以通过程序动态生成,并插入到 PDF 文档中。例如,你可以从数据库或 API 中获取数据,然后将数据以图表的形式展示在 PDF 中。

以下是生成折线图并插入到 PDF 的示例:

from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate
from reportlab.graphics.shapes import Drawing
from reportlab.graphics.charts.linecharts import HorizontalLineChart
from reportlab.graphics.widgets.markers import makeMarker
from reportlab.lib import colors# 创建 PDF 文件
pdf_file = "line_chart.pdf"
doc = SimpleDocTemplate(pdf_file, pagesize=letter)# 创建图表数据
data = [(10, 20, 30, 40, 50),(15, 25, 35, 45, 55),
]# 创建绘图对象
drawing = Drawing(400, 200)# 创建折线图
chart = HorizontalLineChart()
chart.x = 50
chart.y = 50
chart.height = 125
chart.width = 300
chart.data = data# 配置折线图
chart.lines[0].strokeColor = colors.blue
chart.lines[1].strokeColor = colors.green
chart.lineLabelFormat = '%2.0f'# 添加数据点标记
chart.lines[0].symbol = makeMarker('Circle')
chart.lines[1].symbol = makeMarker('Square')# 设置轴和标签
chart.categoryAxis.categoryNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May']
chart.categoryAxis.labels.boxAnchor = 'n'drawing.add(chart)# 构建 PDF
doc.build([drawing])

这个例子展示了如何生成一个简单的折线图。ReportLab 的图表模块非常灵活,可以满足各种定制需求。

4.4 使用 ReportLab 生成动态PDF表单

ReportLab 可以生成包含表单字段的 PDF 文件,例如文本框、复选框和下拉列表。这些表单字段可以在生成后由用户在 PDF 阅读器中填写。

from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas# 创建 PDF 文件
pdf_file = "form_example.pdf"
c = canvas.Canvas(pdf_file, pagesize=letter)# 创建文本框
c.drawString(100, 700, "Name:")
c.textfield(name='name_field', tooltip='Your Name', x=150, y=700, width=200)# 创建复选框
c.drawString(100, 650, "Subscribe:")
c.checkbox(name='subscribe', tooltip='Subscribe to Newsletter', x=150, y=650, buttonStyle='check')# 创建下拉列表
c.drawString(100, 600, "Gender:")
c.choice(name='gender', tooltip='Select Gender', x=150, y=600, width=100, options=['Male', 'Female'])# 保存 PDF
c.save()

生成的 PDF 文件可以通过 PDF 阅读器(如 Adobe Acrobat Reader)进行交互。这对于创建需要用户输入的文档或问卷非常有用。

4.5 使用模板生成 PDF

在某些情况下,你可能需要基于模板生成多个相似的 PDF 文件。ReportLab 支持通过预定义的模板来快速生成带有动态内容的 PDF。例如,使用 platypus 模块和自定义样式表生成包含多个动态内容的复杂报告。

from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak
from reportlab.lib.styles import getSampleStyleSheet# 创建 PDF 文件
pdf_file = "templated_report.pdf"
doc = SimpleDocTemplate(pdf_file, pagesize=letter)# 获取样式表
styles = getSampleStyleSheet()# 创建内容模板
story = []# 模板内容示例
for i in range(1, 11):story.append(Paragraph(f"Report Section {i}", styles['Heading1']))story.append(Paragraph(f"This is the content of section {i}.", styles['Normal']))story.append(PageBreak())  # 添加分页符# 构建 PDF
doc.build(story)

这个例子展示了如何使用循环生成多个具有相似结构的报告部分,并自动分页。这种方法特别适合批量生成相似结构的文档,如发票、成绩单或报告。

5. ReportLab 的高级功能总结

ReportLab 不仅仅是一个 PDF 生成工具,它更像是一个强大的排版引擎。它的高级功能使得开发者可以创建非常复杂且高度定制化的文档,包括企业报表、交互式表单、可视化数据报告等。通过 ReportLab,你几乎可以生成任何类型的 PDF 文档,并将它们与动态数据源无缝集成。

三、PyPDF2 与 ReportLab 的综合使用

在实际应用中,PyPDF2ReportLab 通常可以结合使用。你可以使用 ReportLab 生成 PDF 文件,然后使用 PyPDF2 对生成的 PDF 进行后续处理,如合并、拆分或添加水印。例如,使用 ReportLab 生成报告,然后使用 PyPDF2 合并多个报告或添加页码。

from PyPDF2 import PdfReader, PdfWriter
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from io import BytesIO# 使用 ReportLab 创建一个 PDF
packet = BytesIO()
c = canvas.Canvas(packet, pagesize=letter)
c.drawString(100, 100, "This is a dynamically generated PDF.")
c.save()# 读取生成的 PDF
packet.seek(0)
new_pdf = PdfReader(packet)# 读取现有的 PDF
existing_pdf = PdfReader(open("existing.pdf", "rb"))# 创建 PdfWriter 对象
output = PdfWriter()# 将现有的 PDF 页面与新生成的页面合并
for page_num in range(len(existing_pdf.pages)):page = existing_pdf.pages[page_num]if page_num == 0:  # 仅将新内容添加到第一页page.merge_page(new_pdf.pages[0])output.add_page(page)# 输出合并后的 PDF
with open("merged_output.pdf", "wb") as output_stream:output.write(output_stream)

这个例子展示了如何使用 ReportLab 生成动态内容,并将其合并到现有的 PDF 文档中。通过这种方式,你可以实现高度灵活的 PDF 生成与处理工作流。

在处理 PDF 文件时,PyPDF2ReportLab 是两种功能强大的工具。PyPDF2 侧重于对已有 PDF 文件的操作,如读取、拆分、合并和旋转页面等。而 ReportLab 则专注于创建新的 PDF 文件,提供了丰富的功能来生成复杂的报表、图表和交互式表单。

通过掌握这两个库的使用,可以在 Python 中处理几乎所有的 PDF 相关任务。无论是生成定制化的企业报告,还是自动化批量处理 PDF 文件,这两个库都能提供强有力的支持。结合这两者的功能,能够让 PDF 处理领域游刃有余,满足各种实际应用需求。

这篇关于Python 处理 PDF 文件(PyPDF2, ReportLab)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1117681

相关文章

Python将博客内容html导出为Markdown格式

《Python将博客内容html导出为Markdown格式》Python将博客内容html导出为Markdown格式,通过博客url地址抓取文章,分析并提取出文章标题和内容,将内容构建成html,再转... 目录一、为什么要搞?二、准备如何搞?三、说搞咱就搞!抓取文章提取内容构建html转存markdown

Python获取中国节假日数据记录入JSON文件

《Python获取中国节假日数据记录入JSON文件》项目系统内置的日历应用为了提升用户体验,特别设置了在调休日期显示“休”的UI图标功能,那么问题是这些调休数据从哪里来呢?我尝试一种更为智能的方法:P... 目录节假日数据获取存入jsON文件节假日数据读取封装完整代码项目系统内置的日历应用为了提升用户体验,

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Python Websockets库的使用指南

《PythonWebsockets库的使用指南》pythonwebsockets库是一个用于创建WebSocket服务器和客户端的Python库,它提供了一种简单的方式来实现实时通信,支持异步和同步... 目录一、WebSocket 简介二、python 的 websockets 库安装三、完整代码示例1.

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

详解C#如何提取PDF文档中的图片

《详解C#如何提取PDF文档中的图片》提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,下面我们就来看看如何使用C#通过代码从PDF文档中提取图片吧... 当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

Python使用自带的base64库进行base64编码和解码

《Python使用自带的base64库进行base64编码和解码》在Python中,处理数据的编码和解码是数据传输和存储中非常普遍的需求,其中,Base64是一种常用的编码方案,本文我将详细介绍如何使... 目录引言使用python的base64库进行编码和解码编码函数解码函数Base64编码的应用场景注意