python-docx结合lxml读取word文档段落格式、字体格式等信息

python-docx结合lxml读取word文档段落格式、字体格式等信息

最近还是在研究docx文档,搞了几天终于有点心得了。不得不说,虽然python-docx库没那么强大能直接获取样式继承的字体信息之类的,但是通过使用python-docx,获取段落的xml信息会简单很多,结合lxml进一步获取信息也会方便很多。
首先还是,记一下关于样式继承。

一个样式可以从另一个样式继承属性,有点类似于层叠样式表 (CSS) 的工作方式。base_style使用属性指定继承 。通过将一种风格建立在另一种风格上,可以形成任意深度的继承层次结构。没有基本样式的样式会从文档默认值继承属性。
许多字体属性是三态的,这意味着它们可以采用值 True、False和None。True表示该属性是“on”,False表示它是“off”。从概念上讲,None价值意味着“继承”。

样式继承依然不是那么好理解。
这次写详细一点点叭

document.xml/style.xml

当我们把文档后缀的.docx修改成.zip,解压就会看到一些文件。 其中word文件夹下document.xml是存放文本的主要文件,文档的样式信息则在style.xml中。
在这里插入图片描述

信息获取

如果,文档中的某个段落应用了样式,则该段落的字体格式等一些信息需要从style.xml中获取。
在这里插入图片描述
此时使用python-docx获取字体格式信息之类的,大概率返回的结果是None。也有可能返回的是英文字体信息。

import docx
file_name = 'temp.docx'
doc = docx.Document(file_name)
paragraphs = doc.paragraphs
print('段落0字体:',paragraphs[0].style.font.name)
print('段落3字体:',paragraphs[3].style.font.name)
段落0字体: None
段落3字体: Times New Roman

那么问题来了,返回为None时或者想要获取到中文字体该怎么办呢?接下来要说说我不是很懂以及我也很苦恼的xml了。
首先让我们打印一下段落的xml看看它是个啥。

print(paragraphs[0]._p.xml)
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" xmlns:wpsCustomData="http://www.wps.cn/officeDocument/2013/wpsCustomData">
  <w:pPr>
    <w:pStyle w:val="6"/>
    <w:ind w:firstLine="723"/>
    <w:rPr>
      <w:b w:val="0"/>
      <w:bCs w:val="0"/>
      <w:sz w:val="36"/>
      <w:szCs w:val="36"/>
    </w:rPr>
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:hint="eastAsia"/>
      <w:b w:val="0"/>
      <w:bCs w:val="0"/>
      <w:sz w:val="36"/>
      <w:szCs w:val="36"/>
    </w:rPr>
    <w:t>这里是应用了标题样式的一个标题(黑体 小二号居中)</w:t>
  </w:r>
</w:p>

字体信息在<w:rFonts>中的,可以看到这里面是没有显示详细的字体信息的。注意到前面有<w:pStyle w:val="6">,说明这里用到了id为“6”的style。所以打印一下这个段落的样式的xml看看。

print(paragraphs[0].style.element.xml)
<w:style xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:sl="http://schemas.openxmlformats.org/schemaLibrary/2006/main" xmlns:wpsCustomData="http://www.wps.cn/officeDocument/2013/wpsCustomData" w:type="paragraph" w:styleId="6">
  <w:name w:val="Title"/>
  <w:basedOn w:val="1"/>
  <w:next w:val="1"/>
  <w:link w:val="13"/>
  <w:qFormat/>
  <w:uiPriority w:val="10"/>
  <w:pPr>
    <w:spacing w:before="240" w:after="60"/>
    <w:jc w:val="center"/>
    <w:outlineLvl w:val="0"/>
  </w:pPr>
  <w:rPr>
    <w:rFonts w:eastAsia="黑体" w:asciiTheme="majorHAnsi" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi"/>
    <w:b/>
    <w:bCs/>
    <w:sz w:val="36"/>
    <w:szCs w:val="32"/>
  </w:rPr>
</w:style>

可以看到在style中是有字体信息的。

获取字体信息方法1

转换成lxml后进行信息提取

from lxml import etree
from xml.dom.minidom import parseString
p_style_xmlstr = paragraphs[0].style.element.xml
p_style_xml = etree.fromstring(p_style_xmlstr)  # 转换成lxml结点
p_style_dom = parseString(etree.tounicode(p_style_xml))

# 获取段落字体信息
# 字体名称
style_w_rfonts = p_style_dom.getElementsByTagName('w:rFonts')
font_name_zh = w_rfonts[0].getAttribute('w:eastAsia')
font_name = w_rfonts[0].getAttribute('w:ascii')

获取字体信息方法2

使用xpath进行信息提取

link_id = paragraphs[0].style.element.xpath('string(.//w:pStyle/@w:val)')
font_name_zh = doc.styles.element.xpath(f'string(.//w:style[@w:styleId={link_id}]//w:rFonts/@w:eastAsia)')
font_name = doc.styles.element.xpath(f'string(.//w:style[@w:styleId={link_id}]//w:rFonts/@w:ascii)')
  • 10
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值