在Python中使用PyPDF2处理PDF文件

JeamesZora 发布于4月前
0 条问题

介绍

PyPDF2 是一个纯 Python 包,可通过使用 PyPDF2 包在 Python 中处理已先存在的 PDF。

  1. 提取 PDF 中的文档信息
  2. 旋转页面
  3. 合并 PDF
  4. 拆分 PDF
  5. 添加水印
  6. 加密 PDF

1、提取文档信息

使用 PyPDF2 从 PDF 中提取元数据和一些文本,尤其是当在预先存在的 PDF 文件上执行某些类型的自动化时是非常有用的。
以下是当前可以提取的数据:

  • Author
  • Creator
  • Producer
  • Subject
  • Title
  • Number of page

可以在自己的电脑上随便找一个 PDF 文件进行尝试操作。下面是使用该 PDF 编写一些代码,并了解如何访问这些属性:

from PyPDF2 import PdfFileReader

def extract_information(pdf_path):
    with open(pdf_path, 'rb') as f:
        pdf = PdfFileReader(f)
        information = pdf.getDocumentInfo()
        number_of_pages = pdf.getNumPages()

    txt = f"""
    Information about {pdf_path}:

    Author: {information.author}
    Creator: {information.creator}
    Producer: {information.producer}
    Subject: {information.subject}
    Title: {information.title}
    Number of pages: {number_of_pages}
    """

    print(txt)
    return information

if __name__ == '__main__':
    path = 'xxxx.pdf'
    extract_information(path)

首先从 PyPDF2 包导入 PdfFileReader。PdfFileReader 是一个具有多种与 PDF 文件交互的方法的类。在此示例中,我们调用了.getDocumentInfo(),它将返回 DocumentInformation 的实例, 包含了我们感兴趣的大部分信息。我们还可以在 reader 对象上调用.getNumPages(),让它返回文档中的页数。

information 这个变量具有多个实例属性,可以使用这些属性从文档中获取所需的其余元数据。我们可以打印出该信息并将其返回以备将来使用。

虽然 PyPDF2 具有.extractText(),可以在其页面对象上使用提取文本(本例中未显示),但它的效果不是很好。有些 PDF 会返回文本,有些会返回空字符串。如果要从 PDF 中提取文本,建议应该看一下 PDFMiner 项目。PDFMiner 更加强大,专门用于从 PDF 中提取文本。

2、旋转页面

有时候 PDF 是横向模式而不是纵向模式,甚至是颠倒的。当有人扫描文档为 PDF 或电子邮件时,很可能会发生这种情况。我们可以打印出文档并阅读纸质版本,也可以使用 Python 的强大功能来旋转有问题的页面。

下面看一下如何使用 PyPDF2 旋转文章的一些页面:

from PyPDF2 import PdfFileReader, PdfFileWriter

def rotate_pages(pdf_path):
    pdf_writer = PdfFileWriter()
    pdf_reader = PdfFileReader(path)
    # 顺时针旋转90度
    page_1 = pdf_reader.getPage(0).rotateClockwise(90)
    pdf_writer.addPage(page_1)
    # 逆时针旋转90度
    page_2 = pdf_reader.getPage(1).rotateCounterClockwise(90)
    pdf_writer.addPage(page_2)
    # 在正常方向上添加一页
    pdf_writer.addPage(pdf_reader.getPage(2))

    with open('rotate_pages.pdf', 'wb') as fh:
        pdf_writer.write(fh)

if __name__ == '__main__':
    path = '新路径.pdf'
    rotate_pages(path)

3、合并 PDF

在许多情况下,我们希望将两个或多个 PDF 合并到一个 PDF 中。例如,现在可能有一个标准的封面,需要转到许多类型的报告中。这时候就可以使用 python 来帮助完成这类工作。

下面是实现的代码,完成 PDF 合并的操作:

from PyPDF2 import PdfFileReader, PdfFileWriter
def merge_pdfs(paths, output):
    pdf_writer = PdfFileWriter()

    for path in paths:
        pdf_reader = PdfFileReader(path)
        for page in range(pdf_reader.getNumPages()):
            # 将每页添加到writer对象
            pdf_writer.addPage(pdf_reader.getPage(page))

    # 写入合并的pdf
    with open(output, 'wb') as out:
        pdf_writer.write(out)

if __name__ == '__main__':
    paths = ['document1.pdf', 'document2.pdf']
    merge_pdfs(paths, output='merged.pdf')

假如有一个要合并到一起的 pdf 列表时,可以直接使用 merge_pdf 函数完成。此函数采用了输入路径和输出路径作为参数。

首先遍历输入的 paths,并为每个输入创建一个 PDF 阅读对象。然后遍历 PDF 文件中的所有页面,并使用.addpage() 将这些页面写入 writer 对象。当完成对列表中所有 PDF 的所有页面的写入后,将在末尾写入新的结果中。

如果不想合并每个 PDF 的所有页面,可以通过添加一系列要添加的页面来稍微增强这个脚本。挑战一点的话,也可以使用 Python 的 argparse 模块为这个函数创建一个命令行接口。

4、拆分 PDF

有时可能需要将 PDF 拆分为多个 PDF,对于包含大量扫描内容的 PDF 来说尤其重要。以下是如何使用 PyPDF2 将 PDF 拆分为多个文件:

from PyPDF2 import PdfFileReader, PdfFileWriter

def split(path, name_of_split):
    pdf = PdfFileReader(path)
    for page in range(pdf.getNumPages()):
        pdf_writer = PdfFileWriter()
        pdf_writer.addPage(pdf.getPage(page))

        output = f'{name_of_split}{page}.pdf'
        with open(output, 'wb') as output_pdf:
            pdf_writer.write(output_pdf)

if __name__ == '__main__':
    path = 'xxx.pdf'
    split(path, 'jupyter_page')

这个函数中再次创建了 PDF 的 reaer 对象,并对其所读取的页面进行遍历。对于 PDF 中的每个页面,创建一个新的 PDF 的 writer 实例并向其添加单个页面。然后,将该页面写入一个唯一命名的文件。脚本运行完毕后,就可以将原始 PDF 的每个页面拆分为单独的 PDF。

5、添加水印

水印是纸质或者电子文档上的图像或图案,一些水印只能在特殊照明条件下才能看到。水印的重要性在于它可以保护你的知识产权,例如图像或 PDF。

我们可以使用 Python 和 PyPDF2 为文档添加水印,而且是拥有仅包含水印图像或文本的 PDF。下面是向 PDF 添加水印方法:

from PyPDF2 import PdfFileWriter, PdfFileReader

def create_watermark(input_pdf, output, watermark):
    watermark_obj = PdfFileReader(watermark)
    watermark_page = watermark_obj.getPage(0)

    pdf_reader = PdfFileReader(input_pdf)
    pdf_writer = PdfFileWriter()

    # 给所有页面添加水印
    for page in range(pdf_reader.getNumPages()):
        page = pdf_reader.getPage(page)
        page.mergePage(watermark_page)
        pdf_writer.addPage(page)

    with open(output, 'wb') as out:
        pdf_writer.write(out)

if __name__ == '__main__':
    create_watermark(
        input_pdf='Jupyter_Notebook_An_Introduction.pdf', 
          output='watermarked_notebook.pdf',
        watermark='watermark.pdf')

上面 create_watermark 有三个参数:

  • input_pdf:要加水印的 PDF 文件路径
  • output:要保存 PDF 的水印版本的路径
  • watermark:包含水印图像或文本的 PDF

在代码中,打开水印 PDF 并从文档中抓取第一页,因为这是水印应该驻留的位置。然后使用 input_pdf 和通用 pdf_writer 对象创建 PDF 的 writer 对象,以写出带水印的 PDF。

下一步是遍历 input_pdf 中的页面,然后调用.mergePage() 并以用上面读取的水印对象 watermark_page 为参数,这样会将 watermark_page 覆盖在当前页面的顶部,然后再将新合并的页面添加到 pdf_writer 对象中。遍历完成后,最后将新加水印的 PDF 写入磁盘。

6、加密 PDF

PyPDF2 目前仅支持将用户密码和所有者密码添加到预先存在的 PDF。在 PDF 版本中,所有者密码会提供 PDF 的管理员权限,并允许设置文档的权限,而用户密码只允许打开文档。

实际上,PyPDF2 是不允许设置文档的任何权限的,即使它允许设置所有者密码的情况下。但无论如何,这是可以加密的方式,也将固有地加密 PDF:

from PyPDF2 import PdfFileWriter, PdfFileReader

def add_encryption(input_pdf, output_pdf, password):
    pdf_writer = PdfFileWriter()
    pdf_reader = PdfFileReader(input_pdf)

    for page in range(pdf_reader.getNumPages()):
        pdf_writer.addPage(pdf_reader.getPage(page))

    pdf_writer.encrypt(user_pwd=password, owner_pwd=None, 
                       use_128bit=True)

    with open(output_pdf, 'wb') as fh:
        pdf_writer.write(fh)

if __name__ == '__main__':
    add_encryption(input_pdf='reportlab-sample.pdf',
                 output_pdf='reportlab-encrypted.pdf',
                 password='twofish')

dd_encryption 以输入输出 PDF 路径和要添加到 PDF 的密码为参数。由于需要加密整个输入 PDF,因此需要遍历其所有页面并将其添加到 writer 编写器。最后一步是调用.encrypt(),以用户密码,所有者密码以及是否应该添加 128 位加密为参数。默认情况下,要启用 128 位加密。如果将其设置为 False,则将应用 40 位加密。

查看原文: RPA-使用Python处理PDF文件

  • bigelephant
  • smallcat
需要 登录 后回复方可回复, 如果你还没有账号你可以 注册 一个帐号。