Python 自动化:处理 PDF(笔记)

P

同样是 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 文件无法直接复制到一个新的文件当中,只能把所需要的页面一页一页复制过去。

  1. 用 PdfFileReader 打开一个或者多个原始 PDF 文件
  2. 创建一个新的 PdfFileWriter 对象
  3. 从 PdfFileReader 对象复制页面到 PdfFileWriter 对象
  4. 用 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 这个库,然而看上去有些复杂还是等到有需要批量生成的时候再说了。

About the author

secangel

双子座 AB 型,资深女校男生

1 comment

About Author

secangel

双子座 AB 型,资深女校男生

Keep In Touch