PyPDF2:用于PDF文件操作的Python库
PyPDF2是一个纯Python库,可处理PDF文件。
我们可以使用PyPDF2模块来处理现有的PDF文件。
我们无法使用此模块创建新的PDF文件。
PyPDF2功能
PyPDF2模块的一些令人兴奋的功能包括:
PDF文件元数据,例如页数,作者,创建者,创建时间和上次更新时间。
逐页提取PDF文件的内容。
合并多个PDF文件。
将PDF文件页面旋转一个角度。
PDF页面缩放。
从PDF页面提取图像并使用Pillow库保存为图像。
安装PyPDF2模块
我们可以使用PIP安装PyPDF2模块。
$pip install PyPDF2
PyPDF2范例
让我们看一些使用PyPDF2模块处理PDF文件的示例。
1.提取PDF元数据
我们可以在PDF文件中获取页数。
我们还可以获得有关PDF作者,创建者应用程序和创建日期的信息。
import PyPDF2
with open('Python_Tutorial.pdf', 'rb') as pdf_file:
pdf_reader = PyPDF2.PdfFileReader(pdf_file)
print(f'Number of Pages in PDF File is {pdf_reader.getNumPages()}')
print(f'PDF Metadata is {pdf_reader.documentInfo}')
print(f'PDF File Author is {pdf_reader.documentInfo["/Author"]}')
print(f'PDF File Creator is {pdf_reader.documentInfo["/Creator"]}')
示例输出:
Number of Pages in PDF File is 2
PDF Metadata is {'/Author': 'Microsoft Office User', '/Creator': 'Microsoft Word', '/CreationDate': "D:20191009091859+00'00'", '/ModDate': "D:20191009091859+00'00'"}
PDF File Author is Microsoft Office User
PDF File Creator is Microsoft Word
推荐读物:带有Statement和Python f字符串的Python
PDF文件应以二进制模式打开。
因此,文件打开模式以" rb"的形式传递。PdfFileReader类用于读取PDF文件。
documentInfo是一个字典,其中包含PDF文件的元数据。
我们可以使用getNumPages()函数获取PDF文件中的页数。
另一种方法是使用numPages属性。
2.提取PDF页面的文本
import PyPDF2
with open('Python_Tutorial.pdf', 'rb') as pdf_file:
pdf_reader = PyPDF2.PdfFileReader(pdf_file)
# printing first page contents
pdf_page = pdf_reader.getPage(0)
print(pdf_page.extractText())
# reading all the pages content one by one
for page_num in range(pdf_reader.numPages):
pdf_page = pdf_reader.getPage(page_num)
print(pdf_page.extractText())
PdfFileReader的getPage(int)方法返回
PyPDF2.pdf.PageObject实例。我们可以在页面对象上调用extractText()方法来获取页面的文本内容。
extractText()将不会返回任何二进制数据,例如图像。
3.旋转PDF文件页面
PyPDF2允许许多类型的操作,可以逐页进行。
我们可以将页面顺时针或者逆时针旋转一个角度。
import PyPDF2
with open('Python_Tutorial.pdf', 'rb') as pdf_file:
pdf_reader = PyPDF2.PdfFileReader(pdf_file)
pdf_writer = PyPDF2.PdfFileWriter()
for page_num in range(pdf_reader.numPages):
pdf_page = pdf_reader.getPage(page_num)
pdf_page.rotateClockwise(90) # rotateCounterClockwise()
pdf_writer.addPage(pdf_page)
with open('Python_Tutorial_rotated.pdf', 'wb') as pdf_file_rotated:
pdf_writer.write(pdf_file_rotated)
PdfFileWriter用于从源PDF写入PDF文件。
我们使用rotateClockwise(90)方法将页面顺时针旋转90度。
我们将旋转后的页面添加到PdfFileWriter实例。
最后,PdfFileWriter的write()方法用于生成旋转的PDF文件。
PdfFileWriter可以从某些源PDF文件写入PDF文件。
我们无法使用它从某些文本数据创建PDF文件。
4.合并PDF文件
import PyPDF2
pdf_merger = PyPDF2.PdfFileMerger()
pdf_files_list = ['Python_Tutorial.pdf', 'Python_Tutorial_rotated.pdf']
for pdf_file_name in pdf_files_list:
with open(pdf_file_name, 'rb') as pdf_file:
pdf_merger.append(pdf_file)
with open('Python_Tutorial_merged.pdf', 'wb') as pdf_file_merged:
pdf_merger.write(pdf_file_merged)
上面的代码可以很好地合并PDF文件。
但是,它产生了一个空的PDF文件。
原因是源PDF文件在实际写入之前就已关闭,以创建合并的PDF文件。
这是最新版本的PyPDF2中的一个错误。
您可以在GitHub问题上阅读它。
还有一种替代方法是使用contextlib模块来保持源文件打开,直到完成写操作为止。
import contextlib
import PyPDF2
pdf_files_list = ['Python_Tutorial.pdf', 'Python_Tutorial_rotated.pdf']
with contextlib.ExitStack() as stack:
pdf_merger = PyPDF2.PdfFileMerger()
files = [stack.enter_context(open(pdf, 'rb')) for pdf in pdf_files_list]
for f in files:
pdf_merger.append(f)
with open('Python_Tutorial_merged_contextlib.pdf', 'wb') as f:
pdf_merger.write(f)
您可以在此StackOverflow问题中阅读有关它的更多信息。
5.将PDF文件拆分为单页文件
import PyPDF2
with open('Python_Tutorial.pdf', 'rb') as pdf_file:
pdf_reader = PyPDF2.PdfFileReader(pdf_file)
for i in range(pdf_reader.numPages):
pdf_writer = PyPDF2.PdfFileWriter()
pdf_writer.addPage(pdf_reader.getPage(i))
output_file_name = f'Python_Tutorial_{i}.pdf'
with open(output_file_name, 'wb') as output_file:
pdf_writer.write(output_file)
Python_Tutorial.pdf有2页。
输出文件名为Python_Tutorial_0.pdf和Python_Tutorial_1.pdf。
6.从PDF文件提取图像
我们可以将PyPDF2与Pillow(Python Imaging Library)一起使用,以从PDF页面提取图像并将其另存为图像文件。
首先,您将必须使用以下命令安装枕头模块。
$pip install Pillow
这是从PDF文件的第一页提取图像的简单程序。
我们可以轻松地进一步扩展它,以从PDF文件中提取所有图像。
import PyPDF2
from PIL import Image
with open('Python_Tutorial.pdf', 'rb') as pdf_file:
pdf_reader = PyPDF2.PdfFileReader(pdf_file)
# extracting images from the 1st page
page0 = pdf_reader.getPage(0)
if '/XObject' in page0['/Resources']:
xObject = page0['/Resources']['/XObject'].getObject()
for obj in xObject:
if xObject[obj]['/Subtype'] == '/Image':
size = (xObject[obj]['/Width'], xObject[obj]['/Height'])
data = xObject[obj].getData()
if xObject[obj]['/ColorSpace'] == '/DeviceRGB':
mode = "RGB"
else:
mode = "P"
if '/Filter' in xObject[obj]:
if xObject[obj]['/Filter'] == '/FlateDecode':
img = Image.frombytes(mode, size, data)
img.save(obj[1:] + ".png")
elif xObject[obj]['/Filter'] == '/DCTDecode':
img = open(obj[1:] + ".jpg", "wb")
img.write(data)
img.close()
elif xObject[obj]['/Filter'] == '/JPXDecode':
img = open(obj[1:] + ".jp2", "wb")
img.write(data)
img.close()
elif xObject[obj]['/Filter'] == '/CCITTFaxDecode':
img = open(obj[1:] + ".tiff", "wb")
img.write(data)
img.close()
else:
img = Image.frombytes(mode, size, data)
img.save(obj[1:] + ".png")
else:
print("No image found.")

