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

从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()

相关文章:

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

1 发现问题 我的excel中有浮动图片和嵌入式图片&#xff0c;但是openpyxl的_image对象只提取到了浮动图片&#xff0c;通过阅读其源码发现&#xff0c;这是因为openpyxl只解析了drawing文件导致的&#xff0c;所以确定需要自己解析 2 解决思路 1、解析出media资源 2、解析…...

python socket 网络编程的基本功

python socket逻辑思维整理 UDP发送步骤&#xff1a; 1 、先建立udp套接字 udp_socket socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 2、利用sendto把数据并指定对端IP和端口&#xff0c;本端端口可以不用指定用自动随机的 udp_socket.sendto(“发送的内容”.encode(“…...

【element-ui】form表单初始化页面如何取消自动校验rules

问题描述&#xff1a;elementUI表单提交页面&#xff0c;初始化页面是获取接口数据&#xff0c;给form赋值&#xff0c;但是有时候这些会是空值情况&#xff0c;如果是空值&#xff0c;再给form表单赋值的话&#xff0c;页面初始化时候进行rules校验会不通过&#xff0c;此时前…...

git 公钥密钥 生成与查看

1.什么是公钥 很多服务器都是需要认证的&#xff0c;ssh认证是其中的一种。在客户端生成公钥&#xff0c;把生成的公钥添加到服务器&#xff0c;你以后连接服务器就不用每次都输入用户名和密码了。 很多git服务器都是用ssh认证方式&#xff0c;你需要把你生成的公钥发送给代码仓…...

数据标注对新零售的意义及人工智能在新零售领域的应用?

数据标签对于新零售至关重要&#xff0c;因为它构成了训练和部署人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;模型的基础。在新零售的背景下&#xff0c;数据标签涉及对数据进行分类、标记或注释以使其能够被机器理解的过程。然后&#xff0c;这些…...

命令模式-请求发送者与接收者解耦

去小餐馆吃饭的时候&#xff0c;顾客直接跟厨师说想要吃什么菜&#xff0c;然后厨师再开始炒菜。去大点的餐馆吃饭时&#xff0c;我们是跟服务员说想吃什么菜&#xff0c;然后服务员把这信息传到厨房&#xff0c;厨师根据这些订单信息炒菜。为什么大餐馆不省去这个步骤&#xf…...

【雕爷学编程】Arduino动手做(186)---WeMos ESP32开发板

37款传感器与模块的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&#x…...

3、JSON数据的处理

3.1 介绍 JSON数据 Spark SQL can automatically infer the schema of a JSON dataset and load it as a DataFrame Spark SQL能够自动将JSON数据集以结构化的形式加载为一个DataFrame This conversion can be done using SparkSession.read.json on a JSON file 读取一个JSO…...

8月5日上课内容 nginx的优化和防盗链

全部都是面试题 nginx的优化和防盗链 重点就是优化&#xff1a; 每一个点都是面试题&#xff0c;非常重要&#xff0c;都是面试题 1、隐藏版本号&#xff08;重点&#xff0c;一定要会&#xff09; 备份 cp nginx.conf nginx.conf.bak.2023.0805 方法一&#xff1a;修改配…...

网络爬虫请求头中的Referer和User-Agent与代理IP的配合使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8EJgMcgK-1691050515642)(https://cdn.nlark.com/yuque/0/2023/png/1313150/1691048724422-2a76d7b8-3ec3-48b7-9aec-d609d09b16d4.png#averageHue%2385b0a7&clientIdu3856fd20-7701-4&fromui&…...

RabbitMQ 生产者-消息丢失 之 场景分析

生产者-消息丢失 之 场景分析 生产者消息丢失的场景消息无法到达RabbitMQ连接断开信道关闭 RabbitMQ无法将消息入队交换机不存在无匹配队列 消息过期丢失消息丢失场景对比 生产者消息丢失的场景 生产者发送消息的流程如下&#xff1a;首先生产者和RabbitMQ服务器建立连接&…...

Hyper实现git bash在windows环境下多tab窗口显示

1.电脑上安装有git bash 下载链接&#xff1a;https://gitforwindows.org/ 安装Hyper 下载链接:官网 https://hyper.is/ 或者在百度云盘下载&#xff1a; https://pan.baidu.com/s/1BVjzlK0s4SgAbQgsiK1Eow 提取码&#xff1a;0r1f 设置 打开Hyper&#xff0c;依次点左上角-&g…...

Matlab的信号频谱分析——FFT变换

Matlab的信号频谱分析——FFT变换 Matlab的信号频谱分析 FFT是离散傅立叶变换的快速算法&#xff0c;可以将一个时域信号变换到频域。 有些信号在时域上是很难看出什么特征的。但是如果变换到频域之后&#xff0c;就很容易看出特征了。 这就是很多信号分析采用FFT变换的原因…...

如何从 Android 设备恢复已删除的文件?

从 Android 设备恢复已删除的文件很简单&#xff0c;但您需要了解内部恢复和SD 卡恢复之间的区别。 目前销售的大多数 Android 设备都配备了 SD 卡插槽&#xff08;通常为 microSD&#xff09;&#xff0c;可以轻松添加额外的存储空间。该存储空间可用于存储照片、视频、文档&a…...

servlet生命周期和初始化参数传递

servlet生命周期和初始化参数传递 1、servlet生命周期 只有第一次访问才会初始化&#xff0c;之后访问都只执行service中的。 除非tomcat关闭重新启动&#xff1a; 2、初始化参数传递...

dvwa靶场通关(十一)

第十一关&#xff1a;Reflected Cross Site Scripting (XSS) low 这一关没有任何防护&#xff0c;直接输入弹窗 <script>alert(xss)</script> 打开网页源代码&#xff0c; 从源代码中我们可以看到&#xff0c;前面是输出的第一部分Hello&#xff0c;我们输入的脚…...

【Spring】使用注解存储Bean对象

目录 一、配置扫描路径&#xff08;使用注解的方式存对象的前提&#xff09; 二、使用类注解存储Bean对象 1、使用五大类注解存储Bean对象 2、为什么要这么多的类注解&#xff1f; 2.1、五大类注解之间的关系 3、获取Bean对象时的默认命名规则 三、使用方法注解来存储…...

怎么维护好自己的电脑

你的电脑已经成为你工作、学习、娱乐的最佳工具之一&#xff0c;但是如果你不做好电脑维护工作&#xff0c;就可能面临着电脑变慢、蓝屏、崩溃等问题。在这篇文章中&#xff0c;我们将介绍10个电脑维护步骤&#xff0c;让你的电脑更加稳定&#xff01; 为什么需要电脑维护&…...

vscode中无法使用git解决方案

1 首先查看git安装目录 where git 2 找到bash.exe 的路径 比如&#xff1a;C:/Users/Wangzd/AppData/Local/Programs/Git/bin/bash 3 找到vscode的配置项setting.json 4 添加 "terminal.integrated.shell.windowns": "C:/Users/Wangzd/AppData/Local/Pr…...

MybatisPlus-CRUD,不带条件构造器的常用方法

mapper层 Repository public interface UserMapper extends BaseMapper<User> BaseMapper中封装好了增删改查的方法 后面直接调用就好了 测试类 SpringBootTest public class CrudTest {Autowiredprivate UserMapper userMapper;//新增Testpublic void insert(){//没…...

qt风格创建子线程。继承自qthread的类,只有run函数里面才是子线程

...

保姆级教程:用VASP+VTST脚本搞定CI-NEB过渡态计算(从编译到出图)

从零构建VASPVTST的CI-NEB计算体系&#xff1a;科研级过渡态求解实战指南 在计算材料科学领域&#xff0c;精确确定化学反应或扩散过程的过渡态结构是理解反应机理的关键。传统NEB方法虽能描绘反应路径&#xff0c;但对鞍点的定位精度有限——这正是CI-NEB方法的价值所在。本文…...

2026年支持人民币计价的金价追踪APP有哪些

家人们谁懂啊&#xff01;上周我发小蹲了3个月的50克古法金镯子终于下手&#xff0c;结账的时候才傻了眼&#xff1a;她之前用来盯金价的APP默认是美元离岸价&#xff0c;自己换算的时候忘了算汇率差和国内基础金价的浮动&#xff0c;预估的总价和实际付款差了快1800&#xff0…...

手把手教你用CANoe分析CAN FD报文:从帧格式到CRC校验实战

CAN FD报文解析实战&#xff1a;从帧结构到CRC校验的工程化操作指南 在汽车电子和工业控制领域&#xff0c;CAN总线技术已经演进到更高效的CAN FD标准。对于已经掌握CAN基础知识的工程师而言&#xff0c;如何将理论转化为实际工程能力&#xff0c;特别是在使用行业标准工具CAN…...

英雄联盟LCU工具集LeagueAkari:终极自动化游戏助手完整指南

英雄联盟LCU工具集LeagueAkari&#xff1a;终极自动化游戏助手完整指南 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power &#x1f680;. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit LeagueAkari是一款基于…...

Perplexity搜索响应延迟突增2100ms?内部API调用链路拆解,开发者必看避坑清单

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;Perplexity搜索响应延迟突增2100ms&#xff1f;现象复现与影响定性 近期监控系统捕获到Perplexity搜索API端点&#xff08; /v1/search&#xff09;在UTC时间2024-06-12T08:14:22Z起出现持续约17分钟的P99延迟…...

3个真实场景告诉你,Avogadro 2分子建模软件如何改变化学研究方式

3个真实场景告诉你&#xff0c;Avogadro 2分子建模软件如何改变化学研究方式 【免费下载链接】avogadroapp Avogadro is an advanced molecular editor designed for cross-platform use in computational chemistry, molecular modeling, bioinformatics, materials science, …...

操作插件方法

事件触发时机事务状态适用场景beforeExecuteOperationTransaction操作校验通过后&#xff0c;开启事务之前事务未开启✅ 修改源单据关联的其他单据beginOperationTransaction开启事务后&#xff0c;提交数据库之前事务已开启修改当前操作的单据自身数据...

别再傻傻等下载了!QMT历史数据获取的3个高效技巧(含xtquant代码示例)

QMT历史数据获取效率优化实战&#xff1a;3个让回测提速200%的高级技巧 每次打开QMT准备回测策略时&#xff0c;最让人抓狂的莫过于漫长的历史数据等待时间。作为一名量化研究员&#xff0c;我曾在数据准备环节浪费了无数个下午——直到发现这几个能彻底改变工作流的技巧。本文…...

告别阿里云物联网平台:用免费公共MQTT服务器玩转ESP32远程监控

告别商业云平台&#xff1a;用免费公共MQTT服务器实现ESP32远程监控 在物联网项目开发中&#xff0c;远程数据传输是核心需求之一。许多开发者习惯性选择阿里云、腾讯云等商业物联网平台&#xff0c;却常常被复杂的配置流程、高昂的服务费用所困扰。实际上&#xff0c;对于个人…...