Python提取PDF指定内容并生成新文件
作者:程序员启航 发布时间:2022-11-09 19:44:00
在之前的Python办公自动化案专题中,我们已经介绍了如何有选择的提取某些页面进行合并。
但是很多时候,我们并不会预知希望提取的页号,而是希望将包含指定内容的页面提取合并为新PDF,本文就以两个真实需求为例进行讲解。
01需求描述
数据是一份有286页的上市公司公开年报PDF,大致如下
现在需要利用 Python 完成以下两个需求
“需求一:提取所有包含 战略 二字的页面并合并新PDF
需求二:提取所有包含图片的页面,并分别保存为 PDF 文件
”
02前置知识和逻辑梳理
2.1 PyPDF2
模块实现合并
PyPDF2
导入模块的代码常常是:
from PyPDF2 import PdfFileReader, PdfFileWriter
这里导入了两个方法:
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
import pdfplumber
指定文件所在的路径,同时初始化写入器,将文件交给读取器:
path = r'C:\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 = r'C:\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)
3.2 需求二的实现
接下来完成需求二的任务。首先导入需要的库:
from PyPDF2 import PdfFileReader, PdfFileWriter
import fitz
import re
import os
指定文件所在的路径:
path = r'C:\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 = r'C:\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等模块实现批量操作,解放双手。
来源:https://blog.csdn.net/aaahtml/article/details/117650641


猜你喜欢
- 实战场景这次被我们盯上的平台是【SMZDM】。本次目标站点是:aHR0cHM6Ly93d3cuc216ZG0uY29tLw==。正式开始前,
- 如下所示:import pymysqlimport timeimport redef get_raw_label(rece): re1 =
- 在实现鼠标停在某元素上,会出现提示信息,以前我们太多是采用javascript脚本代码来实现。看了怿飞的IE中伪类:hover的使用及BUG
- 排序这个词,我的第一感觉是几乎所有App都有排序的地方,淘宝商品有按照购买时间的排序、B站的评论有按照热度排序的...对于MySQL,一说到
- 从这里开始我的博客,后台数据库是什么?没错,就是MySQL,服务器端使用的脚本就是PHP,整个框架使用的是WordPress。PHP和MyS
- Jupyter notebook 更改文件打开的默认路径第一步:修改图标- 找到 Jupyter notebook 桌面图标- 对着 Jup
- 首先,建一个文件夹,把你要隐藏的文件放在里面,你的所有黑客程序什么的。假设你建的文件夹叫hacker然后呢,我们给这个文件夹加个扩展名(后缀
- 本文实例讲述了Python及Django框架生成二维码的方法。分享给大家供大家参考,具体如下:一、包的安装和简单使用1.1 用Python来
- 前言本文是美团一位大佬写的,还不错拿出来和大家分享下,代码中嵌套在html中sql语句是java框架的写法,理解其sql要执行的语句即可。背
- 初学python,小缘缘出了几道题: 有一 list a = [1, 2, 3, 4, 5, 6] 请将 a 依 0, 1 1, 2 2,
- 例如:文本abcaBcabCaBCabcaBCa,关键字bc,在不区分大小写的情况,一共有6个匹配项。 则在网页中显示的是abcaBcabC
- 目录jiaba库的使用1、jieba库的安装2、统计荷塘月色词频总结jiaba库的使用jieba库是一款优秀的 Python 第三方中文分词
- 本文为大家分享了Ubuntu18.04安装mysql5.7.23的具体方法,供大家参考,具体内容如下参考文章:Ubuntu 18.04 安装
- 前言上机实践课程开始了,嗯,老师来了之后念了下PPT,然后说:开始做吧.........然后就开始了Python的GUI之路,以前没接触过P
- 在调用后端接口时,由于后端接口的不规范统一,接口最外层在没有数据时返回的是空数组(其实更想要的是空json对象),而在有数据时返回的是jso
- 有如下格式的文本文件/“/请/!/”/“/请/!/”/两名/剑士/各自/倒转/剑尖/,/右手/握/剑柄/,/左手/搭于/右手/手背/,/躬身
- 一、为何人工智能(AI)首选Python?读完这篇文章你就知道了。我们看谷歌的TensorFlow基本上所有的代码都是C++和Python,
- 一、前言在生活中,我们经常会遇到电脑中文件重复的情况。在文件较少的情况下,这类情况还比较容易处理,最不济就是一个个手动对比删除;而在重复文件
- 引言基于net包的小应用完整代码已经上传到github GitHub-TCP欢迎star和issueTCP介绍特点面向连接的运输
- Python list在介绍 Python tuple 时,我使用了类比的方法,将其比做一个袋子,您可以在袋子中存放不同的东西。Python