当前位置: 首页 > 科技观察

如何用Python玩转各种PDF操作?

时间:2023-03-21 18:12:35 科技观察

便携式文档格式,或PDF是一种文件格式,可用于跨操作系统的演示和文档交换。尽管PDF最初是由Adob??e发明的,但它现在是国际标准化组织(ISO)维护的开放标准。您可以使用PyPDF2包在Python中处理预先存在的PDF。PyPDF2是一个纯Python包,可用于许多不同类型的PDF操作。本文将向您介绍如何:在Python中从PDF中提取文档信息旋转页面合并PDF拆分PDF添加水印加密PDFpyPdf、PyPDF2和PyPDF4的历史最初的pyPdf包于2005年发布。pyPdf的最后一个正式版本是2010年。大约一年后,一家名为Phasit的公司赞助了一个名为PyPDF2的pyPdf分支。编写的代码是为了与原始代码向后兼容,并且运行良好多年,最后一个版本是在2016年。有一个名为PyPDF3的包的一系列简短版本,然后该项目更名为PyPDF4。所有这些项目都完全相同,但pyPdf和PyPDF2+最大的区别在于后者增加了对Python3的支持。Python3的原始pyPdf有一个不同的Python3分支,但是这个分支已经很多年没有维护了。尽管最近放弃了PyPDF2,但新的PyPDF4并不完全向后兼容PyPDF2。本文中的大多数示例都适用于PyPDF4***,但有些则不能,这就是本文中没有更多介绍PyPDF4的原因。随意用PyPDF4替换PyPDF2的导入,看看它是如何工作的。pdfrw:另一种PDF操作包PatrickMaupin创建了一个名为pdfrw的包,它可以做许多与PyPDF2相同的事情。除了加密的特殊情况,本文后面提到的PyPDF2的所有操作都可以通过pdfrw来实现。pdfrw的最大区别在于它集成了ReportLab包,因此您可以使用部分或所有预先存在的PDF来构建新的PDF。PyPDF2的安装如果您使用Anaconda而不是常规Python,则可以使用pip或conda安装PyPDF2。以下是使用pip安装PyPDF2的方法:$pipinstallpypdf2由于PyPDF2没有任何依赖项,因此安装速度非常快。如何从Python中提取PDF文档信息我们可以使用PyPDF2从PDF中提取元数据和一些文本,这在对预先存在的PDF文件执行某些类型的自动化时特别有用。以下是目前可以提取的数据类型:作者创作者制作人主题标题页码您可以在您的计算机上找到一个PDF文件并尝试一下。下面是使用该PDF的一些代码并查看如何访问这些属性:fromPyPDF2importPdfFileReaderdefextract_information(pdf_path):withopen(pdf_path,'rb')asf:pdf=PdfFileReader(f)information=pdf.getDocumentInfo()number_of_pages=pdf.getNumPages()txt=f"""关于{pdf_path}的信息:作者:{information.author}创作者:{information.creator}制作人:{information.producer}主题:{information.subject}标题:{information.title}页数:{number_of_pages}"""print(txt)返回信息if__name__=='__main__':path='xxxx.pdf'extract_information(path)首先从PyPDF2包导入PdfFileReader。PdfFileReader是一个具有多种与PDF文件交互的方法的类。在这个例子中,我们调用.getDocumentInfo(),它返回一个包含我们感兴趣的大部分信息的DocumentInformation实例。我们也可以在reader对象上调用.getNumPages()让它返回页面中的页数文档。信息变量有几个实例属性,可用于从文档中获取所需的其余元数据。我们可以打印此信息并返回以备将来使用。虽然PyPDF2具有.extractText()可用于其页面对象以提取文本(此示例中未显示),但效果不是很好。有些PDF会返回文本,有些会返回空字符串。如果你想从PDF中提取文本,我建议你看看PDFMiner项目。PDFMiner功能更强大,专为从PDF中提取文本而设计。如何旋转页面?有时PDF处于横向模式而不是纵向模式,甚至颠倒。当有人将文档扫描为PDF或电子邮件时,很可能会发生这种情况。我们可以打印文档并阅读纸质版本,也可以使用Python的强大功能来旋转相关页面。来看看如何使用PyPDF2旋转文章的部分页面:fromPyPDF2importPdfFileReader,PdfFileWriterdefrotate_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)))withopen('rotate_pages.pdf','wb')asfh:pdf_writer.write(fh)if__name__=='__main__':path='newpath.pdf'rotate_pages(path)除了pdfileReader,还引入了pdfileWriter,因为我们需要写一个新的pdf。rotate_pages()获取要修改的PDF的路径。在这个函数中,你需要创建一个名为pdf-writer的writer对象和一个名为pdf-reader的reader对象。接下来,您可以使用.getpage()来获取所需的页面。上面开始输入第0页,即第***页,调用page对象的.rotateClockwise()方法顺时针旋转,输入90。然后同理,对于第二页,调用.rotateCounterLockwise()逆时针旋转并输入90。每次调用Rotation方法后,都会调用.addPage(),这会将页面的旋转版本添加到writer对象。***一页是第3页,没有应用任何旋转。***,使用.write()将所有新页面写入新PDF。如何合并PDF?在很多情况下,我们希望将两个或多个PDF合并为一个PDF。例如,现在可能有一个标准的封面需要用于多种类型的报告。这时候就可以借助python来帮助完成这类工作。以下是完成PDF合并操作的实现代码:fromPyPDF2importPdfFileReader,PdfFileWriterdefmerge_pdfs(paths,output):pdf_writer=PdfFileWriter()forpathinpaths:pdf_reader=PdfFileReader(path)forpageinrange(pdf_reader.getNumPages()):#将每一页添加到writerObjectpdf_writer.addPage(pdf_reader.getPage(page))#Writemergedpdfwithopen(output,'wb')asout:pdf_writer.write(out)if__name__=='__main__':paths=['document1.pdf','document2.pdf']merge_pdfs(paths,output='merged.pdf')如果有pdf列表要合并在一起,可以直接使用merge_pdf函数来完成。此函数将输入路径和输出路径作为参数。首先遍历输入路径并为每个输入创建一个PDF阅读对象。然后遍历PDF文件中的所有页面,并使用.addpage()将这些页面写入writer对象。当列表中所有PDF的所有页面写完后,最后会写一个新的结果。如果您不想合并每个PDF的所有页面,您可以通过添加要添加的页面列表来稍微增强此脚本。对于更多挑战,还可以使用Python的argparse模块为该函数创建一个命令行界面。如何拆分PDF?有时可能需要将一个PDF拆分为多个PDF,对于包含大量扫描内容的PDF尤其重要。以下是使用PyPDF2将PDF拆分为多个文件的方法:))output=f'{name_of_split}{page}.pdf'withopen(output,'wb')asoutput_pdf:pdf_writer.write(output_pdf)if__name__=='__main__':path='xxx.pdf'split(path,'jupyter_page')该函数再次创建PDFreaer对象,并遍历它读取的页面。对于PDF中的每一页,创建一个新的PDF编写器实例并向其添加一个页面。然后,将该页面写入一个唯一命名的文件。脚本完成运行后,就可以将原始PDF的每一页拆分为单独的PDF。如何添加水印?水印是纸质或电子文档上的图像或图案,有些水印只有在特殊的光照条件下才能看到。加水印的重要性在于它可以保护您的知识产权,例如图像或PDF。我们可以使用Python和PyPDF2为文档添加水印,并拥有仅包含水印图像或文本的PDF。下面是给PDF加水印的方法:fromPyPDF2importPdfFileWriter,PdfFileReaderdefcreate_watermark(input_pdf,output,watermark):watermark_obj=PdfFileReader(watermark)watermark_page=watermark_obj.getPage(0)pdf_reader=PdfFileReader(input_pdf)pdf_writer=PdfFileWriter给所有页面加水印()forpageinrange(pdf_reader.getNumPages()):page=pdf_reader.getPage(page)page.mergePage(watermark_page)pdf_writer.addPage(page)withopen(output,'wb')asout: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水印的路径版本水印:包含带水印图像或文本的PDF在代码中,打开带水印的PDF并从文档中抓取第一页,因为水印应该位于此处。然后使用input_pdf和通用pdf_writer对象创建一个PDF的writer对象,以写出带水印的PDF。接下来就是遍历input_pdf中的页面,然后以上面读取的水印对象watermark_page为参数调用.mergePage(),会在当前页面之上覆盖watermark_page,然后将新合并的页面添加到pdf_writer中对象中间。遍历完成后,***将新加水印的PDF写入磁盘。PDF是如何加密的?PyPDF2目前仅支持将用户和所有者密码添加到预先存在的PDF中。在PDF版本中,所有者密码提供了PDF的管理员权限,允许设置文档的权限,而用户密码只允许打开文档。事实上,PyPDF2不允许对文档设置任何权限,即使它允许设置所有者密码。但无论如何,这是它可以加密的方式,也将固有地加密PDF:fromPyPDF2importPdfFileWriter,PdfFileReaderdefadd_encryption(input_pdf,output_pdf,password):pdf_writer=PdfFileWriter()pdf_reader=PdfFileReader(input_pdf)forpageinrange(pdf_reader.getNumPages()):pdf_writer.addPage(pdf_reader.getPage(page))pdf_writer.encrypt(user_pwd=password,owner_pwd=None,use_128bit=True)withopen(output_pdf,'wb')asfh: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进行加密,因此需要遍历其所有页面并添加到writerwriter。最后一步是使用用户密码、所有者密码以及是否应添加128位加密作为参数调用.encrypt()。默认情况下,启用128位加密。如果设置为False,将应用40位加密。结论PyPDF2包非常好用,可以使用PyPDF2自动执行脚本完成对PDF文档的批量操作。本文介绍如何从PDF中提取元数据、旋转页面、合并和拆分PDF、添加水印和添加加密。另外,请留意更新的PyPDF4包,因为它将很快取代PyPDF2。也可以看看pdfrw包,它也做许多与PyPDF2相同的事情。