PyPDF2:用于 PDF 文件操作的 Python 库

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”文件名保存它。

参考