PyPDF2 是一个用于处理 PDF 文件的纯 Python 库。我们可以使用 PyPDF2 模块来处理现有的 PDF 文件。我们无法使用此模块创建新的 PDF 文件。
PyPDF2 功能
PyPDF2 模块的一些令人兴奋的功能包括:
- PDF 文件元数据,例如页面数、作者、创建者、创建和上次更新时间。
- 逐页提取 PDF 文件的内容。
- 合并多个 PDF 文件。
- 将 PDF 文件页面旋转一定角度。
- PDF 页面的缩放。
- 使用 Pillow 库从 PDF 页面中提取图像并将其另存为图像。
安装 PyPDF2 模块
我们可以使用PIP来安装PyPDF2模块。
$ pip 安装 PyPDF2
PyPDF2 示例
让我们看一些使用 PyPDF2 模块处理 PDF 文件的示例。
1. 提取PDF元数据
我们可以获取PDF文件的页数。我们还可以获得有关 PDF 作者、创建者应用程序和创建日期的信息。
导入 PyPDF2 使用 open('Python_Tutorial.pdf', 'rb') 作为 pdf_file: pdf_reader = PyPDF2.PdfFileReader(pdf_file) print(f'PDF 文件的页数为 {pdf_reader.getNumPages()}') print(f'PDF 元数据是 {pdf_reader.documentInfo}') print(f'PDF 文件作者是 {pdf_reader.documentInfo["/Author"]}') print(f'PDF 文件创建器是 {pdf_reader.documentInfo["/Creator"]}')
示例输出:
PDF 文件的页数为 2 PDF 元数据为 {'/Author': 'Microsoft Office User', '/Creator': 'Microsoft Word', '/CreationDate': "D:20191009091859+00'00'", '/ModDate': "D:20191009091859 +00'00'"} PDF 文件作者是 Microsoft Office 用户 PDF 文件创建器是 Microsoft Word
推荐阅读:Python with Statement 和 Python f-strings
- PDF 文件应以二进制模式打开。这就是为什么文件打开模式被传递为“rb”。
- PdfFileReader类用于读取PDF文件。
- documentInfo 是包含 PDF 文件元数据的字典。
- 我们可以使用 getNumPages() 函数获取 PDF 文件的页数。另一种方法是使用
numPages
属性。
2. 提取PDF页面文本
导入 PyPDF2 使用 open('Python_Tutorial.pdf', 'rb') 作为 pdf_file: pdf_reader = PyPDF2.PdfFileReader(pdf_file) # 打印第一页内容 pdf_page = pdf_reader.getPage(0) 打印(pdf_page.extractText()) # 逐一读取所有页面内容 对于范围内的 page_num(pdf_reader.numPages): pdf_page = pdf_reader.getPage(page_num) 打印(pdf_page.extractText())
- PdfFileReader getPage(int) 方法返回
PyPDF2.pdf.PageObject
实例。 - 我们可以调用页面对象的extractText()方法来获取页面的文本内容。
- extractText() 不会返回任何二进制数据,例如图像。
3.旋转PDF文件页面
PyPDF2 允许多种类型的操作,可以逐页完成。我们可以顺时针或逆时针旋转页面一个角度。
导入 PyPDF2 使用 open('Python_Tutorial.pdf', 'rb') 作为 pdf_file: pdf_reader = PyPDF2.PdfFileReader(pdf_file) pdf_writer = PyPDF2.PdfFileWriter() 对于范围内的 page_num(pdf_reader.numPages): pdf_page = pdf_reader.getPage(page_num) pdf_page.rotateClockwise(90) # 逆时针旋转() pdf_writer.addPage(pdf_page) 使用 open('Python_Tutorial_rotated.pdf', 'wb') 作为 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文件
导入 PyPDF2 pdf_merger = PyPDF2.PdfFileMerger() pdf_files_list = ['Python_Tutorial.pdf', 'Python_Tutorial_rotated.pdf'] 对于 pdf_files_list 中的 pdf_file_name: 以 open(pdf_file_name, 'rb') 作为 pdf_file: pdf_merger.append(pdf_file) 使用 open('Python_Tutorial_merged.pdf', 'wb') 作为 pdf_file_merged: pdf_merger.write(pdf_file_merged)
上面的代码看起来很适合合并 PDF 文件。但是,它生成了一个空的 PDF 文件。原因是源 PDF 文件在实际写入创建合并 PDF 文件之前已关闭。
这是最新版本 PyPDF2 中的一个错误。您可以在这个 GitHub 问题中阅读相关内容。
还有一种替代方法可以使用该contextlib
模块保持源文件打开,直到写入操作完成。
导入上下文库 导入 PyPDF2 pdf_files_list = ['Python_Tutorial.pdf', 'Python_Tutorial_rotated.pdf'] 使用 contextlib.ExitStack() 作为堆栈: pdf_merger = PyPDF2.PdfFileMerger() files = [stack.enter_context(open(pdf, 'rb')) for pdf_files_list 中的 pdf] 对于文件中的 f: pdf_merger.append(f) 打开('Python_Tutorial_merged_contextlib.pdf','wb')作为f: pdf_merger.write(f)
您可以在StackOverflow Question中阅读更多相关信息。
5.将PDF文件拆分为单页文件
导入 PyPDF2 使用 open('Python_Tutorial.pdf', 'rb') 作为 pdf_file: pdf_reader = PyPDF2.PdfFileReader(pdf_file) 对于我在范围内(pdf_reader.numPages): pdf_writer = PyPDF2.PdfFileWriter() pdf_writer.addPage(pdf_reader.getPage(i)) 输出文件名 = f'Python_Tutorial_{i}.pdf' 以 open(output_file_name, 'wb') 作为输出文件: pdf_writer.write(输出文件)
Python_Tutorial.pdf 有 2 页。输出文件命名为 Python_Tutorial_0.pdf 和 Python_Tutorial_1.pdf。
6. 从 PDF 文件中提取图像
我们可以使用 PyPDF2 和 Pillow(Python 图像库)从 PDF 页面中提取图像并将其保存为图像文件。
首先,您必须使用以下命令安装 Pillow 模块。
$ pip 安装 Pillow
这是一个从 PDF 文件第一页提取图像的简单程序。我们可以轻松地进一步扩展它以从 PDF 文件中提取所有图像。
导入 PyPDF2 从 PIL 导入图像 使用 open('Python_Tutorial.pdf', 'rb') 作为 pdf_file: pdf_reader = PyPDF2.PdfFileReader(pdf_file) # 从第一页提取图像 page0 = pdf_reader.getPage(0) if '/XObject' in page0['/Resources']: xObject = page0['/Resources']['/XObject'].getObject() 对于 xObject 中的 obj: 如果 xObject[obj]['/Subtype'] == '/Image': 大小 = (xObject[obj]['/宽度'], xObject[obj]['/高度']) 数据 = xObject[obj].getData() 如果 xObject[obj]['/ColorSpace'] == '/DeviceRGB': 模式=“RGB” 别的: 模式=“P” 如果 xObject[obj] 中的“/Filter”: 如果 xObject[obj]['/Filter'] == '/FlateDecode': img = Image.frombytes(模式、大小、数据) img.save(obj[1:] + ".png") elif xObject[obj]['/Filter'] == '/DCTDecode': img = open(obj[1:] + ".jpg", "wb") img.write(数据) img.close() elif xObject[obj]['/Filter'] == '/JPXDecode': img = open(obj[1:] + ".jp2", "wb") img.write(数据) img.close() elif xObject[obj]['/Filter'] == '/CCITTFaxDecode': img = open(obj[1:] + ".tiff", "wb") img.write(数据) img.close() 别的: img = Image.frombytes(模式、大小、数据) img.save(obj[1:] + ".png") 别的: print("没有找到图像。")
我的示例 PDF 文件的第一页上有一个 PNG 图像,程序以“image20.png”文件名保存它。