#RAG|NLP|Jieba|PDF2WORD# pdf转word-换行问题
文档在生成PDF时,文宁都发生了什么。本文讲解了配置对象、resources对象和content对象的作用,以及字体、宇号、坐标、文本摆放等过程。同时,还解释了为什么PDF转word或转文字都是一行一行的以及为什么页眉页脚的问题会加大识别难度。最后提到了文本的编码和PDF中缺少文档结构标记的问题。PDF转word更像是一种逆向工程。
第三方库pdf转word的痛点-格式不保留
本文着力解决换行问题:
- 源文本正常输入,pdf解析第三方库识别出来多余换行符
如
原文:“你好”
识别:“你\n好” - 源文本出现多个换行符,pdf解析第三方库识别出一个换行符
如
原文:“你好\n\n\n\n\n\n我是向日葵花子”
识别:“你好\n我是向日葵花子”
word 转 pdf 经历了什么
文本转换为PDF时,记录的信息
包括:
- 位置和大小信息:记录每个文本在页面上的位置和大小。
- 字体信息:记录文本所使用的字体名称、大小和样式。
- 颜色信息:记录文本的颜色。
- 行间距和段落间距:记录文本之间的行间距和段落之间的间距。
- 文本属性:记录文本的对齐方式、装饰等其他属性。
- 超链接和书签:记录文本中的超链接和书签信息,以实现交互功能。
这些信息的记录旨在确保在PDF中正确呈现文本内容,并保持文档的原始格式和布局。
pdf文本信息
pdf文本是由文本空间组成的,其中包含:
文本矩阵,定义下一个字形的当前转换。它由文本定位和显示运算符的文本改变。
文本行矩阵,它是当前行开头的文本矩阵的状态。因此,通过使用操作员移动到下一行,可以垂直对齐文本行,而无需手动跟踪行的开始位置。
这些矩阵不会从文本部分持续到文本部分,而是在每个文本部分的开头重置为单位矩阵。 结合字体大小,水平缩放和文本上升,这两个矩阵定义了从文本空间到用户空间的转换。
如何获得pdf信息
大段处理
可以在调用第三方库的过程中加一些小算法,我这里给一点点提示
- 读取pdf基本信息
- 逐行获取pdf信息
- 根据每行的行宽来判断是不是多输出了换行符
- 每行即使没有文字只有换行符也要加入到获取的信息中
这一步可以完成百分之八十的换行格式还原。
获取每行信息的代码:
with pdfplumber.open(file_path) as pdf:for p in pdf.pages:# print(p.bbox)page_lines = p.extract_text_lines()
接下来就要去分析文档每行的信息,然后利用坐标去处理了,大家可以自己思考下代码怎么写。

页眉页脚、大小标题
识别处理思路和大段处理一致
小段处理

通过坐标处理不了两行的小段,特别是开头没有缩进的unstructured文本,这里我们需要加上其他算法。
我使用的是nlp的文本分析进行兜底。
处理流程:
- 分析上下文关系优化结构算法: 在获取到文本内容后,可以编写一个分析句子上下文关系的算法来处理文本,对于出现问题的地方进行修正。
主要用到:
词性标注(Part-of-Speech Tagging): 词性标注是将句子中的每个词汇标记为其对应的词性(如名词、动词、形容词等)的过程。通过词性标注可以识别句子中各个词汇的语法角色,从而帮助理解句子的结构和含义。
句法分析(Syntax Parsing): 句法分析是分析句子中各个词汇之间的语法关系,如主谓关系、动宾关系等。通过句法分析可以构建句子的语法树,从而帮助理解句子的结构和语义。 - 合并文本: 根据分析结果,将需要合并的部分合并到一起。
- 输出结果:输出处理后的文本。
这一步可以完成到90%的换行格式还原,通过不断优化句法分析的规则,可以逐渐接近100%。
清洗文本
nlp句法分析是分析句子中各个词汇之间的语法关系,因此,像emoji或者其他特殊、对于计算机语义处理无意义的符号保留下来必定对结果产生很大影响,最终合并的效果大打折扣,所以我们需要先对文本进行一个清洗,去掉无意义的符号。
由于我的文档只涉及到emoji这种特殊符号,所以我只进行了emoji的清洗
def remove_emoji(text):emoji_pattern = re.compile("["u"\U0001F600-\U0001F64F" # emoticonsu"\U0001F300-\U0001F5FF" # symbols & pictographsu"\U0001F680-\U0001F6FF" # transport & map symbolsu"\U0001F1E0-\U0001F1FF" # flags (iOS)u"\U00002600-\U000027BF" # miscellaneous symbolsu"\U0001F300-\U0001FAD6" # additional emoticons"]+", flags=re.UNICODE)return emoji_pattern.sub(r'', text)
句子拆分
按照逗号拆分就可以,然后找到带有换行符号的句子进行进一步的词性标注
注意只取带有换行符的小句,这样可以提高工作效率减少无意义的算法调用
使用split函数即可
词性标注

为了分析句子语法关系、上下文关系,我们必须先进行词性标注,构建语法树,然后再进行句子分析
这里我直接用的中文nlp库jieba,其他好用的库可以直接替换使用,如果是英文词性标注可以使用ntlk,ntlk也有中文词性标注,但是我中文标注我更喜欢用jieba
jieba的jieba词性标注表我也给大家整理好了
词性标注的代码:
import jieba.posseg as psg
# 分词和词性标注
seg = psg.cut(sentence)
# 定义语法规则
result_list = []
verbs = []
for word, pos in seg:# 对句法树进行处理,这里只是简单打印出来,你可以根据需要处理print("句法树:", word, pos)word_info = {'word': word, 'pos': pos}# 将字典添加到列表中result_list.append(word_info)if pos == 'v':verbs.append(word_info)
verbs = [word for word, pos in seg if pos == 'v']
分析上下文关系
词性标注结束后,我们就可以根据语法树分析上下文关系了
merged_sentences = []
for i, sentence in enumerate(sentences):if i > 0:# 分析上下文关系verbs_prev, seg_prev = analyze_context(sentences[i - 1])verbs_curr, seg_curr = analyze_context(sentence)x = list(seg_prev)# 如果前一个句子或当前句子至少有一个含有动词,则进行合并if (len(verbs_prev) == 1 and len(verbs_curr) == 0) or (len(verbs_prev) == 0 and len(verbs_curr) == 1):merged_sentences[-1] += sentence# 如果上一句的最后一个词和下一句的第一个词都是动词,则进行合并elif seg_prev[-1] and seg_curr[0] and seg_prev[-1]["pos"] in ['r', 'v'] and seg_curr[0]["pos"] == 'v':merged_sentences[-1] += sentence# 代词和指示词:如果后一个句子以代词或指示词开头,这可能表明它是对前一个句子的补充。elif seg_curr[0]["pos"] in ['r', 'z', 'c'] or seg_curr[0]["word"] in ['这', '那', '其', ...]:merged_sentences[-1] += sentence# 时间+nelif seg_curr[0]["pos"] in ['n'] or seg_prev[0]["pos"] in ['t', 'm', ...]:merged_sentences[-1] += sentence# 句号和分号:虽然句号和分号通常表示句子的结束,但如果它们后面紧跟的是小写字母或标点符号,可能意味着这是同一句话的一部分。elif seg_prev[-1]["word"] in ['。', ';'] and not seg_curr[0]["word"].istitle():merged_sentences[-1] += sentence# 如果后一个句子的第一个词是“的”并且前一个句子的最后一个词是动词,则进行合并elif seg_curr[0] and seg_curr[0]["pos"] == 'm' and seg_prev[-1] and seg_prev[-1]["pos"] == 'v':merged_sentences[-1] += sentences[i]# 如果后一个句子的第一个词是“的”并且前一个句子的最后一个词是动词,则进行合并elif seg_curr[0] and seg_curr[0]["pos"] == 'p' and seg_prev[-1] and seg_prev[-1]["pos"] == 'd':merged_sentences[-1] += sentences[i]# 3. 如果上一句的最后一个词是标点符号,且下一句的第一个词不是句首发语词,则进行合并elif seg_prev[-1]["pos"] == 'x' and seg_curr[0]["pos"] not in ['c', 'r', 'u', 'p', 'm', 'e']:merged_sentences[-1] += sentence# 4. 如果上一句的最后一个词是名词或动词,且下一句以时间状语或条件状语开头,则进行合并elif (seg_prev[-1]["pos"] in {'n', 'vg', 'v'}) and (seg_curr[0]["pos"] in {'f', 'c'}):merged_sentences[-1] += sentenceelse:merged_sentences.append(sentence)else:merged_sentences.append(sentence)
我在判断规则的同时,进行了是否合并的判断,这样 我们就得到了合并后的文本merged_sentences

参考文献
https://www.bilibili.com/video/BV1Vi4y1C71M/?spm_id_from=333.788&vd_source=8c9777cd5733f7f447f766cd5105041b
相关文章:
#RAG|NLP|Jieba|PDF2WORD# pdf转word-换行问题
文档在生成PDF时,文宁都发生了什么。本文讲解了配置对象、resources对象和content对象的作用,以及字体、宇号、坐标、文本摆放等过程。同时,还解释了为什么PDF转word或转文字都是一行一行的以及为什么页眉页脚的问题会加大识别难度。最后提到了文本的编码和PDF中缺少文档结构标…...
solr的原理是什么
1 Java程序里如果有无限for循环的代码导致CPU负载超高,如何排查? 排查Java程序中由于无限循环导致的CPU负载过高的问题,可以按照以下步骤进行: 资源监控: 使用系统命令行工具(如Linux上的top或htop…...
【安装指南】nodejs下载、安装与配置详细教程
目录 🌼一、概述 🍀二、下载node.js 🌷三、安装node.js 🍁四、配置node.js 🌼一、概述 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时,用于构建可扩展的网络应用程序。Node.js 使用事件驱动、…...
Mobileye CES 2024 自动驾驶新技术新方向
Mobileye亮相2024年国际消费类电子产品展览会推出什么自动驾驶新技术? Mobileye再次亮相CES,展示了我们的最新技术,并推出了Mobileye DXP--我们全新的驾驶体验平台。 与往年一样,Mobileye是拉斯维加斯展会现场的一大亮点,让参观者有机会见证我们对自主未来的愿景。 在…...
【Linux】网络基本配置及网络测试、测试工具
一、网络基本配置 查看网络信息: ifconfigc / ip addr停止网卡eth0: ifconfig eth0 down在本地启动网卡eth0: ifconfig eth0 up改变网卡ip: ifconfig eth0 192.168. .修改子网掩码: ifconfig eth0 (I…...
pnpm : 无法加载文件 D:\tool\nvm\nvm\node_global\pnpm.ps1,因为在此系统上禁止运行脚本
你们好,我是金金金。 场景 新创建的项目,在vscode编辑器终端输入 pnpm i,显示报错如上 解决 在终端输入get-ExecutionPolicy(查看执行策略/权限) 输出Restricted(受限的) 终端再次输入Set-ExecutionPolicy -Scope CurrentUser命令给用户赋予…...
Python 类与实例
在面向对象编程中,类(Class)是一种抽象的概念,它描述了对象的属性和行为。类可以看作是创建对象的蓝图或模板,它定义了一组属性和方法,并提供了创建对象的规范。 类包含了对象的属性和方法的定义ÿ…...
2的N次方
题目描述 输入n行,每行一个整数x,输出2的x次方的个位是多少?2的3次方表示3个2相乘,结果是8 输入 输入n行,每行一个整数x 输出 输出n行,每行一个整数,2的x次方的个位。 样例输入 Copy 5 4…...
cobra - 更容易地构建命令行应用
cobra 是什么 cobra 的主要功能是创建强大的现代 cli 应用程序。目前市面上许多的著名的 Go 语言开源项目都是使用 Cobra 来构建的,例如:K8s、Hugo、etcd、Docker 等,是非常可靠的一个开源项目。 没有 cobra 之前用什么 如果不用 cobra&am…...
windows10设置多个jar后台开机自启
1、window10启动多个jar包的脚本 新建一个txt文档,将以下内容复制到文档中: echo off taskkill /f /im javaw.exe //停用之前启动过的所有后台javaw程序 d: //jar包所在盘符 cd saas //jar包所在文件夹 start cmd /c "title 程序…...
数据库||数据库相关知识练习题目与答案
目录 1.只能读取本系学生的信息? 2.要查询选修“Computer”课的男生姓名,将涉及到关系( ) 3.实体完整性规则规定( ) 4.下列有关范式的叙述中正确的是( ) 5.从课程表course&…...
YOLOv8改进 | 损失函数篇 | 更加聚焦的边界框损失Focaler-IoU、InnerFocalerIoU(二次创新)
一、本文介绍 本文给大家带来的改进机制是更加聚焦的边界框损失Focaler-IoU已经我进行二次创新的InnerFocalerIoU同时本文的内容支持现阶段的百分之九十以上的IoU,比如Focaler-IoU、Focaler-ShapeIoU、Inner-Focaler-ShapeIoU包含非常全的损失函数,边界框的损失函数只看这一…...
利用nginx宝塔免费防火墙实现禁止国外IP访问网站
本章教程,主要介绍,如何利用nginx宝塔面板中的插件免费防火墙,实现一键禁止国外IP访问网站。 目录 一、安装宝塔插件 二、 开启防火墙 一、安装宝塔插件 在宝塔面板中的软件商店,搜索防火墙关键词,找到Nginx免费防火…...
消息中间件(MQ)对比:RabbitMQ、Kafka、ActiveMQ 和 RocketMQ
前言 在构建分布式系统时,选择适合的消息中间件是至关重要的决策。RabbitMQ、Kafka、ActiveMQ 和 RocketMQ 是当前流行的消息中间件之一,它们各自具有独特的特点和适用场景。本文将对这四种消息中间件进行综合比较,帮助您在项目中作出明智的…...
MySQL索引原理以及SQL优化
案例 struct index_failure_t{int id;string name;int cid;int score;string phonenumber;}Map<int,index_failure>; 熟悉C的同学知道,上述案例中,我们map底层是一颗红黑树,一个节点存储了一对kv(键值对)&…...
[Bug] [OpenAI] [TypeError: fetch failed] { cause: [Error: AggregateError] }
[Bug] [OpenAI] [TypeError: fetch failed] { cause: [Error: AggregateError] } ubuntu20 win10 edge浏览器访问 服务器部署 页面打开后想使用chatgpt报错了 rootcoal-pasi1cmp:/www/wwwroot/ChatGPT-Next-Web# PORT3000 yarn start yarn run v1.22.19 warning package.json:…...
@ 代码随想录算法训练营第5周(C语言)|Day31(贪心算法)
代码随想录算法训练营第5周(C语言)|Day31(贪心算法) Day31、贪心算法(包含题目 455.分发饼干 376. 摆动序列 53. 最大子序和 ) 455.分发饼干 题目描述 假设你是一位很棒的家长,想要给你的孩…...
面试手写第二期 Promsie相关
文章目录 一. 手写实现PromiseA规范二. Promise.all实现三. Promise.race实现四. Promise.allsettled实现六. Promise.any实现六. 如何实现 Promise.map,限制 Promise 并发数七. 实现函数 promisify,把回调函数改成 promise 形式八. 并发请求控制 一. 手…...
Windows冷知识:最小化远程桌面与ffmpeg
Windows冷知识:最小化远程桌面与ffmpeg – WhiteNights Site 标签:ffmpeg, Windows, 冷知识 最小化远程桌面会中断ffmpeg的录制 我觉得这个应该算冷知识吧。 前情提要 远程桌面连接至虚拟机,并通过ffmpeg录屏 这里可能不太好理解。 我在用…...
12nm工艺,2.5GHz频率,低功耗Cortex-A72处理器培训
“ 12nm工艺,2.5GHz频率,低功耗Cortex-A72处理器培训” 本项目是真实项目实战培训,低功耗UPF设计,后端参数如下: 工艺:12nm 频率:2.5GHz 资源:2000_0000 instances 为了满足更多…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
