python中reader_用Python处理pdf文档

介绍

译者翻译了很多Python强大的包,其中,一以贯之的思想是:面向对象。我用下面的翻译来举一个例子,比如:从PyPDF2包中导入PdfFileReader包。PdfFileReader是此包的一个类,拥有与PDF文档交互的多种方法,我调用了这个类创造了一个可用来读取的对象,这个对象的名称为pdf。方法和属性的调用就只能靠多加练习了。

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

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

1、安装

pip install pypdf2
#假设你直接使用Python
conda install pypdf2
#假设你在anconda环境下使用Python

2、提取文档信息

使用PyPDF2可提取PDF文档的一些元数据和文本信息。当你做一些关于PDF文档的自动化处理时,这些信息是非常有用的。

我们可以提取哪些具体信息呢?

  • Author
  • Creator
  • Producer
  • Subject
  • Title
  • Number of pages
#extract_doc_info.py

首先,我们从PyPDF2包中导入PdfFileReader包。PdfFileReader是此包的一个类,拥有与PDF文档交互的多种方法,我调用了这个类创造了一个可用来读取的对象,这个对象的名称为pdf。在这个例子中,我对pdf使用了.getDocumnetInfo()方法,它返回一个DocumentInformation实例,名称为information,这个实例包含了我想提取的大部分信息。当然,我也对pdf使用了.getNumPages()方法,这个方法返回pdf的页数。

我们用一些方法去按需调取information实例的属性(即我们想要的信息)。不过,如果我们想调取文本信息,最好不要对information使用.extractText()方法,因为它有时会返回空字符串。如果想要从PDF提取文本,建议应该看一下PDFMiner项目。PDFMiner更加强大,专门用于从PDF中提取文本。

3、旋转页面

有时,PDF的页面是横向的,而不是纵向的,甚至是倒放的。当你扫描文档或者邮件时,这些情况很有可能发生。我们可以打印出来纸质版并阅读它,或者我们可借助Python强大的力量来旋转那些有问题的页面。

# rotate_pages.py

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 = r'C:Users23909DesktopThe World in 2020.pdf'
    rotate_pages(path)

此次,你需要额外再导入PdfFileWriter类,因为最后你还要生成一个新的PDF对象并保存。rotatepages()函数以旧PDF文件的路径作为参数。在这个函数内部,我创造了一个可读取的对象,名称为pdf_reader,以及可写入的对象,名称为pdf_writer。

接下来,你对pdf_reader使用.GetPage()方法去取得就PDF文件的目标页,这里我选取了第一页,也就是此方法的参数为整数零,此方法返回一个页面对象,名称为page_1。我们对page1使用.rotateClocwise()方法,使其旋转90度,默认方向为右,我们对pafwriter对象使用.addPage()方法,将page_1加上去。对page_2对象,我们使用rotateCounterClockwise(),使page_2对象旋转90度,方向为左,我们对pdf_writer对象使用.addPage()方法,将page_2加上去。

然后我们又调用pdf_writer对象的.addPage()方法,去把旧PDF文件的第三页也加上去,只不过我们不对这个第三页做任何旋转。

最后,我们调用.write函数去把这个包含三页页面的新文档存储起来。.write函数以类文件路径作为参数。

4、合并PDF

在许多情况,你也许有把多个PDF合并成一个PDF文件的需要。比如,你需要给多张PDF报告加一个标准的PDF封面。你可以用Python帮你做这类事情。

# pdf_merging.py

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()):
            # 把每张PDF页面加入到这个可读取对象中
            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 阅读对象,名称为pdfreader。然后遍历 PDF 文件中的所有页面,并使用.addpage() 将这些页面写入 pdf_writer 对象。当完成对列表中所有 PDF 的所有页面的写入后,将在末尾写入新的结果中。

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

5、拆分PDF

在许多时候,我们需要把一个PDF文件拆分成多个PDF文件。尤其是PDF文件包含过多需要浏览的内容时,当然你也许其他重要的原因。

以下是如何使用 PyPDF2 将 PDF 拆分为多个文件:

# pdf_splitting.py

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 = r'C:Users23909DesktopThe World in 2020.pdf'
    split(path, 'jupyter_page')

在这个例子中,你再一次创造一个可读取的PDF对象,名称为pdf,然后遍历它的页数。

对于pdf的每一页,你创造了一个可读取的PDF实例,并向其添加单个页面。然后,将该页面写入一个唯一命名的文件。脚本运行完毕后,就可以将原始 PDF 的每个页面拆分为单独的 PDF。

6、添加水印

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

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

# pdf_watermarker.py

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()

    # Watermark all the pages
    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=r'C:Users23909DesktopThe World in 2020.pdf', 
        output='watermarked_notebook.pdf',
        watermark='watermark.pdf')

上面 create_watermark 有三个参数:

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

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

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

7、PDF加密

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

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

# pdf_encrypt.py

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')

add_encryption 以输入输出 PDF 路径和要添加到 PDF 的密码为参数。由于需要加密整个输入 PDF,因此需要遍历其所有页面并将其添加到 writer 编写器。

最后一步是调用.encrypt(),以用户密码,所有者密码以及是否应该添加 128 位加密为参数。默认情况下,要启用 128 位加密。如果将其设置为 False,则将应用 40 位加密。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值