第107天: Python 解析 PDF

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介: 第107天: Python 解析 PDF

上次给大家介绍了 Python 如何操作 Word 和 Excel ,而今天想为大家再介绍下,用 Python 如何解析 PDF ,PDF 格式不像前面两个那么规范,从它的表现来看,它更像是一张图片,在一张白纸上把内容摆放在固定的位置上,没有逻辑结构。不过还是那句话,可以先了解下都能实现什么功能,以备不时之需。


正是因为 PDF 没有统一的规范,也没有逻辑结构,比如句子或段落,并且不能自适应页面大小的调整。今天要介绍的 PDFMiner 尝试通过猜测它们的布局来重建它们的结构,但是并不能保证一定能识别成功,尤其是对图片和表格的识别处理会差一些。


安装 PDFMiner


解析 PDF 需要用到 pdfminer 库,目前最新版本只支持 Python3.6 及以上 ,执行如下安装命令:


$ pip3 install pdfminer
################# 运行结果 ################Collecting pdfminer  Downloading https://files.pythonhosted.org/packages/71/a3/155c5cde5f9c0b1069043b2946a93f54a41fd72cc19c6c100f6f2f5bdc15/pdfminer-20191125.tar.gz (4.2MB)     |████████████████████████████████| 4.2MB 2.8MB/s Collecting pycryptodome (from pdfminer)  Downloading https://files.pythonhosted.org/packages/cc/a6/f7e09ad45296eff20bd1db5aa14b1c9ea06826dd68eb2a7a27572c71d581/pycryptodome-3.9.4-cp37-cp37m-macosx_10_6_intel.whl (10.1MB)     |████████████████████████████████| 10.1MB 1.6MB/s Building wheels for collected packages: pdfminer  Building wheel for pdfminer (setup.py) ... done  Stored in directory: /Users/mjg/Library/Caches/pip/wheels/e1/00/af/720a55d74ba3615bb4709a3ded6dd71dc5370a586a0ff6f326Successfully built pdfminerInstalling collected packages: pycryptodome, pdfminerSuccessfully installed pdfminer-20191125 pycryptodome-3.9.4


OK,如果提示以上信息则安装成功。


解析概述


由于PDF文件有如此大和复杂的结构,完整解析 PDF 文件很费时费力的。


因此 PDFMiner 采用了一个懒惰分析的策略,就是只分析你所需要的部分。换句话就是说,根据你自己的需要只解释出你要的那部分就可以了。这里有两个核心类是必须的 PDFParserPDFDocument,除了这两个模块还有以下几个模块来配合使用。


模块名 说明
PDFParser 从文件中获取数据
PDFDocument 存储文档数据结构到内存中
PDFPageInterpreter 解析page内容
PDFDevice 把解析到的内容转化为你需要的东西
PDFResourceManager 存储共享资源,例如字体或图片等


下面这个图表示了 PDFMiner 各模块之间的关系,让我们能有个基本的认识:


image.png


基本用法

首先我准备了一个 pdf 格式的文档,内容基本如下图这样:



微信图片_20220211100150.jpg


下面这段代码给出了 PDFMiner 解析 PDF 文档的基本方法,首先打开 pdf 文件,创建解析对象,存储文档结构,创建资源管理对象以及共享资源,然后再创建 device 对象,最后再创建文档解析对象,并处理文档中的每一页。是不是看起来很复杂,不过确实也挺麻烦,还是让我们直接看代码吧。


# pdf_1.py
# 导入库from pdfminer.pdfparser import PDFParserfrom pdfminer.pdfdocument import PDFDocumentfrom pdfminer.pdfpage import PDFPagefrom pdfminer.pdfpage import PDFTextExtractionNotAllowedfrom pdfminer.pdfinterp import PDFResourceManagerfrom pdfminer.pdfinterp import PDFPageInterpreterfrom pdfminer.pdfdevice import PDFDevicefrom pdfminer.layout import LAParamsfrom pdfminer.converter import PDFPageAggregator
# 设置文档密码password = ''
#打开pdf文件fp = open('pdfminer.pdf','rb')
#从文件句柄创建一个pdf解析对象parser = PDFParser(fp)
#创建pdf文档对象,存储文档结构document = PDFDocument(parser,password)
#创建一个pdf资源管理对象,存储共享资源rsrcmgr = PDFResourceManager()
#创建一个device对象device = PDFDevice(rsrcmgr)
#创建一个解释对象interpreter = PDFPageInterpreter(rsrcmgr, device)
#处理包含在文档中的每一页for page in PDFPage.create_pages(document):    interpreter.process_page(page)


这样就完成了将页面对象加载的操作,下面通过命令 python pdf_1.py 运行程序,没有报错就说明页面信息已经成功加载至内存,然后我们就得想办法分别解析各类型信息,那都有哪些类型的对象呢?


解析对象


布局分析器把 pdf 文档中每一页返回为一个 LTPage 对象. 该对象包含该页面中的所有子对象,它们之间的关系大概如下图所示:


image.png


接下来我再列出一个表格具体说明下各对象:

对象名 对象说明 备注
LTPage 代表一个完整的页面,可以包含子对象 例如:LTTextBox,LTFigure,LTImage,LTRect,LTCurve和LTLine
LTTextBox 它包含 LTTextLine 对象的列表,代表一组被包含在矩形区域中的文本 注意:该box是根据几何学分析得到的,并不一定准确地表现为该文本的逻辑范围,get_text()方法可以返回文本内容
LTTextLine 包含一个LTChar对象的列表,表现为单行文本 字符表现为一行或一列,取决于文本书写方式,get_text()方法返回文本内容
LTChar 表示一个在文本中的真实的字母,作为一个unicode字符串 LTChar 对象有真实的分隔符
LTAnno 表示一个在文本中的真实的字母,作为一个unicode字符串 LTAnno 对象没有,是虚拟分隔符,按照两个字符之间的关系,布局分析器插入虚拟分隔符
LTFigure 表示一个被 PDF Form 对象使用的区域 pdf form适用于目前的图表(present figures)或者页面中植入的另一个pdf文档图片,LTFigure对象可以递归
LTImage 表示一个图形对象,可以是JPEG或者其他格式 但 PDFMiner 目前没有花太多精力在图形对象上
LTLine 表示一根直线 用来分割文本或图表(figures)
LTRect 表示一个矩形 用来框住别的图片或者图表
LTCurve 代表一个贝塞尔曲线


好了,了解以上对象都表示什么以后,现在我们写一段代码解析一个 pdf 并打印出来所解析的内容。


# pdf_2.py
# 导入库from pdfminer.pdfparser import PDFParserfrom pdfminer.pdfdocument import PDFDocumentfrom pdfminer.pdfpage import PDFPagefrom pdfminer.pdfpage import PDFTextExtractionNotAllowedfrom pdfminer.pdfinterp import PDFResourceManagerfrom pdfminer.pdfinterp import PDFPageInterpreterfrom pdfminer.pdfdevice import PDFDevicefrom pdfminer.layout import *from pdfminer.converter import PDFPageAggregator
# 提供初始密码password = ''# 没有密码可以初始密码# document.initialize()
#打开pdf文件fp = open('pdfminer.pdf','rb')
#从文件句柄创建一个pdf解析对象parser = PDFParser(fp)
#创建pdf文档对象,存储文档结构document = PDFDocument(parser, password)
#创建一个pdf资源管理对象,存储共享资源rsrcmgr = PDFResourceManager()
laparams = LAParams()
#创建一个device对象device = PDFPageAggregator(rsrcmgr, laparams=laparams)
#创建一个解释对象interpreter = PDFPageInterpreter(rsrcmgr, device)
#处理包含在文档中的每一页for page in PDFPage.create_pages(document):    interpreter.process_page(page)    layout = device.get_result()    for x in layout:        # 获取文本对象        if isinstance(x, LTTextBox):            print(x.get_text().strip())        # 获取图片对象        if isinstance(x,LTImage):            print('这里获取到一张图片')        # 获取 figure 对象        if isinstance(x,LTFigure):            print('这里获取到一个 figure 对象')


OK,这次我们把 pdf 文件加载到内存后,循环加载到每个页面对象,并遍历各个对象,使用 isinstance 方法判断对象的类型,将文本对象时直接打印出来,当为其他对象时打印一个字符串,返回结果如下图:


image.png


可以看出 PDFMiner 对文本的解析还是不错的,不过对图片的解析,正如官方文档所说,识别并不是很准确,这里将图片识别为了 figure 对象。另外对于表格的支持也不够好,虽然能读取出来表格内容,但完全看不出表格的样式来,后期还需要进一步处理。


总结


本文为大家介绍了 Python 中如何解析 PDF 文档,由于 PDF 并没有规范的格式,解析起来会比较复杂。当然除了 PDFMiner ,还有很多处理 pdf 的工具,各有优缺点,今天算是带大家入个门,就以 PDFMiner 为例做了一个简单介绍,如果想了解更多请参考文末官网介绍。


参考

python-pdfminer 官网:https://euske.github.io/pdfminer/

Python PDF Parser:https://github.com/euske/pdfminer

目录
相关文章
|
23天前
|
算法 Python
Python 大神修炼手册:图的深度优先&广度优先遍历,深入骨髓的解析
在 Python 编程中,掌握图的深度优先遍历(DFS)和广度优先遍历(BFS)是进阶的关键。这两种算法不仅理论重要,还能解决实际问题。本文介绍了图的基本概念、邻接表表示方法,并给出了 DFS 和 BFS 的 Python 实现代码示例,帮助读者深入理解并应用这些算法。
31 2
|
1月前
|
测试技术 开发者 Python
深入浅出:Python中的装饰器解析与应用###
【10月更文挑战第22天】 本文将带你走进Python装饰器的世界,揭示其背后的魔法。我们将一起探索装饰器的定义、工作原理、常见用法以及如何自定义装饰器,让你的代码更加简洁高效。无论你是Python新手还是有一定经验的开发者,相信这篇文章都能为你带来新的启发和收获。 ###
21 1
|
1月前
|
设计模式 测试技术 开发者
Python中的装饰器深度解析
【10月更文挑战第24天】在Python的世界中,装饰器是那些能够为函数或类“添彩”的魔法工具。本文将带你深入理解装饰器的概念、工作原理以及如何自定义装饰器,让你的代码更加优雅和高效。
|
2月前
|
XML 前端开发 数据格式
Beautiful Soup 解析html | python小知识
在数据驱动的时代,网页数据是非常宝贵的资源。很多时候我们需要从网页上提取数据,进行分析和处理。Beautiful Soup 是一个非常流行的 Python 库,可以帮助我们轻松地解析和提取网页中的数据。本文将详细介绍 Beautiful Soup 的基础知识和常用操作,帮助初学者快速入门和精通这一强大的工具。【10月更文挑战第11天】
64 2
|
2月前
|
数据安全/隐私保护 流计算 开发者
python知识点100篇系列(18)-解析m3u8文件的下载视频
【10月更文挑战第6天】m3u8是苹果公司推出的一种视频播放标准,采用UTF-8编码,主要用于记录视频的网络地址。HLS(Http Live Streaming)是苹果公司提出的一种基于HTTP的流媒体传输协议,通过m3u8索引文件按序访问ts文件,实现音视频播放。本文介绍了如何通过浏览器找到m3u8文件,解析m3u8文件获取ts文件地址,下载ts文件并解密(如有必要),最后使用ffmpeg合并ts文件为mp4文件。
|
2月前
|
Web App开发 SQL 数据库
使用 Python 解析火狐浏览器的 SQLite3 数据库
本文介绍如何使用 Python 解析火狐浏览器的 SQLite3 数据库,包括书签、历史记录和下载记录等。通过安装 Python 和 SQLite3,定位火狐数据库文件路径,编写 Python 脚本连接数据库并执行 SQL 查询,最终输出最近访问的网站历史记录。
34 4
|
2月前
|
机器学习/深度学习 算法 Python
深度解析机器学习中过拟合与欠拟合现象:理解模型偏差背后的原因及其解决方案,附带Python示例代码助你轻松掌握平衡技巧
【10月更文挑战第10天】机器学习模型旨在从数据中学习规律并预测新数据。训练过程中常遇过拟合和欠拟合问题。过拟合指模型在训练集上表现优异但泛化能力差,欠拟合则指模型未能充分学习数据规律,两者均影响模型效果。解决方法包括正则化、增加训练数据和特征选择等。示例代码展示了如何使用Python和Scikit-learn进行线性回归建模,并观察不同情况下的表现。
349 3
|
6月前
|
XML JavaScript 关系型数据库
Python XML 解析
Python XML 解析
|
7月前
|
XML JavaScript API
Python XML 解析
Python XML 解析
|
XML JavaScript 关系型数据库