Python使用pdfminer解析PDF

因为爬虫爬到的字段不是很全,需要去解析PDF来获取一部分字段,于是就有了这篇博客

一.环境配置

因为之前的工程是在py2的基础上,本次打算使用py3,于是自己先把py3的环境配置好,个人比较喜欢anaconda,因为内置了很多需要的第三方包,在装一些其他包的时候难免会用到一些依赖包,而anaconda中恰好自带了一部分。(win,mac,linux都有,需要的自行下载安装),安装anaconda3时间比较长,如果急着用,直接安装python3即可。

把需要的python3环境配置好,然后就可以安装pdfminer这个模块了

注意:python2中是pdfminer ,python3中是pdfminer3k

pip install pdfminer3k

二.pdfminer分析

附上pdfminer的文档

解析PDF是一件非常耗时和内存的工作,因此PDFMiner使用了一种称作lazy parsing的策略,只在需要的时候才去解析,以减少时间和内存的使用。要解析PDF至少需要两个类:PDFParser 和 PDFDocument,PDFParser 从文件中提取数据,PDFDocument保存数据。另外还需要PDFPageInterpreter去处理页面内容,PDFDevice将其转换为我们所需要的。PDFResourceManager用于保存共享内容例如字体或图片。

比较重要的是Layout,主要包括以下这些组件:

LTPage

Represents an entire page. May contain child objects like LTTextBox, LTFigure, LTImage, LTRect, LTCurve and LTLine.

 

三.代码实现


import urllib
import importlib,sys
importlib.reload(sys)
from pdfminer.pdfparser import PDFParser, PDFDocument
from pdfminer.pdfdevice import PDFDevice
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LTTextBoxHorizontal, LAParams
from pdfminer.pdfinterp import PDFTextExtractionNotAllowed


def parse(DataIO, save_path):

    #用文件对象创建一个PDF文档分析器
    parser = PDFParser(DataIO)
    #创建一个PDF文档
    doc = PDFDocument()
    #分析器和文档相互连接
    parser.set_document(doc)
    doc.set_parser(parser)
    #提供初始化密码,没有默认为空
    doc.initialize()
    #检查文档是否可以转成TXT,如果不可以就忽略
    if not doc.is_extractable:
        raise PDFTextExtractionNotAllowed
    else:
        #创建PDF资源管理器,来管理共享资源
        rsrcmagr = PDFResourceManager()
        #创建一个PDF设备对象
        laparams = LAParams()
        #将资源管理器和设备对象聚合
        device = PDFPageAggregator(rsrcmagr, laparams=laparams)
        #创建一个PDF解释器对象
        interpreter = PDFPageInterpreter(rsrcmagr, device)

        #循环遍历列表,每次处理一个page内容
        #doc.get_pages()获取page列表
        for page in doc.get_pages():
            interpreter.process_page(page)
            #接收该页面的LTPage对象
            layout = device.get_result()
            #这里的layout是一个LTPage对象 里面存放着page解析出来的各种对象
            #一般包括LTTextBox,LTFigure,LTImage,LTTextBoxHorizontal等等一些对像
            #想要获取文本就得获取对象的text属性
            for x in layout:
                try:
                    if(isinstance(x, LTTextBoxHorizontal)):
                        with open('%s' % (save_path), 'a') as f:
                            result = x.get_text()
                            print (result)
                            f.write(result + "\n")
                except:
                    print("Failed")


if __name__ == '__main__':
    #解析本地PDF文本,保存到本地TXT
    with open(r'E:\parse_pdf\3.pdf','rb') as pdf_html:
        parse(pdf_html, r'E:\parse_pdf\d.txt')

    #解析网络上的PDF,保存文本到本地
    # url = "https:"
    # pdf_html = urllib.urlopen(url).read()
    # DataIO = StringIO(pdf_html)
    # parse_pdf(DataIO, r'E:\parse_pdf')

四.代码分析

PDF不像word,TXT可以随意读取内容,本身读取PDF就是一件比较困难的事,用程序去读取PDF的时候也是以二进制去读取PDF然后在转换成文字。

PDF更像一张图片。PDF更像是在一张纸的各个准确的位置上把内容都摆放出来。大部分情况下,没有逻辑结构,比如句子或段落,并且不能自适应页面大小的调整。PDFMiner尝试通过猜测它们的布局来重建它们的结构,但是不保证一定能工作。

  我们把流程图分解来看:

解析PDF的时候有两个核心方法:PDFParse和PDFDocument,他们两个结合使用就可以解析PDF

PDFParser     从文件中获取数据

PDFDocument   存储文档数据结构到内存中

PDFPageInterpreter 解析page内容

PDFDevice    把解析到的内容转化为你需要的东西

PDFResourceManager存储共享资源,例如字体或图片

1.打开本地或者网络PDF

    #解析本地PDF文本,保存到本地TXT
    with open(r'E:\parse_pdf\3.pdf','rb') as pdf_html:
        parse(pdf_html, r'E:\parse_pdf\d.txt')

    #解析网络上的PDF,保存文本到本地
    # url = "https://"
    # pdf_html = urllib2.urlopen(url).read()
    # parse_pdf(pdf_html, r'E:\parse_pdf')

2.建立文档分析器并关联文档

    #用文件对象创建一个PDF文档分析器
    parser = PDFParser(DataIO)
    #创建一个PDF文档
    doc = PDFDocument()
    #分析器和文档相互连接
    parser.set_document(doc)
    doc.set_parser(parser)

 

3.文档密码初始化

    #提供初始化密码,没有默认为空
    doc.initialize()

4.创建解释器

先创建一个资源管理器和参数分析器

 #创建PDF资源管理器,来管理共享资源
        rsrcmagr = PDFResourceManager()
        #创建一个PDF参数对象
        laparams = LAParams()

 创建一个聚合器,接收资源管理器和参数

创建一个解释器,接收资源管理器和聚合器

 #将资源管理器和设备对象聚合
        device = PDFPageAggregator(rsrcmagr, laparams=laparams)
        #创建一个PDF解释器对象
        interpreter = PDFPageInterpreter(rsrcmagr, device)

这样 页面解释器 就具有对PDF文档进行编码,解释成Python能够识别的格式

5.文本获取

使用doc.get_pages()获得所有的所有页面,然后去遍历每一页,然后使用interperter页面解释器对页面进行逐一聚合,然后调用聚合器的get_result()获取到layout,layout中的每一个内容,只有事文本的才能被提出来,写到TXT中。

        for page in doc.get_pages():
            interpreter.process_page(page)
            #接收该页面的LTPage对象
            layout = device.get_result()
            #这里的layout是一个LTPage对象 里面存放着page解析出来的各种对象
            #一般包括LTTextBox,LTFigure,LTImage,LTTextBoxHorizontal等等一些对像
            #想要获取文本就得获取对象的text属性
            for x in layout:
                try:
                    if(isinstance(x, LTTextBoxHorizontal)):
                        with open('%s' % (save_path), 'a') as f:
                            result = x.get_text()
                            print (result)
                            f.write(result + "\n")
                except:
                    print("Failed")

五.结果分析

如果PDF中只含有文本,那么可以完全解析出来,如果含有图片,没有办法获取到,因为pdfminer只是获取PDF中的文本。如果这个PDF本身就不能提取文本那么会在

if not doc.is_extractable:
    raise PDFTextExtractionNotAllowed
就抛出异常,我在测试的带有水印PDF时就会抛出异常,所以这个非常有局限性,可以结合OCR使用,因为涉及到公司代码就没有把OCR部分贴出来。
  • 24
    点赞
  • 152
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值