实用脚本!Python 提取 PDF 指定内容生成新文件!

优采云 发布时间: 2022-04-30 19:15

  实用脚本!Python 提取 PDF 指定内容生成新文件!

  很多时候,我们并不会预知希望提取的页号,而是希望将包含指定内容的页面提取合并为新PDF,本文就以两个真实需求为例进行讲解。

  01

  需求描述

  数据是一份有286页的上市公司公开年报PDF,大致如下

  

  现在需要利用 Python 完成以下两个需求

  “

  需求一:提取所有包含 战略 二字的页面并合并新PDF

  需求二:提取所有包含图片的页面,并分别保存为 PDF 文件

  ”

  02

  前置知识和逻辑梳理

  2.1 PyPDF2 模块实现合并

  PyPDF2 导入模块的代码常常是:

  from PyPDF2 import PdfFileReader, PdfFileWriter<br />

  这里导入了两个方法:

  PdfFileReader 可以理解为读取器PdfFileWriter 可以理解为写入器

  利用 PyPDF2 实现合并运用的一下逻辑:

  读取器将所有pdf读取一遍读取器将读取的内容交给写入器写入器统一输出到一个新pdf

  隐含知识点:读取器只能将读取的内容一页一页交给写入器

  2.2 获取与添加页面

  之前我们的推文中提到这两个代码,下面列出作为复习:

  .getPage 获取特定页.addPage 添加特定页2.3 图片和文字的处理

  要实现本文的需求还要做到很重要的一个判断:确定页面中有无包含的文字或图片

  判断是否包含特定的文字比较简单,遍历每一页的时候都将包含的文本抽提出,做字符串层面的判断即可,代码思路:

  利用 pdfplumber 打开PDF 文件获取指定的页,或者遍历每一页利用 .extract_text() 方法提取当前页的文字判断 “战略” 是否在提取的文字中

  判断是否包含图片,思路和上面是类似的,但方法不同。图片考虑用正则的方法识别,用 fitz 和 re 配合,具体见下文代码

  03

  代码实现

  3.1 需求一的实现

  首先来完成需求一的任务,导入需要用到的库:读取写入PDF文件的 PyPDF2 以及抽提文本的 pdfplumber

  from PyPDF2 import PdfFileReader, PdfFileWriter<br />import pdfplumber<br />

  指定文件所在的路径,同时初始化写入器,将文件交给读取器:

  path = r'C:\xxxxxx'<br />pdf_writer = PdfFileWriter()<br />pdf_reader = PdfFileReader(path + r'\公司年报.PDF')<br />

  以上下文管理器形式通过 pdfplumber 打开文件,同时用 .getNumPages 获取读取器的最大页利于遍历每一页来抽提文字:

  with pdfplumber.open(path + r'\公司年报.PDF') as pdf:<br />    for i in range(pdf_reader.getNumPages()):<br />        page = pdf.pages[i]<br />        print(page.extract_text())<br />

  我们抽提文字的目的是用来判断,将符合要求的页码作为读取器 .getPage 的参数,最后用 .addPage 交给写入器:

  with pdfplumber.open(path + r'\公司年报.PDF') as pdf:<br />    for i in range(pdf_reader.getNumPages()):<br />        page = pdf.pages[i]<br />        print(page.extract_text())<br />        if '战略' in page.extract_text():<br />            pdf_writer.addPage(pdf_reader.getPage(i))<br />            print(i + 1, page.extract_text())<br />

  完成识别后让写入器输出为需要的文件名:

  with open(path + r'\new_公司年报.pdf', 'wb') as out:<br />    pdf_writer.write(out)<br />

  至此,我们就完成了包含特定文字内容页面的提取,并整合成一个PDF。所有的页面均包含“战略”二字:

  

  

  需求一完整代码如下,感兴趣的读者可以自行研究

  from PyPDF2 import PdfFileReader, PdfFileWriter<br />import pdfplumber<br /><br />path = r'C:\xxx'<br />pdf_writer = PdfFileWriter()<br />pdf_reader = PdfFileReader(path + r'\公司年报.PDF')<br /><br />with pdfplumber.open(path + r'\公司年报.PDF') as pdf:<br />    for i in range(pdf_reader.getNumPages()):<br />        page = pdf.pages[i]<br />        print(page.extract_text())<br />        if '战略' in page.extract_text():<br />            pdf_writer.addPage(pdf_reader.getPage(i))<br />            print(i + 1, page.extract_text())<br /><br />with open(path + r'\new_公司年报1.pdf', 'wb') as out:<br />    pdf_writer.write(out)<br />

  3.2 需求二的实现

  接下来完成需求二的任务。首先导入需要的库:

  from PyPDF2 import PdfFileReader, PdfFileWriter<br />import fitz<br />import re<br />import os<br />

  指定文件所在的路径:

  path = r'C:\xxxxxx'<br />

  正则识别图片的部分不细讲,之前的推文已经介绍过,我们直接看代码:

  page_lst = []<br />checkImg = r"/Subtype(?= */Image)"<br />pdf = fitz.open(path + r'\公司年报.PDF')<br />lenXREF = pdf._getXrefLength()<br /><br />for i in range(lenXREF):<br />    text = pdf._getXrefString(i)<br />    isImage = re.search(checkImg, text)<br />    if isImage:<br />        page_lst.append(i)<br /><br />print(page_lst)<br />

  

  获取到所有包含图片的页面后,再结合读取器和写入器的配合就能完成新 PDF 的产生。注意本需求是所有图片单独输出,因此获取到页面后交给写入器直接输出成文件:

  pdf_reader = PdfFileReader(path + r'\公司年报.PDF')<br />for page in page_lst:<br />    pdf_writer = PdfFileWriter()<br />    pdf_writer.addPage(pdf_reader.getPage(page))<br />    with open(path + r'\公司年报_{}.pdf'.format(page + 1), 'wb') as out:<br />        pdf_writer.write(out)<br />

  至此也完成了第二个需求。需要说明的是目前没有非常完美提取PDF图片的方法,本案例介绍的方法识别图片也并不稳定。读者可以利用自己的数据多做尝试。完整代码如下:

  from PyPDF2 import PdfFileReader, PdfFileWriter<br />import fitz<br />import re<br />import os<br /><br />path = r'C:\xxx'<br /><br />page_lst = []<br />checkImg = r"/Subtype(?= */Image)"<br />pdf = fitz.open(path + r'\公司年报.PDF')<br />lenXREF = pdf._getXrefLength()<br />for i in range(lenXREF):<br />    text = pdf._getXrefString(i)<br />    isImage = re.search(checkImg, text)<br />    if isImage:<br />        page_lst.append(i)<br /><br />print(page_lst)<br /><br />pdf_reader = PdfFileReader(path + r'\公司年报.PDF')<br />for page in page_lst:<br />    pdf_writer = PdfFileWriter()<br />    pdf_writer.addPage(pdf_reader.getPage(page))<br />    with open(path + r'\公司年报_{}.pdf'.format(page + 1), 'wb') as out:<br />        pdf_writer.write(out)<br />

  实现这两个单个需求后,就可以将相关代码封装并结合os等模块实现批量操作,解放双手。

  近期阅读学习推荐:

  如何找到我:

  

  

<p data-mid="" style="outline: 0px;max-width: 100%;font-size: 14px;font-family: PingFangSC-Medium, "PingFang SC";font-weight: bold;color: rgb(183, 78, 67);line-height: 20px;box-sizing: border-box !important;overflow-wrap: break-word !important;">分享

  收藏

  点赞

  在看</p>

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线