一开始以为docx解析一切,后来发现远没有那么简单。
这里探讨的是docx文件,doc文件比较麻烦,最好在windows平台上处理成docx文件。两者的区别是doc格式比较早office 2003,存储的是二进制格式,docx存储的是xml文件等组成的压缩包,存储容量更小。
这篇文章没给代码,基于提示去问问大模型怎么写,根本记不住。
from docx import Document
提取段落 .paragraps
提取表格 .tables
获取每个元素的类型 .element.body 其中.tag.endswith p为段落,tbl为表格,secPr为章节?,bookmarkStart、bookmarkEnd为书签
获取段落的分页信息 ._element.xml 包含lastRenderedPageBreak
获取样式 .style.name 可以获知其是一级标题?二级标题?
获取字号 从paragraps的runs中提取font.size
如果用终端vim xxx.docx,会看到一堆文件让选择,但是vim并不能真正显示出这些文件的内容。用zipfile可以将.docx的内容解压到一个文件夹
import zipfile
with zipfile.Zipfile(file_path,'r')as f:
f.extractall(output_path)
文档中嵌套的文档可以在word/media或word/embeddings下找一找
主要文件在word/document.xml
页脚文件在word/footer*.xml
页眉文件在word/header*.xml
标号文件在word/numbering.xml
有2种情况,后面链接到了本地一个文件,根据路径找到对应文件,或者文件作为附件真正被插入到文档中。
情况一:链接
用docx找一下oleObject
document = Document(f_path)
for rel in document.part.rels.values():
if 'oleObject' in rel.reltype:
print(rel.target_ref)
oleobject:代表工作表上的一个 ActiveX 控件或链接或嵌入的 OLE 对象
OLEObject 对象 (Excel) | Microsoft Learn
情况二:附件
用zipfile解压后找一下
按照分隔符迭代拆分
139 深入解析 RecursiveCharacterTextSplitter 类 langchain_text_splitters.charater.py-CSDN博客
本质是用docx2txt(一个可以用pip安装的库)提取page_content信息,再用自定义的Document进行管理。docx2txt的功能具体看:
七
缺点:
1、没有分离页眉页脚
2、不能保留表格,每个单元格都变成了一行
3、附件没有
本质还是用docx实现的,考虑了段落的分页情况,可以提取起止页间的段落
lainchain的底层,可以对word文件解压后提取页眉、主文本、页脚、图片
从docx的xml源文件解析复杂表格,试过多种开源的docx解析方案,对复杂表格的解析都不好,会丢失格式信息。尝试自己来解析,获得准确的列信息,解析word/document.xml文件,获得一个大xml,可以发现,段落和表格的信息都在其中,奇怪的是,这个xml会进行奇奇怪怪的断句。将表格前后的xml内容复制,在xml在线解析网页中格式化,可以看到清晰的表格格式。
用xml.etree.ElementTree解析后所有数据是一个tree的形式,而不是list的形式,用findall、find、get来获得下一级的信息。列合并看gridSpan,可以直接看到列合并数量,如
上文说到xml会进行奇奇怪怪的断句,所以一般会用‘’.join进行拼接,但是暴力拼接会丢失换行的段落信息,解决办法是在单元格内找段落,段落内进行拼接。
# 表
for table in tables:
# 行
rows = table.findall('.//w:tr',ns)
for row in rows:
#单元格
cells = row.findall('.//w:tc',ns)
for cell in cells:
# 段落
ps = cell.findall('.//w:p',ns)
for p in ps:
# 文本
t = ''.join([text.text for text in p.findall('.//w:t',ns)])
参考Python批量提取docx格式Word文档中所有文本框内的文本_python怎么复制word文档中的文本框和内容-CSDN博客缺陷是不知道文本框的位置,有的文档是左右2个文本框人为做了分栏,但是脚本提取时,可能先提取到右边的再提取到左边的。
自动编号时,有多种样式,在document.xml中没有直接记录其样式及内容,需要另外解析word/numbering.xml文件。
Python实现自动编号解析Word文档-物联沃-IOTWORD物联网
参考这篇文章,核心思想是提取document.xml中的ilvl和numId,然后去numbering.xml找对应的lvlText,接着统计出现次数进行渲染
document.xml中的ilvl和numId:
style示例:
{'start': '1', 'numFmt': 'decimal', 'lvlText': '%1.', 'lvlJc': 'left'}
渲染示例:
lvlText = lvlText.replace(f'%{i + 1}', str(cache[(abstractId, i)]))
渲染时会遇到一点奇怪的问题numbering.xml中记录的lvlText和word中不一样。