前言

文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。

作者: wLsq

PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http://t.cn/A6Zvjdun

Portable Document Format(可移植文档格式),或者PDF是一种文件格式,可以用于跨操作系统的呈现和文档交换。尽管PDF最初是由Adobe发明的,但它现在是由国际标准化组织(ISO)维护的开放标准。你可以通过使用PyPDF2包在Python中处理已先存在的PDF。

PyPDF2是一个纯Python包,可用于许多不同类型的PDF操作。 本文将带你了解如何执行以下操作:

从Python中提取PDF中的文档信息

  • 旋转页面
  • 合并PDF
  • 拆分PDF
  • 添加水印
  • 加密PDF

pyPdf,PyPDF2和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的方法:

  1. $ pip install pypdf2

由于PyPDF2没有任何依赖,因此安装非常快。

如何从Python中提取PDF文档信息

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

以下是当前可以提取的数据类型:

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

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

  1. from PyPDF2 import PdfFileReader
  2. def extract_information(pdf_path):
  3. with open(pdf_path, 'rb') as f:
  4. pdf = PdfFileReader(f)
  5. information = pdf.getDocumentInfo()
  6. number_of_pages = pdf.getNumPages()
  7. txt = f"""
  8. Information about {pdf_path}:
  9. Author: {information.author}
  10. Creator: {information.creator}
  11. Producer: {information.producer}
  12. Subject: {information.subject}
  13. Title: {information.title}
  14. Number of pages: {number_of_pages}
  15. """
  16. print(txt)
  17. return information
  18. if __name__ == '__main__':
  19. path = 'xxxx.pdf'
  20. extract_information(path)

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

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

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

如何旋转页面?

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

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

  1. from PyPDF2 import PdfFileReader, PdfFileWriter
  2. def rotate_pages(pdf_path):
  3. pdf_writer = PdfFileWriter()
  4. pdf_reader = PdfFileReader(path)
  5. # 顺时针旋转90度
  6. page_1 = pdf_reader.getPage(0).rotateClockwise(90)
  7. pdf_writer.addPage(page_1)
  8. # 逆时针旋转90度
  9. page_2 = pdf_reader.getPage(1).rotateCounterClockwise(90)
  10. pdf_writer.addPage(page_2)
  11. # 在正常方向上添加一页
  12. pdf_writer.addPage(pdf_reader.getPage(2))
  13. with open('rotate_pages.pdf', 'wb') as fh:
  14. pdf_writer.write(fh)
  15. if __name__ == '__main__':
  16. path = '新路径.pdf'
  17. rotate_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合并的操作:

  1. from PyPDF2 import PdfFileReader, PdfFileWriter
  2. def merge_pdfs(paths, output):
  3. pdf_writer = PdfFileWriter()
  4. for path in paths:
  5. pdf_reader = PdfFileReader(path)
  6. for page in range(pdf_reader.getNumPages()):
  7. # 将每页添加到writer对象
  8. pdf_writer.addPage(pdf_reader.getPage(page))
  9. # 写入合并的pdf
  10. with open(output, 'wb') as out:
  11. pdf_writer.write(out)
  12. if __name__ == '__main__':
  13. paths = ['document1.pdf', 'document2.pdf']
  14. merge_pdfs(paths, output='merged.pdf')

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

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

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

如何拆分PDF?

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

  1. from PyPDF2 import PdfFileReader, PdfFileWriter
  2. def split(path, name_of_split):
  3. pdf = PdfFileReader(path)
  4. for page in range(pdf.getNumPages()):
  5. pdf_writer = PdfFileWriter()
  6. pdf_writer.addPage(pdf.getPage(page))
  7. output = f'{name_of_split}{page}.pdf'
  8. with open(output, 'wb') as output_pdf:
  9. pdf_writer.write(output_pdf)
  10. if __name__ == '__main__':
  11. path = 'xxx.pdf'
  12. split(path, 'jupyter_page')

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

如何添加水印?

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

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

  1. from PyPDF2 import PdfFileWriter, PdfFileReader
  2. def create_watermark(input_pdf, output, watermark):
  3. watermark_obj = PdfFileReader(watermark)
  4. watermark_page = watermark_obj.getPage(0)
  5. pdf_reader = PdfFileReader(input_pdf)
  6. pdf_writer = PdfFileWriter()
  7. # 给所有页面添加水印
  8. for page in range(pdf_reader.getNumPages()):
  9. page = pdf_reader.getPage(page)
  10. page.mergePage(watermark_page)
  11. pdf_writer.addPage(page)
  12. with open(output, 'wb') as out:
  13. pdf_writer.write(out)
  14. if __name__ == '__main__':
  15. create_watermark(
  16. input_pdf='Jupyter_Notebook_An_Introduction.pdf',
  17. output='watermarked_notebook.pdf',
  18. 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写入磁盘。

如何加密PDF?

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

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

  1. from PyPDF2 import PdfFileWriter, PdfFileReader
  2. def add_encryption(input_pdf, output_pdf, password):
  3. pdf_writer = PdfFileWriter()
  4. pdf_reader = PdfFileReader(input_pdf)
  5. for page in range(pdf_reader.getNumPages()):
  6. pdf_writer.addPage(pdf_reader.getPage(page))
  7. pdf_writer.encrypt(user_pwd=password, owner_pwd=None,
  8. use_128bit=True)
  9. with open(output_pdf, 'wb') as fh:
  10. pdf_writer.write(fh)
  11. if __name__ == '__main__':
  12. add_encryption(input_pdf='reportlab-sample.pdf',
  13. output_pdf='reportlab-encrypted.pdf',
  14. password='twofish')

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

PS:如果想了解更多关于python的应用,可以私信小编

PDF各种骚操作如何用python实现的更多相关文章

  1. Python小白需要知道的 20 个骚操作!

    Python小白需要知道的 20 个骚操作! Python 是一个解释型语言,可读性与易用性让它越来越热门.正如 Python 之禅中所述: 优美胜于丑陋,明了胜于晦涩. 在你的日常编码中,以下技巧可 ...

  2. python骚操作---Print函数用法

    ---恢复内容开始--- python骚操作---Print函数用法 在 Python 中,print 可以打印所有变量数据,包括自定义类型. 在 3.x 中是个内置函数,并且拥有更丰富的功能. 参数 ...

  3. Python骚操作!一行命令把电脑变成服务器!

    不知道你有没有遇到这么一种情况,就是你有时候想要把电脑上的一些东西传输到你的手机或者 Pad ,你要么需要使用数据线连接到电脑,有时候还要装各种驱动才可以进行数据传输,要么需要借助第三方的工具,在局域 ...

  4. Python中对 文件 的各种骚操作

    Python中对 文件 的各种骚操作 python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Python脚本工作的目录路径: os.getc ...

  5. Python骚操作从列表推导和生成器表达式开始

    序列 序列是指一组数据,按存放类型分为容器序列与扁平序列,按能否被修改分为不可变序列与可变序列. 容器序列与扁平序列 容器序列存放的是对象的引用,包括list.tuple.collections.de ...

  6. 如何在命令长度受限的情况下成功get到webshell(函数参数受限突破、mysql的骚操作)

    0x01 问题提出 还记得上篇文章记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门),我们讲到了一些PHP的一些如何巧妙地绕过数字和字母受限的技巧,今天我要给大家分享的是如 ...

  7. 如何用python“优雅的”调用有道翻译?

    前言 其实在以前就盯上有道翻译了的,但是由于时间问题一直没有研究(我的骚操作还在后面,记得关注),本文主要讲解如何用python调用有道翻译,讲解这个爬虫与有道翻译的js“斗争”的过程! 当然,本文仅 ...

  8. 用Markdown写Html和.md也就图一乐,真骚操作还得用来做PPT

    前言 和这篇文章一样,我就是用Markdown写的.相信各位平时也就用Markdown写写文档,做做笔记,转成XHtml.Html等,今天教大伙一招骚操作:用Markdown写PPT. 绝大多数朋友做 ...

  9. 如何用python抓取js生成的数据 - SegmentFault

    如何用python抓取js生成的数据 - SegmentFault 如何用python抓取js生成的数据 1赞 踩 收藏 想写一个爬虫,但是需要抓去的的数据是js生成的,在源代码里看不到,要怎么才能抓 ...

随机推荐

  1. vue 指令,成员,组件

    目录 复习 v-once指令 v-cloak指令(了解) 条件指令 v-pre指令(了解) 循环指令 todolist留言板案例 实例成员 - 插值表达式符号(了解) 计算属性 属性监听 组件 局部组 ...

  2. python浅学【网络服务中间件】之Redis

    一.关于NoSQL: NoSQL(NoSQL = Not Only SQL ),"不仅仅是SQL". 相比MySQL等关系型数据库,NoSQL为非关系型的数据存储 Nosql中比较 ...

  3. Salesforce LWC学习(十四) Continuation进行异步callout获取数据

    本篇参考: https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.apex_continua ...

  4. python学习(五)之列表元素的积

    前几天,学完python的列表之后,我们老师留了一道关于列表的题目.几天后,老师讲解习题,很荣幸成为被老师点名讲解自己代码的其中之一下面把我的想法分享一下. 描述一个由n(n>1)个数字组成的列 ...

  5. Docker镜像拉取慢的解决方法

    镜像加速器配置: 下文配置引用于阿里云说明文档:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 1. 安装/升级Docker客户 ...

  6. Mysql获取系统时间,年,月,日

      Mysql数据库中获取系统时间,年,月,日单个获取 获取当前系统日期时间:select SYSDATE() AS 系统日期时间; 获取当前系统年月日:select current_date AS ...

  7. excel中存储的icount,赋值完之后

    最近需要实现一个功能,为了确保每次函数运行的时候count是唯一的,所以想读取excel中存储的icount,赋值完之后对其进行+1操作,并存入excel文件,确保下次读取的count是新的,没有出现 ...

  8. 解决python3使用cx_Freeze打包成exe后不能运行

    我使用的是python3.4,在使用cx_Freeze打包成exe后发现有些打包后程序能够运行,但是有些无法运行 这是控制台报错 经过多方查找发现原来是windows缺少一些python的扩展包 如下 ...

  9. [POJ2533]Longest Ordered Subsequence<dp>

    题目链接:http://poj.org/problem?id=2533 描述: A numeric sequence of ai is ordered if a1 < a2 < ... & ...

  10. vue 对px 做rem 自动转换

    插件:postcss 安装: npm install postcss-pxtorem vue.config.js 配置 css: { loaderOptions: { postcss: { plugi ...