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

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

大家好,我是早起。

在之前的「Python办公自动化」案专题中,我们已经介绍了如何有选择的提取某些页面进行合并。

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

01. 需求描述

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

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

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

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

02. 前置知识和逻辑梳理

2.1 PyPDF2 模块实现合并

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

  1. from PyPDF2 import PdfFileReader, PdfFileWriter 

这里导入了两个方法:

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

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

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

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

2.2 获取与添加页面

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

  1.  .getPage 获取特定页
  2.  .addPage 添加特定页

2.3 图片和文字的处理

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

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

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

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

03. 代码实现

3.1 需求一的实现

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

  1. from PyPDF2 import PdfFileReader, PdfFileWriter  
  2. import pdfplumber 

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

  1. path = r'C:\xxxxxx'  
  2. pdf_writer = PdfFileWriter()  
  3. pdf_reader = PdfFileReader(path + r'\公司年报.PDF') 

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

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

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

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

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

  1. with open(path + r'\new_公司年报.pdf', 'wb') as out:  
  2.     pdf_writer.write(out) 

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

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

  1. from PyPDF2 import PdfFileReader, PdfFileWriter  
  2. import pdfplumber  
  3. path = r'C:\xxx'  
  4. pdf_writer = PdfFileWriter()  
  5. pdf_reader = PdfFileReader(path + r'\公司年报.PDF')  
  6. with pdfplumber.open(path + r'\公司年报.PDF') as pdf:  
  7.     for i in range(pdf_reader.getNumPages()):  
  8.         page = pdf.pages[i]  
  9.         print(page.extract_text())  
  10.         if '战略' in page.extract_text():  
  11.             pdf_writer.addPage(pdf_reader.getPage(i))  
  12.             print(i + 1, page.extract_text()) 
  13. with open(path + r'\new_公司年报1.pdf', 'wb') as out:  
  14.     pdf_writer.write(out) 

3.2 需求二的实现

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

  1. from PyPDF2 import PdfFileReader, PdfFileWriter  
  2. import fitz  
  3. import re  
  4. import os 

指定文件所在的路径: 

  1. path = r'C:\xxxxxx' 

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

  1. page_lst = []  
  2. checkImg = r"/Subtype(?= */Image)"  
  3. pdf = fitz.open(path + r'\公司年报.PDF')  
  4. lenXREF = pdf._getXrefLength()  
  5. for i in range(lenXREF):  
  6.     text = pdf._getXrefString(i)  
  7.     isImage = re.search(checkImg, text)  
  8.     if isImage:  
  9.         page_lst.append(i)  
  10. print(page_lst) 

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

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

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

  1. from PyPDF2 import PdfFileReader, PdfFileWriter  
  2. import fitz  
  3. import re  
  4. import os  
  5. path = r'C:\xxx'  
  6. page_lst = []  
  7. checkImg = r"/Subtype(?= */Image)"  
  8. pdf = fitz.open(path + r'\公司年报.PDF')  
  9. lenXREF = pdf._getXrefLength()  
  10. for i in range(lenXREF):  
  11.     text = pdf._getXrefString(i)  
  12.     isImage = re.search(checkImg, text)  
  13.     if isImage:  
  14.         page_lst.append(i)  
  15. print(page_lst)  
  16. pdf_reader = PdfFileReader(path + r'\公司年报.PDF')  
  17. for page in page_lst:  
  18.     pdf_writer = PdfFileWriter()  
  19.     pdf_writer.addPage(pdf_reader.getPage(page))  
  20.     with open(path + r'\公司年报_{}.pdf'.format(page + 1), 'wb') as out:  
  21.         pdf_writer.write(out) 

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

 

责任编辑:庞桂玉 来源: Python编程
相关推荐

2009-12-16 10:33:31

Ruby更新文件

2010-03-02 13:21:25

Fedora yum配

2015-08-25 11:29:39

LinuxBcachefs

2013-04-18 10:51:17

Windows 8.1ReFS

2020-07-08 07:54:03

PythonPDF数据

2011-12-02 09:32:19

Windows 8文件系统

2020-11-11 17:00:02

PythonOffice文件PDF

2022-03-15 14:30:54

Windows 11微软应用程序

2011-09-28 15:10:00

GNOME 3.2

2015-09-15 13:38:07

更新升级Windows 10

2018-06-04 10:34:52

EROFSLinux安卓

2021-03-30 05:59:20

Windows10操作系统微软

2009-01-21 19:03:33

服务器虚拟化VMware

2023-10-30 17:21:46

训练数据

2022-06-12 06:48:34

Python代码脚本

2024-03-27 15:46:37

开源Blender

2010-04-13 13:02:43

Unix操作系统

2019-10-09 16:08:21

PythonPython教程Python 开发

2022-03-01 20:26:12

PythonCSV脚本

2010-03-10 12:33:10

Python脚本
点赞
收藏

51CTO技术栈公众号