python文件处理:解析docx/word文件文字、图片、复选框

前言

因为一些项目原因,我需要提供解析docx内容功能。本来以为这是一件比较简单的工作,没想到在解析复选框选项上吃了亏,并且较长一段时间内通过各种渠道都没有真正解决这一问题,反而绕了远路。

终于,我在github python-docx模块的Issues中找到了重要的思路及线索,并最终通过后续努力,实现了【解析docx/word文件文字、图片、复选框】这一功能。

Feature: Read checkboxes in Word forms · Issue #224 · python-openxml/python-docx · GitHub

python-docx基础操作

bash 复制代码
# 安装python-docx模块
pip install python-docx
python 复制代码
import os
import docx
import time

# 图片附件的存储地址
image_save_path = 'appendix_dir'

# 读取docx表格里的数据,图片及文字
def read_table_from_docx(file_path):
    """
    :param file_path:
    :return: table_data, images
    """

    # 读取docx/word文件
    doc = docx.Document(file_path)

    # 获取docx中的table对象
    tables = doc.tables
    table_data = []
    images = []

    # 拿取文件中的图片对象,并存储在images列表里
    for rel in doc.part.rels.values():
        if "image" in rel.reltype:
            image = rel.target_part
            image_data = image.blob
            images.append(image_data)

    # 读取文件表格中的文字内容
    # 这里不能解析特殊字符和复选框
    # 并且合并单元格的文字内容,将出现多行多列重复出现,需要注意
    for table in tables:
        for row in table.rows:
            row_data = []
            for cell in row.cells:
                # print(cell, cell.text)
                row_data.append(cell.text)
            table_data.append(row_data)

    return table_data, images

table_data, images = read_table_from_docx('template.docx')
print(table_data)

# 另存docx图片到本地
for i, image_data in enumerate(images):
    # 拼接 存储图片 绝对路径
    image_name = f"expert_{int(time.time() * 1000)}.jpg"
    with open(os.path.join(image_save_path, image_name), "wb") as f:
        f.write(image_data)

拿取复选框选项

关于docx复选框,在这次项目中遇到了一种独特的复选框样式,这种样式并不是通过wps里的【复选框内容控件】创建的,让我一时没办法找到方向。

这是正常用wps添加的复选框方式

很明显,和我的目标不太一样

二者都没办法通过【python-docx基础操作】拿到,因此我只能继续刨坑,终于如【前言】所述,我不得已去模块github的评论区里找到了线索------直接以xml的形式剖析docx文件,并获取复选框选项。

这里为了节约文本资源(太懒了),直接上代码吧!

python 复制代码
from docx import Document

document = Document('template1.docx')
tables = document.tables
content = []
for table in tables:
    for row in table.rows:
        for cell in row.cells:
            for paragraph in cell.paragraphs:
                p = paragraph._element

                # 打印docx的xml内容形式
                # print(p.xml)

                # 拿取所有<w14:checkbox>标签的匹配xml数据
                checkBoxes = p.xpath('.//w14:checkbox')
                if checkBoxes:
                    # 解析<w14:checkbox>内部的内容
                    for checkBox in checkBoxes:
                        # 尝试匹配xml中的<w14:val>对象,也就是上面wps自建的复选框
                        checked_state = checkBox.xpath('.//w14:checked/@w14:val', namespaces={'w14':'http://schemas.microsoft.com/office/word/2010/wordml'})
                        if checked_state:
                            checked_value = checked_state[0]  # 获取第一个匹配的属性值
                            print(paragraph.text, "Checked value:", checked_value)
                            break

                # 这是原模板的复选框选项拿取方案
                # checkBoxes = p.xpath('.//w:r')
                # if checkBoxes:
                #     for checkBox in checkBoxes:
                #         checked_state = checkBox.xpath('.//w:sym/@w:char')
                #         if checked_state:
                #             checked_value = checked_state[0]  # 获取第一个匹配的属性值
                #             print(paragraph.text, "Checked value:", checked_value)
                #             break

这是我的结果【1是选择,0是未选择】

这是docx解析后的xml内容,请自行体会代码与它的联系吧

python 复制代码
<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:jc w:val="both"/>
    <w:rPr>
      <w:rFonts w:hint="eastAsia" w:ascii="仿宋_GB2312" w:hAnsi="仿宋_GB2312" w:eastAsia="仿宋_GB2312" w:cs="仿宋_GB2312"/>
      <w:u w:val="single"/>
      <w:lang w:val="en-US" w:eastAsia="zh-CN"/>
    </w:rPr>
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:hint="default" w:ascii="仿宋_GB2312" w:hAnsi="仿宋_GB2312" w:eastAsia="仿宋_GB2312" w:cs="仿宋_GB2312"/>
      <w:sz w:val="21"/>
      <w:szCs w:val="21"/>
    </w:rPr>
    <w:sym w:font="Wingdings" w:char="00A8"/>
  </w:r>
  <w:r>
    <w:rPr>
      <w:rFonts w:hint="eastAsia" w:ascii="仿宋_GB2312" w:hAnsi="仿宋_GB2312" w:eastAsia="仿宋_GB2312" w:cs="仿宋_GB2312"/>
      <w:sz w:val="21"/>
      <w:szCs w:val="21"/>
      <w:lang w:val="en-US" w:eastAsia="zh-CN"/>
    </w:rPr>
    <w:t>这是选项一</w:t>
  </w:r>
  <w:bookmarkStart w:id="0" w:name="_GoBack"/>
  <w:bookmarkEnd w:id="0"/>
  <w:sdt>
    <w:sdtPr>
      <w:rPr>
        <w:rFonts w:hint="eastAsia" w:ascii="仿宋_GB2312" w:hAnsi="仿宋_GB2312" w:eastAsia="仿宋_GB2312" w:cs="仿宋_GB2312"/>
        <w:color w:val="auto"/>
        <w:kern w:val="2"/>
        <w:sz w:val="21"/>
        <w:szCs w:val="24"/>
        <w:lang w:val="en-US" w:eastAsia="zh-CN" w:bidi="ar-SA"/>
      </w:rPr>
      <w:id w:val="147457823"/>
      <w14:checkbox>
        <w14:checked w14:val="1"/>
        <w14:checkedState w14:val="2612" w14:font="MS Gothic"/>
        <w14:uncheckedState w14:val="2610" w14:font="MS Gothic"/>
      </w14:checkbox>
    </w:sdtPr>
    <w:sdtEndPr>
      <w:rPr>
        <w:rFonts w:hint="eastAsia" w:ascii="仿宋_GB2312" w:hAnsi="仿宋_GB2312" w:eastAsia="仿宋_GB2312" w:cs="仿宋_GB2312"/>
        <w:color w:val="auto"/>
        <w:kern w:val="2"/>
        <w:sz w:val="21"/>
        <w:szCs w:val="24"/>
        <w:lang w:val="en-US" w:eastAsia="zh-CN" w:bidi="ar-SA"/>
      </w:rPr>
    </w:sdtEndPr>
    <w:sdtContent>
      <w:r>
        <w:rPr>
          <w:rFonts w:ascii="MS Gothic" w:hAnsi="MS Gothic" w:eastAsia="宋体" w:cs="Times New Roman"/>
          <w:color w:val="auto"/>
          <w:kern w:val="2"/>
          <w:sz w:val="21"/>
          <w:szCs w:val="24"/>
          <w:lang w:val="en-US" w:eastAsia="zh-CN" w:bidi="ar-SA"/>
        </w:rPr>
        <w:t>☒</w:t>
      </w:r>
    </w:sdtContent>
  </w:sdt>
  <w:r>
    <w:rPr>
      <w:rFonts w:hint="eastAsia" w:ascii="仿宋_GB2312" w:hAnsi="仿宋_GB2312" w:eastAsia="仿宋_GB2312" w:cs="仿宋_GB2312"/>
      <w:i w:val="0"/>
      <w:iCs w:val="0"/>
      <w:color w:val="000000"/>
      <w:kern w:val="0"/>
      <w:sz w:val="21"/>
      <w:szCs w:val="21"/>
      <w:u w:val="none"/>
      <w:bdr w:val="single" w:color="000000" w:sz="4" w:space="0"/>
      <w:lang w:val="en-US" w:eastAsia="zh-CN" w:bidi="ar"/>
    </w:rPr>
    <w:drawing>
      <wp:anchor distT="0" distB="0" distL="114300" distR="114300" simplePos="0" relativeHeight="251659264" behindDoc="0" locked="0" layoutInCell="1" allowOverlap="1">
        <wp:simplePos x="0" y="0"/>
        <wp:positionH relativeFrom="column">
          <wp:posOffset>0</wp:posOffset>
        </wp:positionH>
        <wp:positionV relativeFrom="paragraph">
          <wp:posOffset>0</wp:posOffset>
        </wp:positionV>
        <wp:extent cx="18415" cy="19685"/>
        <wp:effectExtent l="0" t="0" r="0" b="0"/>
        <wp:wrapNone/>
        <wp:docPr id="1" name="图片_2"/>
        <wp:cNvGraphicFramePr/>
        <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
          <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
            <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
              <pic:nvPicPr>
                <pic:cNvPr id="1" name="图片_2"/>
                <pic:cNvPicPr/>
              </pic:nvPicPr>
              <pic:blipFill>
                <a:blip r:embed="rId4"/>
                <a:stretch>
                  <a:fillRect/>
                </a:stretch>
              </pic:blipFill>
              <pic:spPr>
                <a:xfrm>
                  <a:off x="0" y="0"/>
                  <a:ext cx="18415" cy="19685"/>
                </a:xfrm>
                <a:prstGeom prst="rect">
                  <a:avLst/>
                </a:prstGeom>
                <a:noFill/>
                <a:ln>
                  <a:noFill/>
                </a:ln>
              </pic:spPr>
            </pic:pic>
          </a:graphicData>
        </a:graphic>
      </wp:anchor>
    </w:drawing>
  </w:r>
</w:p>
相关推荐
魔道不误砍柴功36 分钟前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
_.Switch1 小时前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops
测开小菜鸟2 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
萧鼎3 小时前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
学地理的小胖砸3 小时前
【一些关于Python的信息和帮助】
开发语言·python
疯一样的码农3 小时前
Python 继承、多态、封装、抽象
开发语言·python
Python大数据分析@4 小时前
python操作CSV和excel,如何来做?
开发语言·python·excel
黑叶白树4 小时前
简单的签到程序 python笔记
笔记·python
Shy9604184 小时前
Bert完形填空
python·深度学习·bert
Jason-河山4 小时前
【自动化更新,让商品信息跳舞】——利用API返回值的幽默编程之旅
运维·自动化