pdf 版面分析与优化策略

news2024/11/27 6:36:24

1. 简介

版面分析作为RAG的第一步工作,其效果对于下游工作至关重要。
在这里插入图片描述

前常见的 PDF 解析方法包括三种

  • 基于规则:根据 PDF 的组织特征确定每个部分的规则(风格和内容)缺点:不通用(PDF格式不固定)
  • 基于深度学习:目标检查和 OCR 结合的流行解决方案
  • 基于多模态大模型:对复杂的结构进行Pasing或提取PDF中的关键信息

1.1 基于规则的pdf解析

代表框架:

  • pdfplumber
  • PyMuPDF
  • pypdf
1.1.1 pdfplumber

pdfplumber 按照每一页处理 pdf,获得 pdf 的页面文字提取表格,最终将 pdf 文件生成对应的 txt 文件。
缺点:按页进行处理有时候一段上下文连续的文字,分散到两页并不好进行处理。

## 纯文本
file_name = './example_data/焦点科技__2019年__年度报告.pdf'
output_file = './example_data/焦点科技__2019年__年度报告.txt'
with pdfplumber.open(file_name) as pdf, open(output_file, 'wt', encoding='utf-8') as f:
	for page in pdf.pages: # pdf.pages是⼀个Page对象的列表
		text = page.extract_text() # 调⽤Page对象的extract_text()⽅法提取⽂本
		f.write(text)
		f.write('\n')
		
## 表格
with pdfplumber.open(file_name) as pdf, open(output_file, 'wt', encoding='utf-8') as f:
	for page in pdf.pages: # pdf.pages是⼀个Page对象的列表
		text = page.extract_table() # 提取每⻚的表格⽂字信息
		# page.extract_tables() 提取多个表格
		print(text)
		if text:
			f.write(str(text))
			f.write('\n')
			
## 表格保存为excel
from openpyxl import Workbook
with pdfplumber.open(file_name) as pdf:
	for i in pdf.pages:
		table = i.extract_table()
		if table:
			workbook = Workbook() # 创建⼀个⼯作簿
			sheet = workbook.active # 获取当前活跃的sheet,默认是第⼀个sheet
			for row in table:
				sheet.append(row)
				workbook.save(output_file) # 保存⼯作簿
				break

## 提取图片保存到本地
with pdfplumber.open(file_name) as pdf:
	for i in pdf.pages:
	print('⻚码:', i.page_number)
	print('⻚宽:', i.width)
	print('⻚⾼:', i.height)
	print('⻚⽂本:', i.extract_text())
	print('⻚表格:', i.extract_table())
	print('⻚图⽚:', i.images)
	for img in i.images:
		# 获取图⽚的⼆进制流
		img_data = img['stream'].get_data()
		with open(output_file, 'wb') as f:
			f.write(img_data)
	break # 解析第⼀⻚
1.1.2 pymupdf

pymupdf 支持将文字修改写入 pdf 的界面,支持提取所有类型的文档,支持的功能特别多,基本上各种文件都可以处理

import fitz
pdf_path = '/example_data/安靠智电__2019年__年度报告.pdf'
doc = fitz.open(pdf_path)

# 基本的pdf信息
title = doc.metadata['title'] # 标题
author = doc.metadata['author'] # 作者
create_time = doc.metadata['creationDate'] # 创建时间
num_pages = doc.page_count # ⻚数
page = doc.load_page(0) # 加载第⼀⻚
page_width = page.rect.width # ⻚宽
page_height = page.rect.height # ⻚⾼
page_text = page.get_text() # ⻚⽂本
page_images = page.get_images(full=True) # ⻚图⽚
print('标题:', title)
print('作者:', author)
print('创建时间:', create_time)
print('⻚数:', num_pages)
print('⻚码:', 1)
print('⻚宽:', page_width)
print('⻚⾼:', page_height)
print('⻚⽂本:', page_text)
print('⻚图⽚:', page_images)


num_pages = doc.page_count # ⻚数
for page_index in range(num_pages):
	page = doc.load_page(page_id=page_index)
	page_text = page.get_text() # ⻚⽂本
	print(page_text)
	break
	
for page_index in range(num_pages):
	page = doc.load_page(page_id=page_index)
	image_list = page.get_images() # 图⽚
	print(image_list)
	# 两种⽅式
	# 1
	for img in image_list:
		xref = img[0]
		base_image = doc.extract_image(xref)
		image_bytes = base_image["image"] # 图⽚⼆进制数据
		image_ext = base_image["ext"] # 图⽚格式
		# image_path = f'./example_data/__焦点科技__2019年__年度报告__page_{page_index}__image_{xref}.{image_ext}'
		# with open(image_path, 'wb') as f:
		# f.write(image_bytes)
	# 2
	pix = fitz.Pixmap(doc, xref)
	pix.save(f'./example_data/焦点科技__2019年__年度报告__page_{page_index}__image_{xref}.png')
	break
	
## 获取表格
for page_index in range(num_pages):
	page = doc.load_page(page_id=page_index)
	tables = page.find_tables() # 表格
	print(tables)
	# 提取表格数据并存储为csv⽂件
	for table in tables:
		df = table.to_pandas()
		print(df.head())
		df.to_csv(
					f'./example_data/焦点科技__2019年__年度报告_page_{page_index}__table_{table}.csv',
				index=False)
		break
		
## PDF文档分割
output_dir = './example_data/{0}.pdf'
for page_index in range(num_pages):
	print(page_index)
	# 创建⼀个新的Document对象,包含当前⻚⾯
	new_pdf = fitz.open()
	new_pdf.insert_pdf(doc, from_page=page_index, to_page=page_index)
	# 保存为单独的pdf⽂件
	new_pdf.save(output_dir.format(page_index))
	new_pdf.close()
	break
doc.close()
1.1.3 pypdf

pypdf 就是一种基于规侧广泛使用的解析器,也是 LangChain 和 Llamalndex 中解析 PDF文件的标准方法。

pip install PyPDF2

在这里插入图片描述

import PyPDF2
filename = "./example_data/焦点科技_2019年__年度报告.pdf"
pdf_file = open(filename, 'rb')
reader = PyPDF2.PdfReader(pdf_file)
page_num = 0
page = reader.pages[page_num]
text = page.extract_text()
print('--------------------------------------------------')
print(text)
pdf_file.close()
'''
焦点科技股份有限公司 2019年年度报告全⽂ 
1 
焦点科技股份有限公司 
Focus Technology Co., Ltd. 
(南京江北新区星⽕路软件⼤厦 A 座12F)
⼆〇⼀九年年度报告 
⼆〇⼆〇年⼆⽉
'''

1.2 基于深度学习的pdf解析

基于深度学习模型的方法能够准确地识别整个文档的布局,包括表格和段落。它甚至可以理解表中的结构。这意味着它可以将文档划分为定义明确、完整的信息单元。同时保留预期的含义和结构。
代表性的开源框架:

  • Unstructured: 已经集成到langchain中。使用hi_res策略设置infer_table_structure=True 可以很好的识别表格信息。然而 fast策略因为不使用目标检测模型,在识别图像和表格方面表现比较差。
  • Layout-parser:如果需要识别复杂的结构化PDF ,建议使用最大的模型以获得更高的精度,但是会比较慢。此外,Layout解析器的模型在过去几年中似乎没有更新。
  • PP-StructureV2: 可以组合各种模型用于文档分析,性能高于平均水平。
Unstructured
from unstructured.partition.pdf import partition_pdf
filename = "../paper/bert.pdf"
# infer_table_structure=True automatically selects hi_res strategy
elements = partition_pdf(filename=filename, infer_table_structure=True)
tables = [el for el in elements if el.category == "Table"]
print(tables[0].text)
print('--------------------------------------------------')
print(tables[0].metadata.text_as_html)

1.3 基于多模态的pdf解析(复杂结构)

LlamaIndex例子:检索相关图像(PDF页面)并将其发送到GPT4-V 以响应查询。

  1. 将每个PDF页面视为一个图像,让GPT4-V 对每个页面进行图像推理,为图像推理构建文本矢量存储索引,根据图像矢量存储查询答案。
  2. 使用Table Transformer从检索到的图像中裁剪表信息,然后将这些裁剪的图像发送到GPT4-V 进行查询相应。
  3. 对裁剪的表图像应用OCR,并将数据发送到GPT4 以回答查询。

经测试确定第三种方法最有效。
此外可以试用多模态模型从图像中提取或者总结关键信息(PDF文件可以很容易转换为图像)

1.3.1 解析pdf文档存在哪些挑战

挑战在于准确提取整个页面的布局,并将表格、标题、段落和图片在内的内容翻译成文档的文本表示。这个过程涉及到处理文本提取、图像识别中的不确定之处,以及表中行-列关系的混乱。

1.3.1.1 挑战一:如何从表格和图像中提取数据问题?

使用unstructured框架作为示例,检测到的表格数据可以直接导出为HTML:
在这里插入图片描述
复制HTML标记并将其另存为HTML文件,使用Chrome打开如下:
在这里插入图片描述

1.3.1.2 挑战二:如何重新排列检测到的块?特别对于双列PDF?

在这里插入图片描述
在确定布局后,unstructured框架会将每个页面划分成几个矩形块:

在这里插入图片描述
每个矩形块的详细信息可以通过以下格式获取:
在这里插入图片描述
其中(x1, y1)是左上顶点的坐标,(x2, y2)是右下顶点的坐标
在这里插入图片描述
此时,可以选择重新调整页面的阅读顺序。unstructured 有一个内置排序算法。但是实际排序结果不是很满意。
因此有必要设计一种排序算法。最简单的方法就是先按左上角顶点的水平座标排序,如果水平座标相同,则按垂直坐标排序。伪代码如下:

layout.sort(key=lambda z:(z.bbox.x1, z.bbox.y1, z.bbox.x2, z.bbox.y2))

然而还发现,即使同一列中的块,其水平坐标也可能发生变化。如下图,提取到的紫色线条块的水平坐标bbox.x1 实际更靠左。排序时他将位于路线块之前,显然违反了阅读顺序。

在这里插入图片描述
在这种情况下使用一种可能的算法:

  • 首先,对左上角所有x坐标x1 进行排序,可以得到X1_min
  • 然后,对所有右下角x坐标x2进行排序,可以得到x2_max
  • 接下来,将页面中心线的x坐标确定x1_min = min([el.bbox.x1 for el in layout]) ; x2_max = max([el.bbox.x2 for el in layout]); mid_line_x_cooedinate = (x2_max + x1_min)/2
  • 接下来,如果bbox.x1< mid_line_x_cordinate ,则块被分类为左列的一部分。否则被视为右边的一部分。
  • 分类完成后,根据列中的y坐标对每个块进行排序。
  • 最后,将右侧列连接到左侧列的右侧
left_column, right_column = [], []
for el in layout:
	if el.bbox.x1 < mid_line_x_cooedinate:
		left_column.append(el)
	else:
		right_column.append(el)

left_column.sort(key = lambda z: z.bbox.y1)
right_column.sort(key = lambda z: z.bbox.y1)
sorted_layout = left_column + right_column

值得一提的是这种改进也与单列pdf兼容.

1.3.1.3 挑战三:如何提取多级标题?

提取多级标题的目的是提高LLM答案的准确性。
该算法依然依赖与上面提到的布局快。我们可以设置type=‘Section-hearder’的块,并计算高度差(bbox.y2-bbox.y1)。高度差最大的块对应第一级标题,其次是第二级标题…

补充:PPT类文档解析问题

  • 难点:如何对PPT 中的大量的流程图,架构图进行提取,因为这些图多以形状元素在PPT中呈现,如果只提取文字,大量潜藏的信息会大量丢失。
  • 解决办法:将PPT转为pdf形式,然后用户上述处理PDF 的形式进行解析。

参考:
版面分析–优化策略篇
【知识库构建——知识文本分块】
【知识库构建——文档切分优化策略篇】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1668935.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DSA理解理解蓝桥杯例题signature

一、历史 1991年8月&#xff0c;NIST&#xff08;Nation Institute of Standards and Technology&#xff0c;美国国家标准技术研究所&#xff09;提出了数字签名算法&#xff08;DSA&#xff09;用于他们的数字签名标准&#xff08;DSS&#xff09;中。 DSA是算法&#xff0c…

C++的数据结构(四):队列

在数据结构中&#xff0c;队列&#xff08;Queue&#xff09;是一种特殊的线性表&#xff0c;只允许在表的前端&#xff08;front&#xff09;进行删除操作&#xff0c;而在表的后端&#xff08;rear&#xff09;进行插入操作。队列中没有元素时&#xff0c;称为空队列。队列的…

python数据分析——matplotlib可视化基础

参考资料&#xff1a;活用pandas库 # 导入库 import pandas as pd import matplotlib.pyplot as plt # 导入数据 anscombepd.read_csv(r"...\seaborn常用数据案例\anscombe.csv") anscombe.head() 大多数基本图表的名字以plt.plot开头。 # 创建数据子集 # 只包含数…

消息中间件Kafka(PHP版本)

小编最近需要用到消息中间件&#xff0c;有需要要复习一下以前的东西&#xff0c;有需要的自取&#xff0c;强调一点&#xff0c;如果真的想了解透彻&#xff0c;一定要动手&#xff0c;脑袋会了不代表就会写了 Kafka是由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅…

py黑帽子学习笔记_环境准备

1 下载os装os 下载一个kali虚机镜像然后用虚机管理软件创虚机&#xff0c;装完如下图&#xff0c;我用的版本是2024.1的版本kali-linux-2024.1-installer-amd64&#xff0c;可以从镜像站下载&#xff0c;官网下的慢还断网Index of /kali-images/kali-2024.1/ | 清华大学开源软…

AI 问答 API 对接说明

我们知道&#xff0c;市面上一些问答 API 的对接还是相对没那么容易的&#xff0c;比如说 OpenAI 的 Chat Completions API&#xff0c;它有一个 messages 字段&#xff0c;如果要完成连续对话&#xff0c;需要我们把所有的上下文历史全部传递&#xff0c;同时还需要处理 Token…

47岁古天乐唯一承认女友约「御用阿妈」过母亲节

日前关宝慧在IG晒出一张聚会照&#xff0c;并写道&#xff1a;「预祝各位#母亲节快乐&#x1f339;#dinner #happy #friends #好味」相中所见&#xff0c;前TVB金牌监制潘嘉德、卢宛茵、黄&#x28948;莹、黎萨达姆都有出席饭局。 当中黄&#x28948;莹身穿卡其色西装褛&…

【35分钟掌握金融风控策略24】定额策略实战

目录 基于客户风险评级的定额策略 确定托底额度和盖帽额度 确定基础额度 基于客户风险评级确定风险系数 计算最终授信额度 确定授信有效期 基于客户风险评级的定额策略 在开发定额策略时&#xff0c;精准确定客户的基础额度是一个关键步骤&#xff0c;通常会基于客户的收…

整体安全设计

人员和资产的安全是当今许多组织的最高优先事项之一。随着暴力事件在美国各地盛行——枪击事件、袭击、内乱等——建筑物业主必须为其建筑物及其居住者的安全做好计划。 为了创造一个安全的环境&#xff0c;新设施或园区的安全设计必须超越基本的摄像头和访问控制设备&#xf…

纯血鸿蒙APP实战开发——首页下拉进入二楼效果案例

介绍 本示例主要介绍了利用position和onTouch来实现首页下拉进入二楼、二楼上划进入首页的效果场景&#xff0c;利用translate和opacity实现动效的移动和缩放&#xff0c;并将界面沉浸式&#xff08;全屏&#xff09;显示。 效果图预览 使用说明 向下滑动首页页面超过触发距…

【Linux】centos7安装软件(rpm、yum、编译安装),补充:查找命令的相关文件路径,yum安装mysql

【Linux】技术上&#xff0c;Linux是内核。而术语上&#xff0c;我们通常说的Linux是完整的操作系统&#xff0c;其实称为"Linux发行版"&#xff0c;是将Linux内核和应用系统打包&#xff0c;由不同的发行家族发行了不同版本。Linux发行版众多&#xff0c;主要有RedH…

HCIP-Datacom-ARST自选题库_07_割接【35道题】

一、单选题 1.在割接的测试阶段&#xff0c;符合以下哪一种情况的可以判断为割接成功? 网络承载的上层应用业务测试正常 网络设备的配置查看结果正常 网络流量路径正常 路由协议运行正常 2.在割接的测试阶段中&#xff0c;表明已经完成测试的标准是: IP设备的配置查看结…

org.postgresql.util.PSQLException: 错误: 关系 “dual“ 不存在

springboot 项目连接 postgreps&#xff0c;启动时报错 org.postgresql.util.PSQLException: 错误: 关系 "dual" 不存在。 查阅资料后发现这是由配置文件中的配置 datasource-dynamic-druid-validationQuery 导致的 spring:datasource:druid:stat-view-servlet:ena…

二叉树介绍

引入 定义 区别 定义不同 形态不同 基本形态

Ubuntu18.04解决有线网卡连接问题(不更新内核成功版)

https://www.realtek.com/Download/List?cate_id584 &#xff08;需要翻一下&#xff09; 不想自己去下载&#xff0c;直接去我资源里下载我上传的包就好啦(&#x1f602;&#x1f602;&#x1f602;刚刚看了下别人下载要VIP还是自己去网站下很快的) 下载后解压&#xff0c;在…

FreeRTOS二值信号量

目录 一、信号量的概念 1、信号量的基本概念 2、信号量的分类 二、二值信号量简介 三、二值信号量相关API 1、创建二值信号量 2、释放二值信号量 3、获取二值信号量 四、二值信号量实操 1、实验需求 2、CubeMX配置 3、代码实现 一、信号量的概念 1、信号量的基本概…

从零开始的软件测试学习之旅(七)接口测试流程及原则案例

接口测试三要素及案例 接口测试介绍接口预定义接口测试的主要作用测试接口流程如下接口测试三要素接口测试分类RESTful架构风格RESTful架构三要素要素一要素二要素三 RESTful架构风格实现restful架构案例接口测试流程接口测试原则功能测试自动化测性能测试 复习复盘 接口测试介…

MYSQL:MySQL 事务隔离级别详解

一、MySQL事务是什么&#xff1f; MySQL事务是一组在数据库中执行的操作&#xff0c;这些操作要么全部成功执行&#xff0c;要么全部不执行&#xff0c;以确保数据库的完整性和一致性。 事务的 ACID 事务具有四个特征&#xff1a;原子性&#xff08; Atomicity &#xff09;、…

COX回归特征筛选

任务&#xff1a;利用cox筛选出P值小于0.05的特征 数据的格式第一列为标签&#xff0c;第二列为时间&#xff0c;第三列及后为特征 先想一想&#xff0c;想好了再更新 这里我们先举一个例子&#xff1a; import pandas as pd from lifelines import CoxPHFitter# 创建示例数…

【随笔】Git 高级篇 -- 远程跟踪分支 git checkout -b | branch -u(三十五)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…