当前位置: 首页 > article >正文

解决使用python提取word文档中所有的图片时图片丢失的问题

python解析word文档,提取文档中所有的图片并保存,并将原图位置用占位符替换。

问题描述

利用python-dox库解析word文档,并提取里面的所有图片时发现会出现一摸一样的图片只解析一次,导致图片丢失,数量不对的情况。

解决方法

通过例如 lxml 或直接解析 Word 的结构解决 例如,读取每个图片引用的具体关系

  1. 解析 Word 文档的内容:我们需要读取 document.xml 来找到所有的 <w:drawing> 元素。
  2. 解析关系文件:在 word/_rels/document.xml.rels 文件中,每张图片都有一个关系定义,你需要读取这个文件来找到图像的实际存储路径。
  3. 提取和保存图像:最后,从 Word 的 ZIP包里把真正的图像提取出来保存到本地。

代码

import os
from datetime import datetime
from docx import Document
from docx.oxml.ns import qn
import zipfile
import os
from zipfile import ZipFile
from lxml import etree

def extract_images_and_replace(docx_path, output_docx_path, images_dir):
    # 打开 docx 文件作为 Zip

    base_filename=os.path.splitext(os.path.basename(docx_path))[0]
    with ZipFile(docx_path, 'r') as docx:
        # 读取 word/document.xml 文件
        document_xml = docx.read('word/document.xml')
        root = etree.XML(document_xml)
        # 读取 word/_rels/document.xml.rels 文件
        rels_xml = docx.read('word/_rels/document.xml.rels')
        rels_root = etree.XML(rels_xml)
        # 查找所有的 <w:drawing> 元素
        drawing_elements = root.findall('.//{http://schemas.openxmlformats.org/wordprocessingml/2006/main}drawing')
        # 创建输出目录
        os.makedirs(images_dir, exist_ok=True)
        # 查找并保存所有图片
        image_id=0
        placelist=[]
        for i, drawing in enumerate(drawing_elements):
            # 获取 <a:blip> 的 r:embed 属性
            blip_element = drawing.find('.//{http://schemas.openxmlformats.org/drawingml/2006/main}blip')
            if blip_element is not None:
                embed_attr = blip_element.get('{http://schemas.openxmlformats.org/officeDocument/2006/relationships}embed')
                if embed_attr:
                    # 查找图像在 rels 中的路径
                    relationship = rels_root.find(f".//{{http://schemas.openxmlformats.org/package/2006/relationships}}Relationship[@Id='{embed_attr}']")
                    if relationship is not None:
                        timestamp = datetime.now().timestamp()
                        target = relationship.get('Target')
                        image_path = os.path.join('word', target)
                        placeholder = f"{base_filename}_{timestamp}<unused{image_id}>"
                        placelist.append(placeholder)
                        # 提取并保存图像
                        with docx.open(image_path) as image_file:
                            image_data = image_file.read()
                            image_ext = os.path.splitext(image_path)[1]
                            # 保存图片到指定目录
                            image_filename = os.path.join(images_dir, f"{placeholder}.png")
                            with open(image_filename, 'wb') as out_file:
                                out_file.write(image_data)
                            print(f'Image saved: {image_filename}')
                            image_id+=1
    print(len(placelist))
    # 替换文档中对应的图片为占位符
    i=0
     # 遍历所有段落及图片
    doc = Document(docx_path)
    for paragraph in doc.paragraphs:
        for run in paragraph.runs:
            # try:
            if 'graphicData' in run._element.xml:  # 搜索图片标记
                # 删除图片并插入占位符文字
                inline = run._element.xpath('.//a:graphic')[0]
                inline.getparent().remove(inline)
                run.text = placelist[i]
                i+=1
            # except:
            #     break
    # 保存修改后的 Word 文档
    doc.save(output_docx_path)
    print(f"提取了 {image_id} 张图片并用占位符替换。")
    print(f"图片保存在:{images_dir}")
    print(f"修改后的 Word 文件保存在:{output_docx_path}")

# 示例调用
docx_path = "/data/xxxxx/ZHX财务管理系统.docx"  # 输入的 Word 文档
output_docx_path = "/data/xxxxx/ZHX财务管理系统--.docx"  # 替换图片后保存的 Word 文档
images_dir = "/data/xxxxx/样例图集/"  # 提取图片保存的目录
extract_images_and_replace(docx_path, output_docx_path, images_dir)

http://www.kler.cn/a/535094.html

相关文章:

  • 八大排序算法细讲
  • PCA9685舵机控制板使用
  • 动手学图神经网络(11):使用MovieLens数据集进行链路预测的实践
  • IDEA使用Auto-dev+DeepSeek 10分钟快速集成,让java开发起飞
  • 如何理解多态,以及由此引出的抽象类和纯虚函数
  • 仿LISP运算
  • MMU工作原理
  • linux的基础入门2
  • 3步打造C# API安全密盾
  • DS目前曲线代替的网站汇总
  • word数学模式公式显示不全
  • 【hudi】基于hive2.1.1的编译hudi-1.0.0源码
  • Hangfire.NET:.NET任务调度
  • ByConity二进制集群版部署
  • 康谋方案 | BEV感知技术:多相机数据采集与高精度时间同步方案
  • DeepSeek-R1 本地电脑部署 Windows系统 【轻松简易】
  • ASP.NET Core标识框架Identity
  • Spring Boot框架知识总结(超详细)
  • ORACLE用regexp_sbustr函数截取json值的sql。
  • 蓝桥杯嵌入式备赛(三)—— LED +按键 + LCD
  • 虚拟机搭建---K8S环境
  • GoFrame 微服务脚手架模块 (v2.8.x)
  • LeetCode 72.编辑距离
  • UE5 蓝图学习计划 - Day 14:搭建基础游戏场景
  • MySQL InnoDB引擎 高度为3的B+树,可以存储的数据量
  • 高级java每日一道面试题-2025年01月30日-框架篇[SpringBoot篇]-如何理解 Spring Boot 配置加载顺序 ?