上图演示了解压缩,并打开了word/media文件夹,这是文档里出现的图片。分析发现,在docx中同一张图复制多次,media里面只保留一张原图。这说明,它是个勤俭节约的好孩子。承载同样多的内容,docx格式比doc的体积要小。
正如我们看到,解压后它是有目录结构的。
放心,我不会挨个把文件都给你介绍一遍。因为,那并没有什么用。即便有用,你也记不住。即便你记得住,我也说不明白……为什么要学习那么全面的知识呢?汉字总计10万多个,常用字只有2500个,够用了。
我说几个比较关键的点。
3.1 主文件 document.xml位于word下的document.xml文件,是docx的主战场。可以说,文档中你能看到的所有内容,在这里都有直接或者间接的记录。
document.xml是一个XML格式的文档。
我们来打开它,咱们先只打开一级。
为了你能看下去,我对数据做了处理,保证你只能看到关键信息。
<w:document>
<w:body>
<w:p>...</w:p>
<w:p>...</w:p>
<w:tbl>...</w:tbl>
<w:p>...</w:p>
...
<w:sectPr>...</w:sectPr>
</w:body>
</w:document>
我们看到,body体里,只有3种标签,分别是<w:p>、<w:tbl>和<w:sectPr>。
一个docx文档,基本由这三种成分组成。w指的是word,p指的是paragraph段落,tbl表示table表格。sectPr全称是section primp,这个千万别记,容易扰乱思路。
清空你的大脑,docx文档里就两种大类,一种叫<w:p>段落,另一种叫<w:tbl>表格。
3.2 段落标签 w:p在docx中,段落是最常见的,是文档中最主要的组成单元。
和你理解的段落一样。不换行就属于一个段落。即便是“咔咔咔”敲上6个回车,虽然没有内容,那它也属于6个段落,在xml中是6个<w:p></w:p>。
另外,包含图片、流程图、公式等元素的内容,也是包含在段落中的。换句话说,它们都是小弟。
我们能用代码取到段落的信息吗?当然能!(这自问自答,被怀疑是凑字数)
我们用哪类编程语言都可以做到,因为仅仅就是读取XML文件。
但是对于教学而言,用python无疑是最佳的选择。
# 导入解析xml的库
import xml.dom.minidom as xdom
# 加载文档
xp = xdom.parse('word/document.xml')
# 获取文档根节点
root=xp.documentElement
# 获取body节点们
bodys = root.getElementsByTagName("w:body")
# 因为getElements返回多个对象,我们只有一个
body = bodys[0]
# 循环遍历body下的节点
for i,ele in enumerate(body.childNodes):
e_name = ele.nodeName
# 打印{序号} -> {节点名称} is {对象}
print(i,"->",e_name,"is",ele)
我们看一下打印结果,它和源文档完全对应,一个都没有少。
下面该详细说一下w:p的小弟们了。
3.3 文本标签 w:t在纷杂的xml文件中,可以扒拉出来一个叫<w:t>标签。
<w:p>
<w:r>
<w:t>word的doc格式原来是不开源的,后来改成了docx格式后,是开源的。</w:t>
……
</w:r>
……
</w:p>
这里面存储的内容,就是word里面的文字,t就是text的简称。
你在docx里面看到的每一个字,基本上都是被<w:t>和</w:r>所包裹的。
也就是说,如果我们拿出所有<w:t>标签内的文本,我们就做到了纯文本docx的解析。
代码,其实很简单,就是在<w:p>元素中,扫描<w:t>的标签并取出其内容。
上面我们已经拿到了body标签,所以从那里继续。
# 循环body下的大单元 w:p段落,w:tbl表格
for i,ele in enumerate(body.childNodes):
# 找到包含w:t的标签,可能是多个
wts = ele.getElementsByTagName("w:t")
ele_text = "" # 记录大单元内所有文本
for wt in wts: # 循环
ele_text = ele_text wt.text
print(ele_text) # 打印输出
看看代码对应的效果。