python 搜索pdf文件中的文字_利用Python在pdf文档中寻找某些词出现的页码

要研究pdf文件的页码,首先要考虑这个文件的种类。pdf可能是一本书的电子版,可能是一份简历、可能是由Word、PPT或其他文档导出的……如果不是一本书,通常页面内容里是没有页码的;如果是一本书,虽然有页码,但是封面、前言、目录、章节的封面很可能不会标上页码,而正文的页码和该pdf文件本身的页码对不上,如页面里的第1页会是pdf的第5页,页面的第2页是pdf的第6页……为了统一,我将页码“定义”为pdf的文件的页码。

下面来试试如何通过Python找到词汇出现过的页码,首先我使用的是PyPDF2这个库,这个库使用起来非常简单,但是只能提取pdf中的文本信息,是可以用来寻找词汇的。我首先利用一篇英文文献试了一下:

1 importPyPDF22

3 pdf_File=open('C:\\Users\\user\\Desktop\\2016.pdf','rb')4 pdf_Obj=PyPDF2.PdfFileReader(pdf_File)5 pages=pdf_Obj.getNumPages()6

7 word_list=['predictedvalues','warfarin','NONMEM','atrialfibrillation','results']8

9 for w inword_list:10 page_list=[]11 for p inrange(0,pages):12 text=pdf_Obj.getPage(p).extractText()13 if w intext:14 page_list.append(p+1)15

16 print(w,page_list)

我要寻找的词汇是:predictive values, warfarin, NONMEM, atrial fibrillation, results,由于PyPDF2处理文本时,所有的空格都会消失,所以“predictive values”和“atrial fibrillation”写成了“predictivevalues”和“atrialfibrillation”。输出的结果如下:

1724317-20190727135045671-865191368.png

可以发现,已经打印出了这些词汇出的页码。然而当我在一份中文pdf上再次应用时,却失败了。我首先想到是编码的问题,于是在第一行加上:

encoding=utf-8

去发现无济于事,那么会不会是这个库并不支持中文文本的提取呢?我在翻了一下这个项目的地址,发现早在2016年,已经有人发现了这个问题:

1724317-20190727135704625-724605764.png

1724317-20190727135839438-2110381407.png

可惜的是这个问题到现在还是没有解决,所以PyPDF2这个库无法解决问题,只能另想办法了。

于是我尝试了另外一个库pdfminer,它比PyPDF2使用起来要复杂地多,不过相应地功能也更加强大,不仅可以提取文本,也可以提取图片、表格等,并且支持中文。但是这个库是为Python2打造的,万幸它有支持Python3的版本pdfminer.six,下面就开始干活吧。

首先导入要使用的模块:

1 from pdfminer.pdfparser importPDFParser,PDFDocument2 from pdfminer.pdfinterp importPDFResourceManager,PDFPageInterpreter3 from pdfminer.converter importPDFPageAggregator4 from pdfminer.layout importLTTextBoxHorizontal,LAParams5 from pdfminer.pdfinterp import PDFTextExtractionNotAllowed

在这一步我出错了好久,最后重启了IDE才顺利导入。

模块导入之后就是提取文本了。这一部分的代码我主要是借鉴了别人的,自己根据需求做了一些改动:

1 defparsePDFtoTXT(pdf_path):2 fp = open(pdf_path, 'rb')3 #创建一个pdf文档分析器

4 parser =PDFParser(fp)5 #创建一个PDF文档对象存储文档结构

6 document=PDFDocument()7 #连接分析器与文档对象

8 parser.set_document(document)9 document.set_parser(parser)10 #提供初始化密码

11 document.initialize()12 #检查文件是否允许文本提取

13 if notdocument.is_extractable:14 raisePDFTextExtractionNotAllowed15 else:16 #创建一个PDF资源管理器对象来存储共赏资源

17 rsrcmgr=PDFResourceManager()18 #设定参数进行分析

19 laparams=LAParams()20 #创建一个PDF设备对象

21 device=PDFPageAggregator(rsrcmgr,laparams=laparams)22 #创建一个PDF解释器对象

23 interpreter=PDFPageInterpreter(rsrcmgr,device)24 #处理每一页

25 for page indocument.get_pages():26 #解析页面

27 interpreter.process_page(page)28 #接受该页面的LTPage对象

29 layout=device.get_result()30 print(layout)31 output=str(layout)32 for x inlayout:33 if(isinstance(x,LTTextBoxHorizontal)):34 text=x.get_text()35 output+=text36 with open('C:\\Users\\user\\Desktop\\pdfoutput.txt','a',encoding='utf-8') as f:37 f.write(output)

这段代码功能的是提取目标pdf中的文本,将其保存为桌面的pdfoutout.txt这个文件。这一步对于提取文本来说没有问题,但是这样一来,所有关于页码的信息就荡然无存了。document.get_pages()是一个生成器(generator)对象,在解析页面时,对它进行遍历,从而一页一页地进行处理,解析的结果(包括文本、图片、表格等)存储在layout中,它是LTPage类型的对象,每一个页面都对应了一个layout。我们需要文本信息,就要判断其中的内容是否为横向文本框(LTTextBoxHorizontal),如果是,则获取其文本。不幸的是,我们虽然可以一页一页地解析页面,但是却无法一页一页输出解析的结果,换句话说,输出的txt文件失去了页面信息,无法用来获得词汇所出现的页面了。

我想到了一个解决办法。虽然无法逐页输出结果,但是我们可以逐页解析结果,那么在解析结果时,能否“留一手”,把页面信息也加上去呢?于是我加上第31行和第35行,在每页的结果前面加上“”,i代表第i页,这样在所输出的文本里,就有了用于区分页码的依据。第30行的代码没有什么实际的作用,我写上去是为了充当进度条,每处理完一页就会打印一行,在pdf页数比较多时可以知道进行到哪一页了。

得到了带有页码信息的文本之后,就是查询目标词汇以及返回它所出现的页码了:

1 defget_word_page(word_list):2 f=open('C:\\Users\\user\\Desktop\\pdfoutput.txt',encoding='utf-8')3 text_list=f.read().split('

我的处理方法是根据每页前的“”把全部的文本进行切分,它们的每一部分都被作为元素存储于1个列表中。pdf有n页,列表中就会有n+1个元素(索引为0到n),其中第0个元素是我们不需要的,剩下的n个元素,其索引i就代表pdf的第i页。判断词汇是否存在于文本时,我用的是最简单的方法,这种方法无法区分大小,如“happy”、“Happy”、“HAPPY”,它们虽然大小写不一致,但实际上是同一个词,上述代码就无法通过“happy”找到后2个词,可以考虑利用正则表达式进行匹配来解决这个问题。最终的结果保存在桌面的result.txt文件中。

下面用一篇中文文献来试验一下,完整的代码如下:

1 #-*- coding: utf-8 -*-

2

3 from pdfminer.pdfparser importPDFParser,PDFDocument4 from pdfminer.pdfinterp importPDFResourceManager,PDFPageInterpreter5 from pdfminer.converter importPDFPageAggregator6 from pdfminer.layout importLTTextBoxHorizontal,LAParams7 from pdfminer.pdfinterp importPDFTextExtractionNotAllowed8

9 defparsePDFtoTXT(pdf_path):10 fp = open(pdf_path, 'rb')11 parser =PDFParser(fp)12 document=PDFDocument()13 parser.set_document(document)14 document.set_parser(parser)15 document.initialize()16 if notdocument.is_extractable:17 raisePDFTextExtractionNotAllowed18 else:19 rsrcmgr=PDFResourceManager()20 laparams=LAParams()21 device=PDFPageAggregator(rsrcmgr,laparams=laparams)22 interpreter=PDFPageInterpreter(rsrcmgr,device)23 for page indocument.get_pages():24 interpreter.process_page(page)25 layout=device.get_result()26 print(layout)27 output=str(layout)28 for x inlayout:29 if(isinstance(x,LTTextBoxHorizontal)):30 text=x.get_text()31 output+=text32 with open('C:\\Users\\user\\Desktop\\pdfoutput.txt','a',encoding='utf-8') as f:33 f.write(output)34

35 defget_word_page(word_list):36 f=open('C:\\Users\\user\\Desktop\\pdfoutput.txt',encoding='utf-8')37 text_list=f.read().split('

47 if __name__=='__main__':48 parsePDFtoTXT('C:\\Users\\user\\Desktop\\群体药动学原理建立卡马西平和丙戊酸的定时定量给药模型及临床应用_林玮玮.pdf')49 get_word_page(['群体药动学','服药时间','知情同意书','NONMEM','贝叶斯反馈'])

运行后生成的pdfoutput.txt的内容如下:

1724317-20190727155331948-1502783911.png

结果文件result.txt如下:

1724317-20190727155523857-1951685014.png

可以看到已经得到了目标词汇所出现过的页码。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值