从excel中提取嵌入式图片的解决方法

1  发现问题

我的excel中有浮动图片和嵌入式图片,但是openpyxl的_image对象只提取到了浮动图片,通过阅读其源码发现,这是因为openpyxl只解析了drawing文件导致的,所以确定需要自己解析

2  解决思路

1、解析出media资源

2、解析出xml,这可以得到资源的rNvpr-rId-image target的关系

3、从xlrd或openpyxl中得到单元格cNvpr,定位到图片

3  解析xlsx

先把xlsx解压出来,得到的文件如下,其中xl文件夹是我们需要的

我分析了里面的所有文件,发现这两个文件存储了嵌入式图片的关键信息

  • xl/cellimages.xml
  • xl/_rels/cellimages.xml

打开这两个文件看看,到底存储了什么?

3.1  xl/cellimages.xml

 

有效信息在cellImage对象中

  • cellImage.pic.nvPicPr.cNvPr.name:记录了函数名
  • cellImage.pic.blipFill.blip.embed:记录了rId

记录这个关系,并建立映射关系 { ID_xxx: rId }

3.2  xl/_rels/cellimages.xml

 

有效信息在Relationship对象中

  • Relationship.id:文件rId
  • Relationship.target:图片地址

建立这个映射关系 { rId: target }

到这一步我们已经可以从函数名定位到图片资源了,剩下一步建立excel单元格和图片的关系,接下来解析excel文件

{ ID_xxx: rId } + { rId: target } = ID_xxx -> target

4  代码实现

接下来简单的代码实现,有问题可以评论区留言,看到会回复

此实现基于openpyxl

from xml.etree.ElementTree import fromstring
from io import BytesIO
from zipfile import ZipFilefrom openpyxl import load_workbook
from openpyxl.packaging.relationship import get_rels_path, get_dependents
from openpyxl.xml.constants import SHEET_DRAWING_NS, REL_NS, IMAGE_NS
from openpyxl.drawing.image import Image, PILImagedef parse_element(element):"""将XML解析为 {ID_XXX: rId}:param element:<etc:cellImage><xdr:pic><xdr:nvPicPr><xdr:cNvPr id="2" name="ID_CBD7CEBC94B44923A5B447F3F21C1995" descr="upload_post_object_v2_167528160"/><xdr:cNvPicPr/></xdr:nvPicPr><xdr:blipFill><a:blip r:embed="rId1"/><a:stretch><a:fillRect/></a:stretch></xdr:blipFill><xdr:spPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="9144000" cy="4796155"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></xdr:spPr></xdr:pic></etc:cellImage>:return:"""data = {}xdr_namespace = "{%s}" % SHEET_DRAWING_NStargets = level_order_traversal(element, xdr_namespace + "nvPicPr")for target in targets:# 是一个cellimagecNvPr = embed = ""for child in target:if child.tag == xdr_namespace + "nvPicPr":cNvPr = child[0].attrib["name"]elif child.tag == xdr_namespace + "blipFill":_rel_embed = "{%s}embed" % REL_NSembed = child[0].attrib[_rel_embed]if cNvPr:data[cNvPr] = embedreturn datadef level_order_traversal(root, flag):"""层次遍历,查找目标节点"""queue = [root]targets = []while queue:node = queue.pop(0)children = [child.tag for child in node]if flag in children:targets.append(node)continuefor child in node:queue.append(child)return targetsdef handle_images(deps, archive) -> []:"""将图片二进制内容封装为Image对象"""images = []if not PILImage:  # Pillow not installed, drop imagesreturn imagesfor dep in deps:if dep.Type != IMAGE_NS:msg = "{0} image format is not supported so the image is being dropped".format(dep.Type)print(msg)continuetry:image_io = archive.read(dep.target)image = Image(BytesIO(image_io))except OSError:msg = "The image {0} will be removed because it cannot be read".format(dep.target)print(msg)continueif image.format.upper() == "WMF":  # cannot savemsg = "{0} image format is not supported so the image is being dropped".format(image.format)print(msg)continueimage.embed = dep.id         # 文件rIdimage.target = dep.target    # 文件地址images.append(image)return imagesdef main():CELLIMAGE_PATH = "xl/cellimages.xml"PARSE_FILE_PATH = 'C:/Users/user/Downloads/TCI验收问题.xlsx'archive = ZipFile(PARSE_FILE_PATH, "r")wb = load_workbook(PARSE_FILE_PATH)src = archive.read(CELLIMAGE_PATH)                              # 打开cellImage.xml文件deps = get_dependents(archive, get_rels_path(CELLIMAGE_PATH))   # 解析cellImage.xml._rel文件image_rels = handle_images(deps=deps.Relationship, archive=archive)node = fromstring(src)cellimages_xml = parse_element(node)cellimages_rel = {}for image in image_rels:cellimages_rel[image.embed] = imagefor cnvpr, embed in cellimages_xml.items():cellimages_xml[cnvpr] = cellimages_rel.get(embed)# df = pd.read_excel(PARSE_FILE_PATH)# df["行号"] = df.index + 2# image_mappings = ParserXLSXEmbed(wb=wb, df=df).extract_images(start_from=max(0, 1) + 1)# image_mappings.update(cellimages_xml)archive.close()  # 关闭压缩文件对象,防止内存泄漏print(cellimages_xml)if __name__ == '__main__':main()

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

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

相关文章

React 路由使用-详细介绍

路由初使用 抽象路由模块 src\page\Article\index.js const Article () > {return (<div><p>文章页</p></div>); };export default Article;src\router\index.js // 导入页面 import Article from "../page/Article"; import Login fr…

MySQL第六七弹,自连接等复杂查询,索引部分知识

一、&#x1f49b; 自连接&#xff1a;自己和自己笛卡尔积&#xff08;奇淫巧技&#xff0c;特殊场景很牛逼&#xff09; SQL&#xff1a;编写条件都是列和列之间的比较&#xff0c;但是SQL无法进行&#xff0c;行与行之间的比较。 如&#xff1a;显示所有java比计算机原理高的…

服务端高并发分布式结构演进之路

目录 一、常见概念 1.1基本概念 二、架构演进 2.1单机架构 2.2应用数据分离架构 2.3应用服务集群架构 2.4读写分离 / 主从分离架构 2.5引入缓存 —— 冷热分离架构 2.6垂直分库 2.7业务拆分 —— 微服务 一、常见概念 1.1基本概念 应用&#xff08;Application&am…

2023华数杯数学建模C题思路分析 - 母亲身心健康对婴儿成长的影响

# 1 赛题 C 题 母亲身心健康对婴儿成长的影响 母亲是婴儿生命中最重要的人之一&#xff0c;她不仅为婴儿提供营养物质和身体保护&#xff0c; 还为婴儿提供情感支持和安全感。母亲心理健康状态的不良状况&#xff0c;如抑郁、焦虑、 压力等&#xff0c;可能会对婴儿的认知、情…

硬件串口通信协议学习(UART、IIC、SPI、CAN)

0.前言 学习资料&#xff1a;江协科技的个人空间-江协科技个人主页-哔哩哔哩视频 通信的目的&#xff1a;将一个设备的数据传送到另一个设备&#xff0c;扩展硬件系统通信协议&#xff1a;制定通信的规则&#xff0c;通信双方按照协议规则进行数据收发 全双工&#xff1a;通信…

腾讯云COS+PicGO+截图工具+Obsidian+Typora+蚁小二:打造丝滑稳定的Markdown写作和分发环境

目录 背景 工具说明 腾讯云COS PicGO图片上传工具 截图工具 Obsidian Typora 蚁小二 首次配置完整演示步骤 腾讯云COS PicGO图片上传工具 截图工具 Obsidian Typora 蚁小二 使用总结&#xff08;简单又丝滑的编辑步骤&#xff09; 背景 很久很久以前&#xff…

【蓝图】p47下车减速功能

p47下车减速功能 p47下车减速功能加速功能下车减速功能 p47下车减速功能 加速功能 上图是ue自带的加速功能&#xff0c;检测到按w时输入轴会传1给设置油门输入&#xff0c;就会加速 所以&#xff0c;减速也可以通过蓝图反方向制作 下车减速功能 打开Sedan蓝图类的上下车图表…

Java网络编程

目录 1.网络编程 2.Echo模型&#xff08;服务器与客户端实现通信&#xff09; 3.BIO处理模型(实现多用户访问同个服务器) 4.UDP程序 1.网络编程 有两种通信模型 C/S(Client/Server)基于客户端和服务器端&#xff0c;实现代码时候需要实现客户端与服务器端 B/S(Browser/S…

QtWebApp开发https服务器,完成客户端与服务器基于ssl的双向认证

引言&#xff1a;所谓http协议&#xff0c;本质上也是基于TCP/IP上服务器与客户端请求和应答的标准&#xff0c;web开发中常用的http server有apache和nginx。Qt程序作为http client可以使用QNetworkAccessManager很方便的进行http相关的操作。Qt本身并没有http server相关的库…

使用Git在GitHub上部署静态页面

在GitHub中&#xff0c;我们可以将自己的静态页面部署到GitHub中&#xff0c;它会给我们提供一个地址使得我们的页面变成一个真正的网站&#xff0c;可以供用户访问。 一、在GitHub下创建仓库 二、将项目部署到GitHub上 1. 初始化Git仓库 2. 提交代码 3. 关联远程仓库 在Gi…

【java安全】原生反序列化利用链JDK7u21

文章目录 【java安全】原生反序列化利用链JDK7u21前言原理equalsImpl()如何调用equalsImpl()&#xff1f;HashSet通过反序列化间接执行equals()方法如何使hash相等&#xff1f; 思路整理POCGadget为什么在HashSet#add()前要将HashMap的value设为其他值&#xff1f; 【java安全】…

WSL1升级为WSL2

首先需要启用组件 使用管理员打开Powershell并运行 Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform启用后会要求重启计算机 从https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi获取WSL2 Linux内核更新包&#xff0c;…

HTML 是什么?它的全称是什么?

聚沙成塔每天进步一点点 专栏简介HTML是什么&#xff1f;HTML的全称是什么&#xff1f;写在最后 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对We…

ad+硬件每日学习十个知识点(16)23.7.27 (总线保持、lin报文、逻辑器件手册解读)

文章目录 1.总线保持是怎么实现的&#xff1f;有什么需要注意的&#xff08;驱动电流和电阻&#xff09;&#xff1f;2.LIN报文3.芯片datasheet的features、applications、description看完&#xff0c;应该能大致判断逻辑器件能否满足我们的要求。4.什么是逻辑器件的传输延时&a…

WiFi无线组网温湿度实时监测系统

近年来随着我国电子技术和无线通信技术的快速发展&#xff0c;远距离数据采集传输被应用到众多领域&#xff0c;由于事关环境安全和生命健康&#xff0c;受到了各行各界的关注。在温湿度监测中&#xff0c;目前采用的通信技术主要是4G、WiFi、以太网、LoRa等&#xff0c;今天&a…

docker删除容器(步骤详解)

要在Docker中删除容器&#xff0c;需要使用命令docker rm。 下面是详细步骤&#xff1a; 1. 首先&#xff0c;使用docker ps命令查看当前正在运行的容器。这个命令会列出所有正在运行的容器的ID、名称、状态等信息。 如果没有正在运行的容器可以通过docker ps -a 查看当前所…

[Qt]FrameLessWindow实现调整大小、移动弹窗并具有Aero效果

说明 我们知道QWidget等设置了this->setWindowFlags(Qt::FramelessWindowHint);后无法移动和调整大小&#xff0c;但实际项目中是需要窗口能够调整大小的。所以以实现FrameLess弹窗调整大小及移动弹窗需求&#xff0c;并且在Windows 10上有Aero效果。 先看一下效果&#xf…

zabbix监控mysql容器主从同步状态并告警钉钉/企业微信

前言&#xff1a;被监控的主机已经安装和配置mysql主从同步&#xff0c;和zabbix-agent插件。 mysql创建主从同步&#xff1a;http://t.csdn.cn/P4MYq centos安装zabbix-agent2&#xff1a;http://t.csdn.cn/fx74i mysql主从同步&#xff0c;主要监控这2个参数指标&#xf…

Python入门【​编辑、组合、设计模式_工厂模式实现 、设计模式_单例模式实现、工厂和单例模式结合、异常是什么?异常的解决思路 】(十七)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小王&#xff0c;CSDN博客博主,Python小白 &#x1f4d5;系列专栏&#xff1a;python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 &#x1f4e7;如果文章知识点有错误…

弘扬“两弹一星”精神,勇攀科学技术高峰——道本科技商业大学党日活动圆满落幕

2023年8月2日&#xff0c;道本科技与商业大学携手举办了一场主题为“弘扬‘两弹一星’精神&#xff0c;勇攀科学技术高峰”的党日活动。本次活动旨在了解党领导下的中国核工业发展历程&#xff0c;传承和弘扬“两弹一星”精神&#xff0c;同时展示道本科技创新产品&#xff0c;…