PDF 表示 Portable Document Format,使用 .pdf 作为文件扩展名。虽然 PDF 支持许多功能,但现在我们专注于最常做的两件事:从 PDF 读取文本内容和从已有的文档生成新的 PDF。主要涉及到三个类:PdfFileReader、PdfFileWriter、PageObject。
Python中用于处理PDF文档的模块是PyPDF2。可以直接通过 pip 指令去安装:pip install PyPDF2
。 这个地方要注意,模块名是区分大小写的,除了 y 是小写其他字母都是大写。
1. PdfFileReader
PdfFileReader是 PyPDF2 提供的一个类,主要是通过方法和属性来提供获取pdf文件内容的相关功能。
使用PdfFileReader读取pdf文件前需要先创建一个PdfFileReader的对象:
PdfFileReader(stream, strict = True,warndest = None,overwriteWarnings = True)
- stream: **File 对象或支持与 File 对象类似的标准读取和查找方法的对象,**也可以是表示 PDF 文件路径的字符串。
- strict(bool): 确定是否应该警告用户所用的问题,也导致一些可纠正的问题是致命的,默认是 True
- warndest : 记录警告的目标(默认是 sys.stderr)
- overwriteWarnings(bool):确定是否 warnings.py 用自定义实现覆盖 Python 模块(默认为 True)
下表是部分 PdfFileReader 对象的方法和属性:
属性和方法 | 描述 |
---|---|
getDestinationPageNumber(destination) | 检索给定目标对象的页码 |
getDocumentInfo() | 检索 PDF 文件的文档信息字典 |
getFields(tree = None,retval = None,fileObj= None) | 如果此 PDF 包含交互式表单字段,则提取字段数据, |
getFormTextFields() | 从文档中检索带有文本数据(输入,下拉列表)的表单域 |
getNameDestinations(tree = None,retval= None) | 检索文档中的指定目标 |
getNumPages() | 计算此 PDF 文件中的页数 |
getOutlines(node = None,outline = None,) | 检索文档中出现的文档大纲 |
getPage(pageNumber) | 从这个 PDF 文件中检索指定编号的页面 |
getPageLayout() | 获取页面布局 |
getPageMode() | 获取页面模式 |
getPageNumber(pageObject) | 检索给定 pageObject 处于的页码 |
getXmpMetadata() | 从 PDF 文档根目录中检索 XMP 数据 |
isEncrypted | 显示 PDF 文件是否加密的只读布尔属性 |
decrypt(密码) | 通过指定密码对pdf文件进行解密 |
实例一:从PDF文件中提取文本
# 从PyPDF2模块中导入PdfFileReader类
from PyPDF2 import PdfFileReader
# 打开需要操作的pdf文件,获取文件对象。因为pdf文件是二进制文件,所以打开的时候是 'rb'
pdf_file = open('files/new.pdf', 'rb')
# 创建pdf文件对应的PdfFileReader对象
pdf_reader = PdfFileReader(pdf_file)
# 获取当前pdf文件总页数(这儿其实不需要,只是给大家看看)
total_page = pdf_reader.getNumPages() # 结果是: 17
# 获取pdf文件的第一页
page0 = pdf_reader.getPage(0)
# 获取第一页中的文本内容
text_content = page0.extractText()
print(text_content)
实例二:解密
# 从PyPDF2模块中导入PdfFileReader类
from PyPDF2 import PdfFileReader
# 创建PdfFileReader对象,并且让它和指定的pdf文件进行关联
# pdf_reader = PdfFileReader('files/MySQL.pdf') # 打开文件的时候可以直接给pdf文件路径
pdf_reader = PdfFileReader(open('files/MySQL.pdf', 'rb')) # 打开文件的时候可以直接给文件对象
# 是否加密 - 如果结果是True,表示已经加密,如果获取页面的时候程序会报错
is_encrypted = pdf_reader.isEncrypted
# 通过密码解密, 这儿的 1234 是密码
pdf_reader.decrypt('1234')
# 获取当前pdf文件的第一页
page0 = pdf_reader.getPage(0)
2. PdfFileWriter
在 PyPDF2 中,与 PdfFileReader 对象相对的是 PdfFileWriter 对象,它可以创建一个新的 PDF 文件。但 PyPDF2 不能将任意文本写入 PDF,就像 Python 可以写入纯文本文件那样。PyPDF2 写入 PDF 的能力,仅限于从其他 PDF 中拷贝页面、旋转页面、重叠页面和加密文件。模块不允许直接编辑 PDF。必须创建一个新的 PDF,然后从已有的文档拷贝内容。PdfFileWriter 的使用一般遵守以下方式:
- 打开一个或多个已有的 PDF(源 PDF),得到 PdfFileReader 对象。
- 创建一个新的 PdfFileWriter 对象。
- 将页面从 PdfFileReader 对象拷贝到 PdfFileWriter 对象中。
- 最后,利用 PdfFileWriter 对象写入输出的 PDF。
创建一个PdfFileWriter 对象,只是在Python 中创建了一个代表PDF 文档的值,这并没有创建实际的PDF 文件,要实际生成文件,必须调用PdfFileWriter 对象的write()方法。
下表是部分 PdfFileWriter 对象的方法和属性:
属性和方法 | 描述 |
---|---|
addAttachment(fname,fdata) | 在 PDF 中嵌入文件 |
addBlankPage(width= None,height=None) | 追加一个空白页面到这个 PDF 文件并返回它 |
addJS(javascript) | 添加将在打开此 PDF 是启动的 javascript |
addLink(pagenum,pagedest,rect,border=None,fit=’/fit’,*args) | 从一个矩形区域添加一个内部链接到指定的页面 |
addPage(page) | 添加一个页面到这个PDF 文件,该页面通常从 PdfFileReader 实例获取 |
getNumpages() | 页数 |
getPage(pageNumber) | 从这个 PDF 文件中检索一个编号的页面 |
insertBlankPage(width=None,height=None,index=0) | 插入一个空白页面到这个 PDF 文件并返回它,如果没有指定页面大小,就使用最后一页的大小 |
insertPage(page,index=0) | 在这个 PDF 文件中插入一个页面,该页面通常从 PdfFileReader 实例获取 |
removeLinks() | 从次数出中删除连接盒注释 |
removeText(ignoreByteStringObject = False) | 从这个输出中删除图像 |
write(stream) | 将添加到此对象的页面集合写入 PDF 文件 |
实例三:拷贝页面
from PyPDF2 import PdfFileReader, PdfFileWriter
# 创建两个pdf文件对应的PdfFileReader对象
pdf_reader1 = PdfFileReader('files/file1.pdf')
pdf_reader2 = PdfFileReader('files/file2.pdf')
# 创建PdfFileWriter对象
writer = PdfFileWriter()
# 遍历将第一个pdf文件中的每一页取出来
for page_num in range(pdf_reader1.getNumPages()):
# 取出每一页对应的PageObject对象
page = pdf_reader1.getPage(page_num)
# 将当前取出来的页面添加到writer中
writer.addPage(page)
# 遍历将第二个pdf文件中的每一页取出来
for page_num in range(pdf_reader2.getNumPages()):
# 取出每一页对应的PageObject对象
page = pdf_reader2.getPage(page_num)
# 将当前取出来的页面添加到writer中
writer.addPage(page)
# write(stream) - 将添加到此对象的页面集合写入 PDF 文件 ,这儿的stream必须是以写的方式打开的文件对象
out_file = open('files/out.pdf', 'wb')
writer.write(out_file)
out_file.close()
# 程序结束后,会在files下创建一个 out.pdf 文件,文件中的内容是 file1.pdf 和 file2.pdf 两个文件中的所有内容
3. PageObject
从 PdfFileReader 对象中通过 getPage 方法得到页面都是 PageObject 的对象。
下表是部分 PageObject 对象的属性和方法:
属性或方法 | 描述 |
---|---|
createBlankPage(pdf=None,width=None,height=None) | 返回一个新的空白页面(静态方法) |
extractText() | 找到所有文本绘图命令,按照他们在内容流中提供的顺序,并提取文本 |
getContents() | 访问页面内容,返回 Contents 对象或 None |
rotateClockwise(angle) | 顺时针旋转指定度数 |
scale(sx,sy) | 通过向其内容应用转换矩阵并更新页面大小 |
mergePage(page) | 页面的合并 |
compressContentStreams() | 页面压缩 |
mediaBox.upperRight | 将页面裁剪成指定大小 |
mediaBox.getUpperRight_x()/mediaBox.getUpperRight_y() | 获取页面的大小 |
实例四:旋转页面
# **实例三:拷贝页面**
from PyPDF2 import PdfFileReader, PdfFileWriter
# 打开文件
# file_reader = PdfFileReader(open('files/MySQL.pdf', 'rb'))
file_reader = PdfFileReader('files/MySQL.pdf')
# 取第一页
page0 = file_reader.getPage(0)
# 旋转90度
page0.rotateClockwise(90)
# 创建 PdfFileWriter 对象
file_writer = PdfFileWriter()
# 将第一页添加到新文件中
file_writer.addPage(page0)
# 保存新文件
file_writer.write(open('files/MySQL2.pdf', 'wb'))
PyPDF2 也可以将一页的内容叠加到另一页上,这可以用来在页面上添加公司标志、时间戳或水印。利用 Python,很容易为多个文件添加水印,并且只针对程序指定的页面添加。
实例五: 添加水印
from PyPDF2 import PdfFileReader, PdfFileWriter
# 打开需要添加水印的文件
pdf_reader = PdfFileReader('files/MySQL.pdf')
# 打开水印文件
water_reader = PdfFileReader('files/water.pdf')
# 获取需要添加水印的页面(如果所有也都要添加水印就遍历)
page0 = pdf_reader.getPage(0)
# 获取水印页
water_page = water_reader.getPage(0)
# 合并
page0.mergePage(water_page)
# 创建PdfFileWriter对象并且将已经添加水印的也添加到PdfFileWriter对象中
writer = PdfFileWriter()
writer.addPage(page0)
# 保存
writer.write(open('out/newMySQL.pdf', 'wb'))
实例六:加密PDF
PdfFileWriter 对象也可以为 PDF 文档进行加密:
from PyPDF2 import PdfFileWriter, PdfFileReader
# 打开需要加密的文件
file_reader = PdfFileReader('files/MySQL.pdf')
# 创建PdfFileWriter对象
file_writer = PdfFileWriter()
# 将原文件的内容全部添加到PdfFileWriter对象中
for page_num in range(file_reader.getNumPages()):
file_writer.addPage(file_reader.getPage(page_num))
# 加密,并且设置密码为: 123456
file_writer.encrypt('123456')
# 保存文件
file_writer.write(open('out/newMySQL.pdf', 'wb'))
参考书籍:《Python编程快速上手-让繁琐工作自动化》