当前位置: 首页 > 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(){//没…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...