同样是 Automate The Boring Stuff 上面有关 PDF 处理的内容,自己整理出来以便以后自己方便查看。
处理 PDF 的库是 PyPDF2, 以下所有的操作都要在导入这个库之后进行。
import PyPDF2 # 导入 PyPDF2 模块处理 PDF
从 PDF 抽取文字
pdfFileObj = open('meetingminutes.pdf', 'rb') # 把目标文件作为二进制文件打开 pdfReader = PyPDF2.PdfFileReader(pdfFileObj) # 用模块的 PdfFileReader 方法把打开的文件变成一个 PDF 文件对象 print(pdfReader.numPages) # 显示 PDF 文件对象有多少页 pageObj = pdfReader.getPage(0) # 把 PDF 文件的第一页变成一个 PDF 页面对象 print(pageObj.extractText()) # 把这个 PDF 页面对象的文字抽取出来 pdfFileObj.close() # 关闭目标文件
已知密码打开已经加密的 PDF
要注意的是即使知道了密码打开了 PDF, 该 PDF 文件本身不算是已经解密了,下次打开依然需要密码。
pdfReader = PyPDF2.PdfFileReader(open('encrypted.pdf', 'rb')) # 把目标文件作为二进制文件打开,用模块的 PdfFileReader 方法把打开的文件变成一个 PDF 文件对象 print(pdfReader.isEncrypted) # 检查 PDF 文件是否已经加密 pageObj = pdfReader.getPage(0) # 尝试获得第一页,加密的状态下会出错 pdfReader = PyPDF2.PdfFileReader(open('encrypted.pdf', 'rb')) # 再次把目标文件作为二进制文件打开,用模块的 PdfFileReader 方法把打开的文件变成一个 PDF 文件对象 pdfReader.decrypt('rosebud') # 使用密码 rosebud 解密解密 PDF 对象;并不能直接去掉 PDF 文件本身的密码 pageObj = pdfReader.getPage(0) # 获得第一页 print(pageObj.extractText()) # 把这个 PDF 页面对象的文字抽取出来 pdfFileObj.close() # 关闭目标文件
基于其他 PDF 文件创建 PDF 文件
PDF 文件无法直接复制到一个新的文件当中,只能把所需要的页面一页一页复制过去。
- 用 PdfFileReader 打开一个或者多个原始 PDF 文件
- 创建一个新的 PdfFileWriter 对象
- 从 PdfFileReader 对象复制页面到 PdfFileWriter 对象
- 用 PdfFileWriter 对象输出 PDF 文件,需要用到 open(‘filename.pdf’, ‘wb’)
复制已有 PDF 文件的页面到新的 PDF 文件当中
pdf1File = open('meetingminutes.pdf', 'rb') # 把第一个目标文件作为二进制文件打开 pdf2File = open('meetingminutes2.pdf', 'rb') # 把第二个目标文件作为二进制文件打开 pdf1Reader = PyPDF2.PdfFileReader(pdf1File) # 用模块的 PdfFileReader 方法把打开的文件变成一个 PDF 文件对象 pdf2Reader = PyPDF2.PdfFileReader(pdf2File) # 用模块的 PdfFileReader 方法把打开的文件变成一个 PDF 文件对象 pdfWriter = PyPDF2.PdfFileWriter() # 用模块的 PdfFileWriter 方法创建一个新的 PDF 文件对象 for pageNum in range(pdf1Reader.numPages): # 在第一个 PDF 文件对象的页数范围内 pageObj = pdf1Reader.getPage(pageNum) # 遍历每一个 PDF 文件对象的每一页 pdfWriter.addPage(pageObj) # 把这一页新增到 pdfWriter 文件对象当中。只能新增页面,无法从中间插入 for pageNum in range(pdf2Reader.numPages): # 在第二个 PDF 文件对象的页数范围内 pageObj = pdf2Reader.getPage(pageNum) # 遍历每一个 PDF 文件对象的每一页 pdfWriter.addPage(pageObj) # 把这一页新增到 pdfWriter 文件对象当中。只能新增页面,无法从中间插入 pdfOutputFile = open('combinedminutes.pdf', 'wb') # 在文件系统新建一个指定文件名的文件 pdfWriter.write(pdfOutputFile) # 把 pdfWriter 文件对象写入目标文件当中 pdfOutputFile.close() # 关闭文件 pdf1File.close() # 关闭文件 pdf2File.close() # 关闭文件
旋转页面
minutesFile = open('meetingminutes.pdf', 'rb') # 把目标文件作为二进制文件打开 pdfReader = PyPDF2.PdfFileReader(minutesFile) # 用模块的 PdfFileReader 方法把打开的文件变成一个 PDF 文件对象 page = pdfReader.getPage(0) # 把文件对象的第一页作为一个页面 page.rotateClockwise(90) # 把第一页顺时针旋转 90 度;只能是 90 180 270 pdfWriter = PyPDF2.PdfFileWriter() # 用模块的 PdfFileWriter 方法创建一个新的 PDF 文件对象 pdfWriter.addPage(page) # 把这一页新增到 pdfWriter 文件对象当中 resultPdfFile = open('rotatedPage.pdf', 'wb') # 在文件系统新建一个指定文件名的文件 pdfWriter.write(resultPdfFile) # 把 pdfWriter 文件对象写入目标文件当中 resultPdfFile.close() # 关闭文件 minutesFile.close() # 关闭文件
加入水印/在页面内容上新增内容
minutesFile = open('meetingminutes.pdf', 'rb') # 把目标文件作为二进制文件打开 pdfReader = PyPDF2.PdfFileReader(minutesFile) # 用模块的 PdfFileReader 方法把打开的文件变成一个 PDF 文件对象 minutesFirstPage = pdfReader.getPage(0) # 把文件对象的第一页作为一个页面 pdfWatermarkReader = PyPDF2.PdfFileReader(open('watermark.pdf', 'rb')) # 把水印目标文件作为二进制文件打开,用模块的 PdfFileReader 方法把打开的文件变成一个 PDF 文件对象 minutesFirstPage.mergePage(pdfWatermarkReader.getPage(0)) # 把原始文件的第一页与水印文件的第一页合并,水印文件在上层 pdfWriter = PyPDF2.PdfFileWriter() # 用模块的 PdfFileWriter 方法创建一个新的 PDF 文件对象 pdfWriter.addPage(minutesFirstPage) # 把合并后的这一页新增到 pdfWriter 文件对象当中 for pageNum in range(1, pdfReader.numPages): # 对剩下的页面不做处理,新增加到新的 PDF 文件对象当中 pageObj = pdfReader.getPage(pageNum) # 遍历第二页到最后一页,把原始文件的每一页都作为一个页面对象 pdfWriter.addPage(pageObj) # 把每一个页面对象新增到 pdfWriter 文件对象当中 resultPdfFile = open('watermarkedCover.pdf', 'wb') # 在文件系统新建一个指定文件名的文件 pdfWriter.write(resultPdfFile) # 把 resultPdfFile 文件对象写入目标文件当中 minutesFile.close() # 关闭文件 resultPdfFile.close() # 关闭文件
给 PDF 文件加上密码
pdfFile = open('meetingminutes.pdf', 'rb') # 把目标文件作为二进制文件打开 pdfReader = PyPDF2.PdfFileReader(pdfFile) # 用模块的 PdfFileReader 方法把打开的文件变成一个 PDF 文件对象 pdfWriter = PyPDF2.PdfFileWriter() # 用模块的 PdfFileWriter 方法创建一个新的 PDF 文件对象 for pageNum in range(pdfReader.numPages): # 在 PDF 文件对象的页数范围内 pdfWriter.addPage(pdfReader.getPage(pageNum)) # 遍历每一个 PDF 文件对象的每一页,并新增到一个新的文件当中 pdfWriter.encrypt('swordfish') # 把新的 PDF 文件对象用密码 swordfish 加密。PDF 有两个密码,一个是查看的密码,一个是拥有者密码,分别对应 encrypt() 的两个参数。如果只指定一个,则是两者都是 resultPdfFile = open('encryptedminutes.pdf', 'wb') # 在文件系统新建一个指定文件名的文件 pdfWriter.write(resultPdfFile) # 把 resultPdfFile 文件对象写入目标文件当中 resultPdfFile.close() # 关闭文件 pdfFile.close() # 关闭文件
至于平时 PDF 的操作,除了需要抽取某些页面出来之外(这个就是第三方软件可以方便做到的),还有的就是处理一些扫描的时候放错方向然后一页正面一页反面的 PDF; 曾经在这样的事情上面耗费很多时间。
这里并没有涉及到从其他文件生成 PDF, 是因为似乎这个库并不能从其他非 PDF 文件创建 PDF. 查了一下似乎需要 pywin32 这个库,然而看上去有些复杂还是等到有需要批量生成的时候再说了。
[…] 这也是 Automate The Boring Stuff With Python 上面的内容,书里面本来是和上一部分 PDF 相关内容放在一起的。 […]