数据分析入门——python提取PDF文本内容

说真的,从PDF里面搜索关键字并提取上下文真的是个噩梦,PDF是个面向打印的文档格式,从里面抓数据太痛苦了,搞了一天已经想吐了。不过我还是沉淀了一点点东西。

python解析PDF文档大致有以下几个库:

  • PDFMiner
  • pdfplumer
  • ta

我们主要是提取文本内容,所以推荐使用pdfminer。

安装

默认使用python3.7的环境, 如果是2.7的请酌情处理。

pip install pdfminer
pip install pdfminer3k
pip install pdfminer.six

可能会用到的的相关类:

  • PDFParser: 从一个文件中获取数据。
  • PDFDocument: 保存获取的数据,和PDFParser是相互关联的。
  • PDFPageInterpreter: 处理页面内容。
  • PDFDevice: 将其翻译成你需要的格式。
  • PDFResourceManager: 用于存储共享资源,如字体或图像。

准备

这里有一个很重要的关于PDF文档结构的知识,有助于你用代码筛选出你想要的东西:


LTPage :表示整个页。可能会含有LTTextBox,LTFigure,LTImage,LTRect,LTCurve和LTLine子对象。
LTTextBox:表示一组文本块可能包含在一个矩形区域。注意此box是由几何分析中创建,并且不一定表示该文本的一个逻辑边界。它包含LTTextLine对象的列表。使用 get_text()方法返回文本内容。
LTTextLine :包含表示单个文本行LTChar对象的列表。字符对齐要么水平或垂直,取决于文本的写入模式。使用get_text()方法返回文本内容。
LTAnno:在文本中字母实际上被表示为Unicode字符串。需要注意的是,虽然一个LTChar对象具有实际边界,LTAnno对象没有,因为这些是“虚拟”的字符,根据两个字符间的关系(例如,一个空格)由布局分析后插入。
LTImage:表示一个图像对象。嵌入式图像可以是JPEG或其它格式,但是目前PDFMiner没有放置太多精力在图形对象。
LTLine:代表一条直线。可用于分离文本或附图。
LTRect:表示矩形。可用于框架的另一图片或数字。
LTCurve:表示一个通用的Bezier曲线
————————————————
版权声明:本文为CSDN博主「周小董」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xc_zhou/java/article/details/81009809

开始发车

真的想吐,本来想好好写一下的,现在完全没心情,直接上代码吧。这个是我封装的一个单独的文件:

from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LAParams, LTTextBox, LTTextBoxHorizontal
from pdfminer.pdfpage import PDFTextExtractionNotAllowed
from pdfminer.pdfpage import PDFPage
import glob


def get_file_list(root=".", file_suffix="*") -> list:
    """

    获取指定目录和指定文件类型的文件列表。

    :param root: 默认为当前目录
    :param file_suffix: 文件名后缀,默认为*
    :return: 返回指定目录和指定文件类型的list
    """
    l = glob.glob("{}/*.".format(root) + file_suffix)
    return l


# 将一个pdf转换成dict
def pdf_to_txt(file_path: str):
    """
    可以搜索指定PDF文件中含关键词的段落内容
    :param file_path: PDF文档路径
    :param key_words: 搜索的关键词
    :return: Dict格式的搜索结果
    """
    # try:
    rs = {}
    my_pdf = open(file_path, 'rb')
    print("File:", file_path)
    # 创建一个文档解析器
    par = PDFParser(my_pdf)
    # 创建一个PDF文档对象存储文档结构
    my_doc = PDFDocument(par)
    # 判断文件是否允许文本提取
    if not my_doc.is_extractable:
        raise PDFTextExtractionNotAllowed
    else:
        # 创建一个PDF资源管理器对象用来存储资源
        res = PDFResourceManager()
        # 设定参数进行分析
        la = LAParams()
        # 创建一个PDF设备对象
        dev = PDFPageAggregator(res, laparams=la)
        # 创建一个PDF解释器对象
        my_interpreter = PDFPageInterpreter(res, dev)
        # return PDFPage.create_pages(my_doc)
        # 按页开始处理
        for pg in PDFPage.create_pages(my_doc):
            my_interpreter.process_page(pg)
            lt_dict = {}
            rs[pg.pageid] = lt_dict
            print("Page ID:", pg.pageid)
            # 接收改页面的LTPage对象
            lt = dev.get_result()
            for l in lt:
                if isinstance(l, LTTextBox):
                    # splitlines方法用来处理 \n 换行符
                    lt_dict[l.index] = l.get_text().splitlines()

    return rs


# 从上面转换出来的字典中搜索关键字并返回它所在的LTTextBox内容以及下一个LTTextBox的内容,别问我为什么,我想吐~~
def search_keywords(the_dict: dict, keywords: str):
    """
    在指定的PDF转成的dict中搜索关键词,并返回其上下文

    :param the_dict: 必须是用本文件中的pdf_to_txt方法返回的字典才可以
    :param keywords: 要搜索的关键字
    :return: dict形式返回搜索结果
    """
    s = {}

    for key, value in the_dict.items():
        # print("koala", key, value)
        if keywords in value:
            s[key - 1] = the_dict[key - 1]
            s[key] = value
            s[key + 1] = the_dict[key + 1]
            print("Bingo!", key, value)
    if len(s) > 0:
        rs = {keywords: s}
        return rs

注释写的非常详细了,虽然折腾了快一天,试来试去,但最后剩下的代码还是比较精简的,踩了不少坑。

以下是一个demo,演示如何调用上面封装好的方法:

fl = pdfTools.get_file_list(file_suffix="pdf")

key_words = "我是关键字"

s = {fl[0]: pdfTools.pdf_to_txt(fl[0])}

aa =[]

for key, value in s[fl[0]].items():
    aa.append(pdfTools.search_keywords(value, key_words))

我不喜欢输入到控制台或者文件,因为用pyCharm,可以直接看到Jupyter Server上的变量值。

从PDF里面找东西真的真的太痛苦了,要是有高手有更好的方法求指教,谢了谢了!

有心情的时候也许我会再完善一下这篇文章吧,今天就这样了,我去吐会儿~~~~~

再次声明一下,本文参考了此篇文章部分内容:[312]python提取pdf文本内容,不要来找我麻烦,我没工夫应付。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容

  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 9,182评论 0 3
  • 原谅把你带走的雨天,在渐渐模糊的窗前。每个人最后都要说,再见。 再遇见,见抑或不见? •第一章• 柯健第一次遇见萧...
    梦1212阅读 460评论 0 2
  • 谦谦君子,窈窕淑女,人皆好之。每个人心中可能都有自己理想的朋友,家人,另一半的模样,但如果发现她不是你理想的...
    不妖陌诺阅读 420评论 10 9