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

时间:2020-02-23 14:42:24  来源:igfitidea点击:

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.")