如何提取WPS表格指定单元格内的嵌入图片
评论
收藏

如何提取WPS表格指定单元格内的嵌入图片

经验分享
沥川
2024-06-24 16:21·浏览量:2615
沥川
发布于 2024-06-16 18:58更新于 2024-06-24 16:212615浏览

ps:社区内已有许多关于提取wps内嵌图片的帖子,但好像都未提及如何提取指定单元格内的图片,特别是在多sheet页和存在重复图片的情况下,希望能帮到大家~

问题及实现演示

问题

如何将WPS表格中的指定单元格的图片提取出来

WPS在线表格中某Sheet页的每一行存储了客户信息和需要发给客户的订单图片(嵌入),该表格约900行,表格中图片约1200张,其中存在200张左右重复图片~~~

为保护客户隐私,现将场景简单复现如下。

如下图所示

实现演示

分析过程

表格特点

观察可知表格中存在①表格中存在重复图片

                                ②每行存储的图片数量不一

                                ③表格中图片均为嵌入图片

                                ④表格中存在多Sheet页且均有图片

                                ⑤表格中存在大量数据(假设)

已知①.xlsx文件实际上是一个 ZIP 压缩包,其中包含多个 XML 文件和其他资源文件

      ②WPS内嵌图片后会由DISPIMG函数生成一串唯一ID

      ③解压后可得到表格内的所有图片,且表格中的重复图片只会保存一张并由imagexx命名

解压后的.xlsx文件的结构一般如下(嵌入式图片):

我们这次需要用到的文件以及表格内的图片均在xl文件夹内,如下所示

如何得到单元格号和图片文件名的映射

接下来就是对xl文件夹内的其中三个xml文件进行分析,最后得到单元格号和图片文件名的映射~

通过对文件的分析可得到rId与DISPIMG_ID的映射、单元格号DISPIMG_ID的映射、rId与imagexx的映射(rId、DISPIMG_ID、imagexx均在文件内),需要分析的三个文件分别是

①...xl\cellimages.xml——得到rId→DISPIMG_ID的映射

②...xl\worksheets\sheetX.xml——单元格号→DISPIMG_ID的映射(sheetX表示需处理的某一Sheet页)

③...xl\_rels\cellimages.xml.rels——rId→imagexx的映射

由这三对映射关系最终可得到单元格号→imagexx的映射,也就达到了我们的目的~

单元格号--→imagexx
{'B1': 'media/image3.png', 'C1': 'media/image2.png', 
 'D1': 'media/image8.png', 'E1': 'media/image1.png', 
 'B2': 'media/image2.png', 'C2': 'media/image1.png', 
 'D2': 'media/image7.jpeg', 'B3': 'media/image6.png', 
 'C3': 'media/image5.png', 'D3': 'media/image4.png', 
 'E3': 'media/image9.png', 'B4': 'media/image4.png', 
 'C4': 'media/image7.jpeg', 'D4': 'media/image3.png', 
 'B5': 'media/image2.png', 'C5': 'media/image1.png'}

代码及使用说明

映射关系提取代码

import xml.etree.ElementTree as ET
import re

# 定义命名空间
NS_1 = {
    'xdr': 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing',
    'a': 'http://schemas.openxmlformats.org/drawingml/2006/main',
    'r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'
}
NS_2 = {'main': 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'}
NS_3 = {'pkg': 'http://schemas.openxmlformats.org/package/2006/relationships'}

# 解析cellimages.xml,得到rId→DISPIMG_ID的映射
def parse_cellimages(file_path):
    tree = ET.parse(file_path)
    root = tree.getroot()
    
    id_list = []
    for cell_image in root.findall('.//xdr:pic', NS_1):
        blip = cell_image.find('.//a:blip', NS_1)
        r_embed = blip.attrib.get('{http://schemas.openxmlformats.org/officeDocument/2006/relationships}embed') if blip is not None else None
        cNvPr = cell_image.find('.//xdr:cNvPr', NS_1)
        name = cNvPr.attrib.get('name') if cNvPr is not None else None

        if r_embed and name:
            id_list.append([r_embed, name])
    
    # print(id_list)
    return id_list

# 解析SheetX.xml,得到sheet页内单元格号→DISPIMG_ID的映射
def parse_spreadsheet(file_path):
    tree = ET.parse(file_path)
    root = tree.getroot()
    
    cell_info = {}
    for cell in root.findall('.//main:c', NS_2):
        formula = cell.find('main:v', NS_2)
        if formula is not None and 'DISPIMG' in formula.text:
            cell_ref = cell.attrib['r']
            match = re.search(r'DISPIMG\("([^"]+)"', formula.text)
            if match:
                dispimg_id = match.group(1)
                cell_info[cell_ref] = dispimg_id
    
    # print(cell_info)
    return cell_info

# 解析cellimages.xml.rels,得到rId→imagexx的映射
def parse_rels(file_path):
    tree = ET.parse(file_path)
    root = tree.getroot()
    
    relationships_dict = {}
    for elem in root.findall('.//pkg:Relationship', NS_3):
        r_id = elem.get('Id')
        target = elem.get('Target')
        if 'image' in target:
            relationships_dict[r_id] = target
    
    # print(relationships_dict)
    return relationships_dict

# 得到单元格号→imagexx的映射
def matches(file_path_1, file_path_2, file_path_3):
    id_list = parse_cellimages(file_path_1)
    cell_info = parse_spreadsheet(file_path_2)
    relationships_dict = parse_rels(file_path_3)
    
    id_to_rid = {item[1]: item[0] for item in id_list}
    for cell in cell_info:
        if cell_info[cell] in id_to_rid:
            cell_info[cell] = id_to_rid[cell_info[cell]]
    
    new_dict = {key: relationships_dict.get(value, value) for key, value in cell_info.items()}
    
    return new_dict

使用说明

①将以上代码拷贝,在影刀中新建py模块,粘贴代码

②调用该模块并传入三个xml文件路径,运行后将返回 {单元格号:imagexx}字典

ps:需要哪个sheet页中的图片对应关系传入对应的sheet页xml文件路径即可

③根据 {单元格号:imagexx}字典即可获取指定单元格内的嵌入图片

以上代码已考虑到重复图片、多sheet页(更换sheet页xml即可)以及图片未加载完整的情况,但现实中的表格可能更加复杂,如得到的结果未能一一对应欢迎大家讨论~

收藏11
全部评论1
最新
发布评论
评论