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

这篇具有很好参考价值的文章主要介绍了Python:PDF文件处理(数据处理)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

  1. PDF文件分割、拼接;

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

  1. PDF文件抽取表格;

  1. PDF文件抽取文本;

  1. PDF文件转docx文件;

  1. docx文件数据抽取;

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

Python版本:Python3.8

一、PDF文件分割、拼接

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

import os
from PyPDF2 import PdfFileWriter, PdfFileReader


def 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文件抽取图片,简单的图片识别

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

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

  1. 文字识别

import fitz
import re
import os


def 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 PaddleOCR
import 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文件抽取表格、文本

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

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

(一)、pdfplumber

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

优点:

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

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

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

缺点:

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

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

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

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

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

简单使用:

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

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

(二)、tablua

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

优点:

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

②不会换行数据干扰;

③可以指定页读取

缺点:

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

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

import tablua


def 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 tables


pdf_file = 'xxxx.pdf'
tables = get_tabula_tables(pdf_path)

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

(三)、Camelot

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

import camelot


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

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

总结-解析PDF文件

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

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

四、PDF文件转docx

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

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

(一)、pdf2docx

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

from pdf2docx import Converter
import logging


logging.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 aw

pdf_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提取出来的表格数据无法使用。

五、docx文件数据抽取

直接上代码

from docx import Document


def 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 result


def 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 lines

docx_file = 'xxx.docx'
doc = Document(docx_file)
tables = get_doc_tables(dox)
paragraphs = doc.paragraphs
lines = get_doc_lines(paragraphs)

优点:

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

  1. 读取的表格数据可以反向推导出表格结构(上下左右合并相同值,我是将list数据转成了<table>包含的字符串)。

缺点:

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

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

总结

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

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

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

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

流程:

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

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

以上就是所有的内容,希望对你有帮助~文章来源地址https://www.toymoban.com/news/detail-491927.html

到了这里,关于Python:PDF文件处理(数据处理)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端处理后端返回的数据中有\n\n字样的换行符标识

    后端返回的数据: 上面圈着的部分就是n,前端需要将数据进行换行,对于这类型的数据,在前端页面是需要进行稍微处理才能正常显示。如果没有经过处理,那么内容是不会在有换行符的位置进行换行显示的 解决办法1: 使用css属性: pre-wrap:连续的空白符会被保留。在遇到

    2024年02月07日
    浏览(38)
  • Python处理xlsx文件(读取、转为列表、新建、写入数据、保存)

    xlsxwriter**库对于xslx表的列数不做限制, xlrd 库不能写入超过65535行,256列的数据。 由于需要处理的数据行列数较多,遇到报错才发现库的限制问题,记录一下。

    2024年02月12日
    浏览(70)
  • Python处理大数据——csv文件类型的小技巧

    当我们遇到一个超大的csv数据文件的时候,双击打开是不现实的。即使打开csv,只能看到104万行的数据,后面都是隐藏的,所以打开也是没有意义的。如果不打开,又无法查看到表的数据结构,就无法进行下一步的工作,比如数据筛选。 一、大数据处理工具 对于超百万行,

    2024年03月14日
    浏览(58)
  • Python小白入门:文件、异常处理和json格式存储数据

    所用资料 代码中所用到的文件可以从下面的网站进行下载: https://www.ituring.com.cn/book/2784 open函数 打开 一个文件。 接收参数为需要打开的文件名 。Python会在 当前执行的文件所在目录下 查找指定文件,因此需要把pi_digits.txt文件放在执行文件的同目录下。 open函数返回一个表示

    2024年02月13日
    浏览(52)
  • Python用pandas进行大数据Excel两文件比对去重300w大数据处理

    Python用pandas进行大数据Excel两文件比对去重 通俗理解有两个excel文件 分别为A和B 我要从B中去掉A中含有的数据, 数据量大约在300w左右 因为数据量较大,无论是wps还是office自带的去重都无法正常使用这样就需要用到脚本了  欢迎大家指导交流,共同学习,共同进步!

    2024年02月15日
    浏览(68)
  • python实现视频抽帧,文件批量操作,文件批量处理(数据集制作的工具箱)

    环境准备 数据集制作 文件批量重命名 文件批量移动 将文件批量按照一定格式进行重命名 修改xml文件内容的方法 Pathlib库的常用接口 在计算机视觉项目中,文件批量操作和文件批量预处理是必不可少的步骤。它们涉及处理大量的图像文件,包括读取、处理、保存和预处理。

    2024年02月09日
    浏览(72)
  • Python两种读取txt与csv文件方式(利用numpy处理数据)

    一共80个数据(只截取前10个数据) 在excel中显示的内容 在pycharm中显示的内容 一共80个数据 在记事本中显示的内容 在pycharm中显示的内容 1、读取所有内容 data_pd打印结果 2、数据转为numpy data_np打印结果 1、读取所有内容 data_pd打印结果 2、数据转为numpy data_np打印结果 1、读取所

    2023年04月11日
    浏览(59)
  • Python中数据处理(npz、npy、csv文件;元组、列表、numpy数组的使用)

    目录 1.npz文件 2.npy文件 3.csv文件 4.列表、元组、numpy矩阵 ①列表 ②元组(不可变列表) ③Numpy数组 ③Numpy矩阵 1.npz文件 npz是python的压缩文件 ①读取文件 ② NpzFile 对象有个属性 files 可以通过它查看该压缩文件的所有文件名,通过 dataset[\\\'文件名\\\'] 来获取文件内容 ③保存为.npz文件

    2024年02月03日
    浏览(47)
  • 【工作笔记】Springboot一个比较通用的数据脱敏处理办法

            个人信息中的手机号、邮箱等属于敏感数据,其中手机号需要加密存储,邮箱可以直接存储但是在获取和展示时要做脱敏处理;         针对此类敏感数据, 介绍一种比较通用的脱敏方法。         1. 定义DataMask注解                  2. 定义DataMaskOperation接

    2024年02月03日
    浏览(41)
  • 【头歌】——数据分析与实践-基于Python语言的文件与文件夹管理-文本 文件处理-利用csv模块进行csv文件的读写操作

    第1关 创建子文件夹 第2关 删除带有只读属性的文件 第3关 批量复制文件夹中的所有文件 未通过本题,如果您通过了本题欢迎补充到评论区,有时间我会整理进来 第1关 读取宋词文件,根据词人建立多个文件 第2关 读取宋词文件,并根据词人建立多个文件夹 第3关 读取宋词文

    2024年01月25日
    浏览(73)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包