大家好,实用我是脚本早起。
在之前的定内「Python办公自动化」案专题中,我们已经介绍了如何有选择的容生提取某些页面进行合并。
但是成新很多时候,我们并不会预知希望提取的文件页号,而是实用希望将包含指定内容的页面提取合并为新PDF,本文就以两个真实需求为例进行讲解。脚本
数据是定内一份有286页的上市公司公开年报PDF,大致如下:
现在需要利用 Python 完成以下两个需求:
需求一:提取所有包含 战略 二字的容生页面并合并新PDF
需求二:提取所有包含图片的页面,并分别保存为 PDF 文件
PyPDF2 导入模块的成新代码常常是:
from PyPDF2 import PdfFileReader, PdfFileWriter这里导入了两个方法:
PdfFileReader 可以理解为读取器 PdfFileWriter 可以理解为写入器利用 PyPDF2 实现合并运用的一下逻辑:
读取器将所有pdf读取一遍 读取器将读取的内容交给写入器 写入器统一输出到一个新pdf隐含知识点:读取器只能将读取的内容一页一页交给写入器
之前我们的推文中提到这两个代码,下面列出作为复习:
.getPage 获取特定页 .addPage 添加特定页要实现本文的需求还要做到很重要的一个判断:确定页面中有无包含的文字或图片
判断是否包含特定的云服务器文字比较简单,遍历每一页的实用时候都将包含的文本抽提出,做字符串层面的脚本判断即可,代码思路:
利用 pdfplumber 打开PDF 文件 获取指定的定内页,或者遍历每一页 利用 .extract_text() 方法提取当前页的文字 判断 “战略” 是否在提取的文字中判断是否包含图片,思路和上面是类似的,但方法不同。图片考虑用正则的方法识别,用 fitz 和 re 配合,具体见下文代码
首先来完成需求一的任务,导入需要用到的库:读取写入PDF文件的 PyPDF2 以及抽提文本的 pdfplumber
from PyPDF2 import PdfFileReader, PdfFileWriter import pdfplumber指定文件所在的路径,同时初始化写入器,将文件交给读取器:
path = rC:\xxxxxx pdf_writer = PdfFileWriter() pdf_reader = PdfFileReader(path + r\公司年报.PDF)以上下文管理器形式通过 pdfplumber 打开文件,同时用 .getNumPages 获取读取器的最大页利于遍历每一页来抽提文字:
with pdfplumber.open(path + r\公司年报.PDF) as pdf: for i in range(pdf_reader.getNumPages()): page = pdf.pages[i] print(page.extract_text())我们抽提文字的目的高防服务器是用来判断,将符合要求的页码作为读取器 .getPage 的参数,最后用 .addPage 交给写入器:
with pdfplumber.open(path + r\公司年报.PDF) as pdf: for i in range(pdf_reader.getNumPages()): page = pdf.pages[i] print(page.extract_text()) if 战略 in page.extract_text(): pdf_writer.addPage(pdf_reader.getPage(i)) print(i + 1, page.extract_text())完成识别后让写入器输出为需要的文件名:
with open(path + r\new_公司年报.pdf, wb) as out: pdf_writer.write(out)至此,我们就完成了包含特定文字内容页面的提取,并整合成一个PDF。所有的页面均包含“战略”二字:
需求一完整代码如下,感兴趣的读者可以自行研究。
from PyPDF2 import PdfFileReader, PdfFileWriter import pdfplumber path = rC:\xxx pdf_writer = PdfFileWriter() pdf_reader = PdfFileReader(path + r\公司年报.PDF) with pdfplumber.open(path + r\公司年报.PDF) as pdf: for i in range(pdf_reader.getNumPages()): page = pdf.pages[i] print(page.extract_text()) if 战略 in page.extract_text(): pdf_writer.addPage(pdf_reader.getPage(i)) print(i + 1, page.extract_text()) with open(path + r\new_公司年报1.pdf, wb) as out: pdf_writer.write(out)接下来完成需求二的任务。首先导入需要的库:
from PyPDF2 import PdfFileReader, PdfFileWriter import fitz import re import os指定文件所在的路径:
path = rC:\xxxxxx正则识别图片的部分不细讲,之前的推文已经介绍过,我们直接看代码:
page_lst = [] checkImg = r"/Subtype(?= */Image)" pdf = fitz.open(path + r\公司年报.PDF) lenXREF = pdf._getXrefLength() for i in range(lenXREF): text = pdf._getXrefString(i) isImage = re.search(checkImg, text) if isImage: page_lst.append(i) print(page_lst)获取到所有包含图片的页面后,再结合读取器和写入器的配合就能完成新 PDF 的产生。注意本需求是所有图片单独输出,因此获取到页面后交给写入器直接输出成文件:
pdf_reader = PdfFileReader(path + r\公司年报.PDF) for page in page_lst: pdf_writer = PdfFileWriter() pdf_writer.addPage(pdf_reader.getPage(page)) with open(path + r\公司年报_{ }.pdf.format(page + 1), wb) as out: pdf_writer.write(out)至此也完成了第二个需求。需要说明的是亿华云目前没有非常完美提取PDF图片的方法,本案例介绍的方法识别图片也并不稳定。读者可以利用自己的数据多做尝试。完整代码如下:
from PyPDF2 import PdfFileReader, PdfFileWriter import fitz import re import os path = rC:\xxx page_lst = [] checkImg = r"/Subtype(?= */Image)" pdf = fitz.open(path + r\公司年报.PDF) lenXREF = pdf._getXrefLength() for i in range(lenXREF): text = pdf._getXrefString(i) isImage = re.search(checkImg, text) if isImage: page_lst.append(i) print(page_lst) pdf_reader = PdfFileReader(path + r\公司年报.PDF) for page in page_lst: pdf_writer = PdfFileWriter() pdf_writer.addPage(pdf_reader.getPage(page)) with open(path + r\公司年报_{ }.pdf.format(page + 1), wb) as out: pdf_writer.write(out)实现这两个单个需求后,就可以将相关代码封装并结合os等模块实现批量操作,解放双手。