Portable Document Format可移植文档格式或者PDF是一种文件格式可以用于跨操作系统的呈现和文档交换。尽管PDF最初是由Adobe发明的但它现在是由国际标准化组织ISO维护的开放标准。你可以通过使用PyPDF2包在Python中处理已先存在的PDF。PyPDF2是一个纯Python包可用于许多不同类型的PDF操作。本文将带你了解如何执行以下操作从Python中提取PDF中的文档信息旋转页面合并PDF拆分PDF添加水印加密PDF一、pyPdfPyPDF2和PyPDF4的历史最初的pyPdf软件包于2005年发布。pyPdf的最后一个正式版本是在2010年。大约一年后一家名为Phasit的公司赞助了一个名为PyPDF2的pyPdf分支。该代码编写为向后与原始代码兼容并且用了好多年效果一直很好其最后一个版本是在2016年。有一个名为PyPDF3的软件包简短系列版本然后该项目被重命名为PyPDF4。所有这些项目都完全相同但pyPdf和PyPDF2 之间的最大区别在于后者版本增加了Python 3支持。Python 3的原始pyPdf有一个不同的Python 3分支但是这个分支已经多年没有维护了。虽然最近放弃了PyPDF2但新的PyPDF4与PyPDF2没有完全的向后兼容性。本文中的大多数示例都可以与PyPDF4完美配合但也有一些不能这就是为什么PyPDF4在本文中没有更多的特色。随意用PyPDF4替换PyPDF2的导入看看它是如何工作的。二、pdfrw一个替代的PDF操作包Patrick Maupin创建了一个名为pdfrw的软件包它可以完成许多与PyPDF2相同的工作。除了加密的特殊情况外本文后面提到PyPDF2的所有操作pdfrw均可以实现。pdfrw的最大区别在于它与ReportLab软件包集成因此你可以使用一些或所有预先存在的PDF构建一个新的PDF。三、PyPDF2的安装如果使用Anaconda而不是常规Python可以使用pip或conda安装PyPDF2。以下是使用pip安装PyPDF2的方法$ pip install pypdf2由于PyPDF2没有任何依赖因此安装非常快。四、如何从Python中提取PDF文档信息我们可以使用PyPDF2从PDF中提取元数据和一些文本尤其是当在预先存在的PDF文件上执行某些类型的自动化时是非常有用的。以下是当前可以提取的数据类型AuthorCreatorProducerSubjectTitleNumber of page可以在自己的电脑上随便找一个PDF文件进行尝试操作。下面是使用该PDF编写一些代码并了解如何访问这些属性1234567891011121314151617181920fromPyPDF2importPdfFileReaderdefextract_information(pdf_path):withopen(pdf_path,rb) as f:pdfPdfFileReader(f)informationpdf.getDocumentInfo()number_of_pagespdf.getNumPages()txtfInformation 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)returninformationif__name____main__:pathxxxx.pdfextract_information(path)首先从PyPDF2包导入PdfFileReader。PdfFileReader是一个具有多种与PDF文件交互的方法的类。在此示例中我们调用了.getDocumentInfo()它将返回DocumentInformation的实例,包含了我们感兴趣的大部分信息。我们还可以在reader对象上调用.getNumPages()让它返回文档中的页数。information这个变量具有多个实例属性可以使用这些属性从文档中获取所需的其余元数据。我们可以打印出该信息并将其返回以备将来使用。虽然PyPDF2具有.extractText()可以在其页面对象上使用提取文本本例中未显示但它的效果不是很好。有些PDF会返回文本有些会返回空字符串。如果要从PDF中提取文本建议应该看一下PDFMiner项目。PDFMiner更加强大专门用于从PDF中提取文本。五、如何旋转页面有时候PDF是横向模式而不是纵向模式甚至是颠倒的。当有人扫描文档为PDF或电子邮件时很可能会发生这种情况。我们可以打印出文档并阅读纸质版本也可以使用Python的强大功能来旋转有问题的页面。下面看一下如何使用PyPDF2旋转文章的一些页面1234567891011121314151617fromPyPDF2importPdfFileReader, PdfFileWriterdefrotate_pages(pdf_path):pdf_writerPdfFileWriter()pdf_readerPdfFileReader(path)# 顺时针旋转90度page_1pdf_reader.getPage(0).rotateClockwise(90)pdf_writer.addPage(page_1)# 逆时针旋转90度page_2pdf_reader.getPage(1).rotateCounterClockwise(90)pdf_writer.addPage(page_2)# 在正常方向上添加一页pdf_writer.addPage(pdf_reader.getPage(2))withopen(rotate_pages.pdf,wb) as fh:pdf_writer.write(fh)if__name____main__:path新路径.pdfrotate_pages(path)上面除了pdfileReader之外还导入了pdfileWriter因为我们需要编写一个新的pdf。rotate_pages()获取要修改的PDF的路径。在这个函数中需要创建一个可以命名为pdf-writer的writer对象和一个名为pdf-reader的reader对象。接下来可以使用.get page()获取所需的页面。上面开始输入了第0页也就是第一页调用page对象的.rotateClockwise()顺时针旋转方法并输入90。然后同样地对于第二页调用.rotateCounterLockwise()逆时针旋转并输入90。每次调用Rotation旋转方法后都会调用.addPage()这将向writer对象添加页面的旋转版本。最后一页是第3页没有对其进行任何旋转。最后使用.write()把所有新页写入新的PDF。六、如何合并PDF在许多情况下我们希望将两个或多个PDF合并到一个PDF中。例如现在可能有一个标准的封面需要转到许多类型的报告中。这时候就可以使用python来帮助完成这类工作。下面是实现的代码完成PDF合并的操作123456789101112131415fromPyPDF2importPdfFileReader, PdfFileWriterdefmerge_pdfs(paths, output):pdf_writerPdfFileWriter()forpathinpaths:pdf_readerPdfFileReader(path)forpageinrange(pdf_reader.getNumPages()):# 将每页添加到writer对象pdf_writer.addPage(pdf_reader.getPage(page))# 写入合并的pdfwithopen(output,wb) as out:pdf_writer.write(out)if__name____main__:paths[document1.pdf,document2.pdf]merge_pdfs(paths, outputmerged.pdf)假如有一个要合并到一起的pdf列表时可以直接使用merge_pdf函数完成。此函数采用了输入路径和输出路径作为参数。首先遍历输入的paths并为每个输入创建一个PDF阅读对象。然后遍历PDF文件中的所有页面并使用.addpage()将这些页面写入writer对象。当完成对列表中所有PDF的所有页面的写入后将在末尾写入新的结果中。如果不想合并每个PDF的所有页面可以通过添加一系列要添加的页面来稍微增强这个脚本。挑战一点的话也可以使用Python的argparse模块为这个函数创建一个命令行接口。七、如何拆分PDF?有时可能需要将PDF拆分为多个PDF对于包含大量扫描内容的PDF来说尤其重要。以下是如何使用PyPDF2将PDF拆分为多个文件123456789101112fromPyPDF2importPdfFileReader, PdfFileWriterdefsplit(path, name_of_split):pdfPdfFileReader(path)forpageinrange(pdf.getNumPages()):pdf_writerPdfFileWriter()pdf_writer.addPage(pdf.getPage(page))outputf{name_of_split}{page}.pdfwithopen(output,wb) as output_pdf:pdf_writer.write(output_pdf)if__name____main__:pathxxx.pdfsplit(path,jupyter_page)这个函数中再次创建了PDF的reaer对象并对其所读取的页面进行遍历。对于PDF中的每个页面创建一个新的PDF的writer实例并向其添加单个页面。然后将该页面写入一个唯一命名的文件。脚本运行完毕后就可以将原始PDF的每个页面拆分为单独的PDF。