我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python:PDF文件处理(数据处理)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python:PDF文件处理(数据处理)

工作中有对PDF文件进行数据抽取,现在总结归纳一下相应的方法,本文包括一下内容:

  1. PDF文件分割、拼接;

  1. PDF文件抽取图片,简单的图片识别;

  1. PDF文件抽取表格;

  1. PDF文件抽取文本;

  1. PDF文件转docx文件;

  1. docx文件数据抽取;

目的:尽可能的将pdf中的数据,抽取出来,尤其是文本和表格数据尽可能的精准。

Python版本:Python3.8

使用场景:什么时候会用到这个功能呢?比如你爬取了一堆的PDF文件,但是这些PDF文件中存在一些干扰页,比如广告页。这种情况下,你就需要对PDF文件进行分割、拼接,在本文中,将会为大家演示这个方式的另外一个用途。

import osfrom PyPDF2 import PdfFileWriter, PdfFileReaderdef clear_dir(dir_path):    """清空目录下的文件"""    names = os.listdir(dir_path)    for name in names:        file_path = os.path.join(dir_path, name)        cmd = 'del %s' % file_path    #这个是windows命令        #cmd = 'rm -rf %s' % file_path  #这个是Linux的命令        cmd = cmd.replace('/', '\\')  #为啥要这个?因为windows命令不支持/所以需要替换,Linux命令没有遇见这个问题;        os.system(cmd)  #可以通过返回值来判断是否执行成功:0成功,其他失败def split_pdf(pdf, output_dir):    """pdf按每页拆分"""    clear_dir(output_path)    # 获取 PdfFileReader 对象    reader = PdfFileReader(pdf_file)    pages_num = reader.getNumPages()    # writer = PdfFileWriter() 生成一个文件    for index in range(pages_num):        #可以通过对index判断分割想要的        writer = PdfFileWriter()  #按照每页来分割pdf        pageObj = reader.getPage(index)        writer.addPage(pageObj)        # 添加完每页,再一起保存至文件中;如果要输出一个文件,后面这些放置到循环外即可        file_name = os.path.join(output_path, str(index) + '.pdf')        with open(file_name, 'wb') as fw:            writer.write(fw)

我对机器学习了解不多,补充这个也是由于在开发中有这么一个需求。使用场景,需要批量的PDF文件重命名,命名中需要包含发布的机构,这个机构的名称可以在首页获取,但是是一个logo。观察发现,logo中包含了机构名称,所以只需要对logo识别中文即可:

  1. 抽取图片:网络上找的代码(太多出处了,懒的写来源了),由于使用的版本不一致,部分代码有微调,这个也是我比较吐槽的地方,测试了半天。

  1. 文字识别

import fitzimport reimport osdef save_pdf_img(path, save_path):    '''    path: pdf的路径    save_path : 图片存储的路径    '''    # 使用正则表达式来查找图片    checkXO = r"/Type(?= */XObject)"    checkIM = r"/Subtype(?= */Image)"    # 打开pdf    doc = fitz.open(path)    # 图片计数    imgcount = 0    # 获取对象数量长度    lenXREF = doc.xref_length()    # 遍历每一个图片对象    for i in range(1, lenXREF):        # 定义对象字符串        text = doc.xref_object(i)        #         print(i,text)        isXObject = re.search(checkXO, text)        # 使用正则表达式查看是否是图片        isImage = re.search(checkIM, text)        # 如果不是对象也不是图片,则continue        if not isXObject or not isImage:            continue        imgcount += 1        # 根据索引生成图像        pix = fitz.Pixmap(doc, i)        # 根据pdf的路径生成图片的名称        new_name = "img{}.png".format(imgcount)        new_name = os.path.join(save_path, new_name)        pix.save(new_name)        # 释放资源        pix = None

第三方包:paddleocr,安装教程网上都有,自己搜索即可

from paddleocr import PaddleOCRimport logging#将一些日志信息过滤掉logging.disable(logging.DEBUG)logging.disable(logging.WARNING)ocr = PaddleOCR(use_angle_cls=True, lang='ch')result = ocr.ocr(img_path, cls=True)if len(result) != 1:    print('result num=', len(result))    exit()result = result[0]lines = []#可以直接答应result看看都是些什么结构for line in result:    lines.append(line[1][0])#这就是识别出来的文本print(lines)

效果:对于正规的的字体识别还是很好的,包括繁体,可能是logo图中的文本比较简单的原因,没有深究,文本识别技术还未深入学习,不发表言论。

PDF文件的数据组成:主要是文本、图片、表格,这三部分组成,但是也会穿插流程图、各种柱状图等。

Python可以抽取的PDF表格、文本数据的第三方包:pdfplumber,tabula,camelot

(一)、pdfplumber

1、pdfplumber:可以说是目前所有包中做的最好的一个包。

优点:

①每页单独对象,支持文本、表格数据的抽取(亮点);

②文本抽取:保留了文本的格式,比如换行位置有空格,可以通过这个特点将一段的文本整合;

③表格数据抽取:不会被换行数据所干扰;

缺点:

①文本抽取:如果这页有表格数据,抽取到的文本数据中会包含表格数据(也可能是一个优点???)。

②表格数据抽取:对于有合并单元格的表格,无法还原表格结构。

③表格数据抽取:表格数据不能100%保证和原数据一致,可能少那么接个字,可能识别出错等。

④表格数据抽取(缺陷):最主要的还是对无边界的表格,效果很差,会丢失边缘的数据!!!

⑤表格数据抽取:会被流程图、柱状图干扰;

简单使用:

import pdfplumberpdf = r'../data/text.pdf'wookroot = pdfplumber.open(pdf)pages = wookroot.pagesfor page in pages:    text = page.extract_text()    tables = page.extract_tables()    print(text)    print(tables)    breakwookroot.close()

这个包也有一下高级的用法,主要是对表格数据抽取进行参数调节,但是效果嘛,不是很理想。

(二)、tablua

  1. tablua:专门用于抽取PDF文件中表格数据的包

优点:

①抽取出来表格数据可以反向推导出表格的结构(亮点);

②不会换行数据干扰;

③可以指定页读取

缺点:

①无法保证表格数据100%准确;

②对于无边界表格支持不好,丢失数据;

import tabluadef get_tabula_tables(pdf_path):    dfs = tabula.read_pdf(pdf_path, pages='all', encoding='gbk')    tables = []    for df in dfs:        df = df.fillna('')        headers = df.keys().values.tolist()        lt = []        for header in headers:            if header.count('Unnamed'):                lt.append('')                continue            if header[-1].isdigit() and header.count('.'):                words = header.split('.')                line = '.'.join(words[:-1])                if headers.count(line):                    lt.append(line)                    continue            lt.append(header)        headers = lt        values = df.values.tolist()        lt = []        for words in values:            rows = []            for word in words:                if not isinstance(word, str):                    word = str(word)                    if word[-2:] == '.0':                        word = word[:-2]                        rows.append(word)                        continue                rows.append(word)            lt.append(rows)        values = lt        values.insert(0, headers)        tables.append(values)    return tablespdf_file = 'xxxx.pdf'tables = get_tabula_tables(pdf_path)

读取表格中的整数,后面会带有“.0“。

(三)、Camelot

安装包以后,默认的模式无法使用,只能够使用stream来读取。

import camelottables = camelot.read_pdf(pdf_file, flavor="stream")for table in tables:    print(table.df)    print('>>'*50)

流式读取会将整页当做一个表格。

总结-解析PDF文件

文本:最好的包就是pdfplumber,可以获取到完整的文本数据,但是表格文本、流程图文本、图表文本所也会被读取。这个缺点自然是难以拆分,基本没有通用的逻辑可以排除。这个也是优点,如果我们想将表格数据插入到文本中,那么是不是就可以通过这种方式来实现呢?总的来说,还是很复杂,对于同一段落的文本,还需要我们自己去合并,涉及到换页、表格数据干扰、流程图数据干扰以及包本身可能会读取出错,这个工作量是非常的大,想要实现真的是很难(这么过滤表格数据就足以搞崩心态)。

表格:对于有线表格,推荐的pdfplumber;边框线缺失的,基本都会丢失数据。如果你需要重构数据,可以用tablua。值得注意的事,不管那个包,都有可能存在表数据和pdf中表数据不一致的问题(或多、或少、或读错)。

相信大家也看到了,想直接从pdf中解析出文本、表格数据是真的心累。那么我们能够换个思路,从它的前身入手,读取docx文档。docx文件与pdf文件不同之处在于,docx中的数据是标签化的,只要是标签化,我们提取数据基本上就不会出错。

我这里一共有两种方式pdf转docx:pdf2docx+aspose

(一)、pdf2docx

这个包是相信大家都是比较熟悉的,百度中90%都是这个用法。

from pdf2docx import Converterimport logginglogging.disable(logging.INFO)logging.disable(logging.DEBUG)logging.disable(logging.WARNING)pdf_file = 'xxx.pdf'cv = Converter(pdf_file)docx_file = 'xxx.docx'cv.convert(docx_file)cv.close()

优点:1、转换速度快,0.2秒一页;2、无线+有线表格都支持;

缺点:1、纸张方向是横向的表格不支持;2、并不是所有表结构都可以转换(表格边框线的多样性会影响转化的效果)。

(二)aspose

官网:File Format APIs for .NET Core, Java, Python, C++, Android | products.aspose.com

今天主要用里面的aspose.words。aspose.pdf这个也可读取数据,但是效果还没有pdflumber好。

import aspose.words as awpdf_file = 'xxx.pdf'docx_file = 'xxx.docx'pdf = aw.Document(pdf_file)pdf.save(docx_file)

优点:1.无线+有线表格都支持;2、支持横向表格;3、表格数据更加准确。

缺点:

  1. 有两个版本,免费版和付费版:免费版单个文件只能转5页。

  1. 有水印+页眉,转换的words中会有该公司的水印和页眉,这个应该能够解决(没试过)。

  1. 和pdf2docx一样,对于特殊结构的表格,转换会很糟糕。

  1. 某些情况下文本会出现错乱(我也不知为啥,但是用pdf2docx没有问题)。

没有哪个是绝对精准、通用的,但是至少有两种方案来互补。我测试过网上的在线pdf转docx,要么表格数据有缺失,要么就是用ocr来识别、重构的word,这个种word提取出来的表格数据无法使用。

直接上代码

from docx import Documentdef get_doc_tables(doc):    """    获取docx文件中表格,转化成list    :param doc:    :return:    """    result = []    tables = doc.tables    for table in tables:        ret = []        for row_index in range(len(table.rows)):            lt = []            for col_index in range(len(table.row_cells(row_index))):                text = table.cell(row_index, col_index).text                lt.append(text)            ret.append(lt)        result.append(ret)    return resultdef get_doc_lines(paragraphs):    lines = []    for paragraph in paragraphs:        line = paragraph.text.strip()        if not line:            continue        lines.append(line)    # aspose用的体验板,带有页眉    lines = lines[1:]    return linesdocx_file = 'xxx.docx'doc = Document(docx_file)tables = get_doc_tables(dox)paragraphs = doc.paragraphslines = get_doc_lines(paragraphs)

优点:

  1. 同一段落的会整合到一块(也会有部分行不会)。

  1. 读取的表格数据可以反向推导出表格结构(上下左右合并相同值,我是将list数据转成了

    包含的字符串)。

    缺点:

    a.每次读取的数据都是整个文件的数据,不支持单页。

    b.无法定位表格数据在原文中的位置。

    直接解析PDF文件,获取表格数据还行,但是获取文本数据就很难,建议转成docx文件后再处理。

    转docx文件,不是所有的pdf都支持,选取多种方式相互补充更为靠谱,没有那个库适合所有的pdf文件!

    从docx中读取数据,数据都好提取,数据的准确度和转成docx文件的准确的有关,转的不好,数据就有问题。

    表格数据定位问题,我是使用的pdfplumber来完成的,虽然很low,但是也没有找到其他办法。

    流程:

    pdf文件---切割--->单页pdf文件---转换--->docx文件---数据提取--->表格数据+文本数据---表格数据定位--->完整的整页数据--->前端展示

    找到一个介绍PDF文件数据结构的文件:PDF Explained (译作《PDF 解析》) | PDF-Explained (zxyle.github.io)

    以上就是所有的内容,希望对你有帮助~

    来源地址:https://blog.csdn.net/Big_Data_Legend/article/details/129091548

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    Python:PDF文件处理(数据处理)

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    Nodejs处理Json文件并将处理后的数据写入新文件中

    这篇文章主要介绍了Nodejs处理Json文件并将处理后的数据写入新文件中,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-13

    VB.NET文件处理数据的方法

    本篇内容介绍了“VB.NET文件处理数据的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!VB.NET文件处理代码:打开csv文件 Pr
    2023-06-17

    shell 文本数据处理

    文章目录 重定向管道`grep` 模式搜索`sed` 匹配替换`awk` 复杂业务编程(TODO)参考   在 linux shell 中,不同工具、程序间通过文本进行数据交互,即以文本作为输入、输出标准格式。文本成为公共的
    2023-08-24

    如何高效利用 Java 数据流来处理文件?(如何使用java数据流处理文件)

    在Java编程中,处理文件是一项常见且重要的任务。而使用Java数据流可以提供高效、灵活的方式来处理文件。以下是详细的步骤介绍。一、准备工作确保你的Java开发环境已经安装并配置好。你需要有一个集成开发环
    如何高效利用 Java 数据流来处理文件?(如何使用java数据流处理文件)
    Java2024-12-21

    利用pandas轻松处理txt文件数据

    利用pandas轻松处理txt文件数据在数据分析和处理中,常遇到从txt文件读入的数据需要进行处理的情况。比如数据格式混乱,需要清洗;某些列无效,需要删除;某些列需要转换类型等。这些工作可能带来很大的工作量和时间花费,但是我们可以通过pa
    利用pandas轻松处理txt文件数据
    2024-01-19

    python 文件处理

    python经常会操作文件,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是 请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数
    2023-01-31

    Python文件处理

    本文给大家介绍Python文件处理相关知识,具体内容如下所示: 1.文件的常见操作文件是日常编程中常用的操作,通常用于存储数据或应用系统的参数。python提供了os、os.path、shutil等模块处理文件,其中包括最常用的打开文件,读
    2022-06-04

    python 文件处理、数据持久化与正则

    一、文件的处理  数据持久化最简单的类型就是普通文件,有时也叫做平面文件(flat file)。文件是计算机中由OS(操作系统)管理的具有名字的存储区域,在linux系统上,文件被看作是字节序列。fileobj=open(filename,
    2023-01-31

    Torch如何处理文本数据

    Torch是一个用于机器学习和深度学习的开源机器学习库。在处理文本数据时,Torch可以使用其内置的文本处理模块来进行文本预处理和特征提取。以下是Torch处理文本数据的一般步骤:读取文本数据:首先,需要将文本数据加载到Torch中。可以使
    Torch如何处理文本数据
    2024-03-08

    Python中 文件处理

    在文件处理当中,只有read默认是以字符为单位,其他方法均已字节为单位.def open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, c
    2023-01-31

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录