Python读取wps中的DISPIMG图片格式

news2024/11/23 3:42:55

需求:
读出excel的图片内容,这放在微软三件套是很容易的,但是由于wps的固有格式,会出现奇怪的问题,只能读出:类似于 =DISPIMG(“ID_2B83F9717AE1XXXX920xxxx644C80DB1”,1) 【该DISPIMG函数只有wps才拥有】

本文参考该多个作者的思路:
https://blog.csdn.net/maudboy/article/details/133145278 java读取Excel,(支持WPS嵌入式图片)
以及该github issus:
https://github.com/qax-os/excelize/issues/664 How to read pictures embedded in cells
当然该项目两个个月前用go 来读取wps中的图片格式:https://github.com/qax-os/excelize excelize

希望大家多多关注

github前几名的excel读取,python在后几名【这让我挺吃惊的,作为第一语言,支持库这么多,竟然没有对wps图片解析的python代码】,第一是Go写的。
在这里插入图片描述

首先明确,xlsx就是一个zip包,否则里面的图片根本没法读取。
下面是该代码的思路:

# xlsx本质就是zip,其解压文件夹为_rels xl docProps
# 代码思路:首先读取excel表,并提取DISPIMG_id列,保存在image_list中
# 根据xl/cellimages.xml 提取出rId与DISPIMG_id的关系,组成一个map1,{"DISPIMG_id":"rId"}
# 再根据xl/_rels/cellimages.xml.rels,根据rId 与 imgae_path的关系,组成一个map2 {"rId":"image_path"}
# 根据map1与map2对应的关系,组成一个新map3 : {"DISPIMG_id": "image_path"} 得出对应的关系
# 输出图片,根据xl/{image_path} 输出图片并把图片重命名为DISPIMG_id.png

代码思路,该代码可以优化,主要多次读取文件并且多次调用map了,不过处理几百条数据还是绰绰有余的。

import zipfile
import os
import xml.etree.ElementTree as ET
import openpyxl



image_list = []  # 存放从excel读出的DISPIMG_id


def read_excel_data(filename_path):
    # 加载 Excel 文件
    workbook = openpyxl.load_workbook(filename_path, data_only=False)
    sheet = workbook.active

    # 遍历数据和公式
    data = [] # data就是文本信息
    for row in sheet.iter_rows(min_row=1, values_only=False):
        row_data = []
        for cell in row:
            if cell.value and isinstance(cell.value, str) and '=_xlfn.DISPIMG(' in cell.value:
                # 提取嵌入的图片 ID
                formula = cell.value
                start = formula.find('"') + 1
                end = formula.find('"', start)
                image_id = formula[start:end]
                row_data.append(f"{image_id}")
                image_list.append(image_id)
                # print(image_id)
            else:
                # 其他数据直接添加
                row_data.append(cell.value)
        data.append(row_data)
    return data


def get_xml_id_image_map(xlsx_file_path):
    # 打开 XLSX 文件
    with zipfile.ZipFile(xlsx_file_path, 'r') as zfile:
        # 直接读取 XML 文件内容
        with zfile.open('xl/cellimages.xml') as file:
            xml_content = file.read()
        with zfile.open('xl/_rels/cellimages.xml.rels') as file:
            relxml_content = file.read()

    # 将读取的内容转换为 XML 树
    root = ET.fromstring(xml_content)

    # 初始化映射字典
    name_to_embed_map = {}

    # 命名空间
    namespaces = {
        'xdr': 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing',
        'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'
    }

    # 遍历所有 pic 元素
    for pic in root.findall('.//xdr:pic', namespaces=namespaces):
        name = pic.find('.//xdr:cNvPr', namespaces=namespaces).attrib['name']
        embed = pic.find('.//a:blip', namespaces=namespaces).attrib[
            '{http://schemas.openxmlformats.org/officeDocument/2006/relationships}embed']
        name_to_embed_map[name] = embed

    # 打印结果
    # print(name_to_embed_map)

    root1 = ET.fromstring(relxml_content)

    # 命名空间字典,根据 XML 中定义的命名空间进行设置
    namespaces = {'r': 'http://schemas.openxmlformats.org/package/2006/relationships'}

    # 创建 ID 和 Target 的映射
    id_target_map = {child.attrib['Id']: child.attrib.get('Target', 'No Target Found') for child in
                     root1.findall('.//r:Relationship', namespaces=namespaces)}

    # print(id_target_map)

    # 使用字典推导构建新的映射表
    name_to_target_map = {name: id_target_map[embed] for name, embed in name_to_embed_map.items() if
                          embed in id_target_map}
    return name_to_target_map


def output_id_image(xlsx_file_path):
    read_excel_data(xlsx_file_path)
    name_to_target_map = get_xml_id_image_map(xlsx_file_path)
    # 构建id_image_对
    new_map = {key: name_to_target_map.get(key) for key in image_list if key in name_to_target_map}
    print(new_map)
    output_directory = './images' #保存的图片目录
    # 打开xlsx文件(即Zip文件)
    with zipfile.ZipFile(xlsx_file_path, 'r') as zfile:
        for key, image_path in new_map.items():
            # 构建实际的图片路径
            actual_image_path = f'xl/{image_path}'  # 假设图片在'xl/media/'目录下
            if actual_image_path in zfile.namelist():
                # 读取图片内容
                with zfile.open(actual_image_path) as image_file:
                    image_content = image_file.read()
                    # 保存图片到新的文件,使用key作为文件名
                    new_file_path = os.path.join(output_directory, f"{key}.png")
                    with open(new_file_path, 'wb') as new_file:
                        new_file.write(image_content)
            else:
                print(f"File {actual_image_path} not found in the archive.")

if __name__ == '__main__':
    output_id_image('/home/jacin/Downloads/英式货表.xlsx')
    # 输出的图片名字就是 xlsx表中的列的DISPIMG_id,保存在images文件夹下
    # 并会在控制台输出一个字典,key是DISPIMG_id,value是图片的路径,例如:{'ID_BE7EFF591B6C4978XXXXXX5266': 'media/image118.png'}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1827229.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

阿里新发布的UniAnimate现高效人像动画生成;在ComfyUI中使用Stable 3模型;音频版的gpt2o;将 PDF 文档转换为音频播客

✨ 1: UniAnimate 阿里新发布的UniAnimate通过统一的视频扩散模型,实现高效人像动画生成,支持长视频生成 UniAnimate 是一种专注于一致性人像动画生成的统一视频扩散模型。该模型通过映射参考图像、姿势指导和噪声视频到一个共同特征空间,实…

docker安装nginx并且加上映射

随机启动nginx,方便复制配置文件 docker run -p 80:80 --name nginx -d nginx:1.10将容器内的配置文件拷贝到当前目录 docker container cp nginx:/etc/nginx .别忘了后面的点 修改文件名称: mv nginx conf 把这个 conf 移动到/mydata/nginx 下 终止原…

金融行业运维实践案例

确保金融系统的稳定运行和数据安全,业务对可靠性、安全性和合规性具有超高的要求。保障IT系统持续高效稳定运维,是金融行业运维的核心诉求。 在实践应用中,有以下方面问题需要解决。 1、数据分散。业务发展快速,数量多&#xff…

IDEA创建lib目录,导入jar

IDEA创建lib目录,导入jar lib第一种创建方法: 当发现项目没有lib目录时,File>>>Project Structure 打开Artifacts目录 lib第二种创建方法: 按需选择需要的jar包或者全选即可 lib第三种创建方法:

基于51单片机的电子秤的设计

第一章 功能说明 本设计系统以单片机AT89S52为控制核心,实现电子秤的基本控制功能。在设计系统时,为了更好地采用模块化设计法,分步设计了各个单元功能模块。 系统的硬件部分包括最小系统部分、数据采集部分、人机交互界面和系统电源四大部分。最小系统部分主要包括AT89S52和…

【刷力扣】23. 合并 K 个升序链表(dummy节点技巧 + 分治思维 + 优先队列)

目录 一、合并升序链表问题二、题目:[21. 合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/description/)1、掌握dummy节点的技巧 三、题目:[23. 合并 K 个升序链表](https://leetcode.cn/problems/merge-k-sorted-lists/descri…

iOS18新增通话录音和应用锁!附升级教程及内置壁纸

一觉睡醒,iOS18终于是揭开面纱了,而且已经有测试版给开发者使用了。 不过还是建议咱们普通用户不要轻易尝试,而且在升级之前一定要用iMazing做个备份,以免测试系统出现问题,丢失数据。 这次WWDC2024与之前爆料完全一样…

宝藏速成秘籍(7)堆排序法

一、前言 1.1、概念 堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法 。堆是一个近似 完全二叉树 的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。 1.2、排…

在VS Code中快速生成Vue模板的技巧

配置vue.json: { "Print to console": {"prefix": "vue","body": ["<template>"," <div class\"\">\n"," </div>","</template>\n","<scri…

[DDR4] 总目录 学习路线

依公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 传送门: 总目录 目录 基础篇 1-1 DDR4 发展历史 1-2 DDR4 和 DDR3 差异与优势 1-3 DDR4 内部结构 1-4 DDR4 工作原理 协议篇 2-1 DDR4 引脚 设计篇 实践篇 进阶篇 学习路线&#xff1a; 了解DDR4的基本知识…

AI赋能软件测试

AI赋能软件测试 AI赋能软件测试软件测试分类软件质量模型:用来衡量软件质量的维度AI赋能软件测试 随着AI时代的到来,如何轻松掌握软件测试新趋势,将AI技术应用于软件测试行业,提高测试速度与测试效率~~ 传智星云AI助手:https://nebula.itcast.cn tips:各种AI工具应有尽有…

一款经典BUCK DCDC降压芯片TPS5430适合24V转5V转12V及其电路图

前言&#xff1a; TPS5430封装和丝印 经典老款DCDC&#xff0c;适合24V转5V、24V转12V及其它24V转其它电压降压使用&#xff0c;对于输入电压较低&#xff0c;如输入12V电压的&#xff0c;不推荐使用该芯片&#xff0c;该芯片出现时间较长&#xff0c;且非同步整流芯片&#xf…

【YashanDB知识库】PHP使用ODBC使用数据库绑定参数功能异常

【问题分类】驱动使用 【关键字】ODBC、驱动使用、PHP 【问题描述】 PHP使用PDO_ODBC连接yashan数据库&#xff0c;使用绑定参数获取数据时&#xff0c;客户现场出现报错 本地复现未出现异常报错&#xff0c;但是无法正确获取数据。 【问题原因分析】开启ODBC报错日志后&am…

【计算机网络仿真实验-实验2.6】带交换机的RIP路由协议

实验2.6 带交换机的rip路由协议 1. 实验拓扑图 2. 实验前查看是否能ping通 不能 3. 三层交换机配置 switch# configure terminal switch(config)# hostname s5750 !将交换机更名为S5750 S5750# configure terminal S5750(config)#vlan 10 S5750(config-vlan)#exit S57…

【elementui源码解析】如何实现自动渲染md文档-第四篇

目录 1.前言 2.md-loader - index.js 1&#xff09;md.render() 2&#xff09;定义变量 3&#xff09;while stripTemplate stripScript genInlineComponentText 4&#xff09;pageScript 5&#xff09;return 6&#xff09;demo-block 3.总结 所有章节&#x…

React@16.x(29)useRef

目录 1&#xff0c;介绍2&#xff0c;和 React.createRef() 的区别3&#xff0c;计时器的问题 目前来说&#xff0c;因为函数组件每次触发更新时&#xff0c;都会重新运行。无法像类组件一样让一些内容保持不变。 所以才出现了各种 HOOK 函数&#xff1a;useState&#xff0c;u…

CCAA质量管理【学习笔记】​​ 备考知识点笔记(二)

第三节 GB/T19001-2016 标准正文 本节为ISO9001:2015 标准条款的正文内容&#xff0c;各条款中的术语参照上节内容理解时&#xff0c;会很轻松。本节不再一一对各条款讲解。 引 言 0.1 总 则 采用质量管理体系是组织的一项战略决策&#xff0c;能够帮助其提高整体绩效…

C++11移动语义

前言 之前我们已经知道了在类里开辟数组后&#xff0c;每一次传值返回和拷贝是&#xff0c;都会生成一个临时变量 class Arr { public://构造Arr() {/*具体实现*/ };//拷贝Arr(const Arr& ar) {/*具体实现*/ };//重载Arr operator(const Arr& ar) { /*具体实现*/Arr …

北方工业大学24计算机考研情况,学硕专硕都是国家线复试!

北方工业大学&#xff08;North China University of Technology&#xff0c;NCUT&#xff09;&#xff0c;简称“北方工大”&#xff0c;位于北京市&#xff0c;为一所以工为主、文理兼融&#xff0c;具有学士、硕士、博士培养层次的多科性高等学府&#xff0c;是中华人民共和…

自动化数据驱动?最全接口自动化测试yaml数据驱动实战

前言 我们在做自动化测试的时候&#xff0c;通常会把配置信息和测试数据存储到特定的文件中&#xff0c;以实现数据和脚本的分离&#xff0c;从而提高代码的易读性和可维护性&#xff0c;便于后期优化。 而配置文件的形式更是多种多样&#xff0c;比如&#xff1a;ini、yaml、…