开发者

Python实现提取Excel嵌入图片并重命名

目录
  • 1. 背景介绍
  • 2. 库的安装
  • 3. 主要类与方法
  • 4、完整代码
  • 5. 注意事项

1. 背景介绍

我们在日常办公的时候经常需要将Excel中嵌入单元的图片进行提取,并在提取的时候将其中的某一列作为提取出图片的命名,然后将图片存放好!

为此我们可以利用python将图片进行提取然后进行保存!

2. 库的安装

用途安装
XMLtodict读取xml文件pip install xmltodict -i https://pypi.tuna.tsinghua.edu.cn/simple/
pandasExcel读写pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple/
os获取路径内置库无需安装
json读写json文件内置库无需安装
re正则表javascript达式内置库无需安装
shutil文件操作内置库无需安装
tempfile创建临时文件和目录内置库无需安装

3. 主要类与方法

ExcelImageProcessor 类

  • 初始化 (__init__):接收Excel文件路径、用于重命名的依据列名(id_column)、包含图片的列名(image_column)。
  • 创建临时工作空间 (create_temp_workspace):创建临时目录,将Excel文件复制到临时目录并解压为.zip格式。
  • 清理临时工作空间 (cleanup_temp_workspace):删除临时目录及其内容。
  • 提取图片ID (extract_image_id):从字符串中提取符合特定正则表达式的图片ID。
  • 获取单元格与图片ID映射 (get_cell_image_mapping):解析sheet.xml文件,获取单元格位置与图片ID的映射。
  • 获取图片ID与rId映射 (get_image_rId_mapping):解析cellimages.xml文件,获取图片ID与rId的映射。
  • 获取rId与目标文件映射 (get_cellimages_rels):解析cellimages.xml.rels文件,获取rId与目标文件路径的映射。
  • 处理Excel文件 (process_excel):调用上述方法,构建单元格到图片文件路径的直接映射。
  • 复制并重命名图片 (copy_and_rename_images):根据映射关系,将图片复制到输出目录并重命名。
  • 主流程 (process):调用上述方法完成整个处理流程。

main 函数

提供使用示例,设置默认参数(如“订单号”和“图片”列),调用ExcelImageProcessor类的process方法执行图片提取与重命名。

关键点

  • 临时目录管理: 使用tempfile.mkdtemp()创建临时目录,确保操作完成后通过shutil.rmtree()清理。
  • XML解析: 使用xmltodict库解析Excel内部的XML文件,提取所需信息。
  • 图片路径修正: 确保图片路径以media/开头,并正确拼接完整路径。
  • 异常处理: 在主流程中捕获异常并打印错误信息,确保程序健壮性。

输出结果

提取的图片保存在图片输出目录下,文件名基于指定列(如“订单号”)重命名。

4、完整代码

# -*- coding: UTF-8 -*-
'''
@Project :45-Excel嵌入图片提取 
@File    :通用版本.py
@IDE     :PyCharm 
@Author  :一晌小贪欢(278865463@qq.com)
@Date    :2025/3/18 20:49 
'''
import pandas as pd
import os
import re
import xmltodict
import shutil
import tempfile


class ExcelImageProcessor:
    def __init__(self, excel_path, id_column, image_column):
        """
        初始化处理器
        Args:
            excel_path: Excel文件路径
            id_column: 用于重命名的依据列名
            image_column:http://www.devze.com 包含图片的列名
        """
        self.excel_path = excel_path
        self.pythonid_column = id_column
        self.image_column = image_column
        self.temp_dir = None
        self.extract_dir = None
        self.output_dir = "图片输出"

    def create_temp_workspace(self):
        """创建临时工作空间并复制Excel文件"""
        self.temp_dir = tempfile.mkdtemp()

        # 复制Excel文件到临时目录
        excel_name = os.path.basename(self.excel_path)
        temp_excel = os.path.join(self.temp_dir, excel_name)
        shutil.copy2(self.excel_path, temp_excel)

        # 创建解压目录
        self.extract_dir = os.path.join(self.temp_dir, 'extracted')
        os.makedirs(self.extract_dir)

        # 复制Excel为zip并解压
        zip_path = os.path.join(self.temp_dir, 'temp.zip')
        shutil.copy2(temp_excel, zip_path)
        shutil.unpack_archive(zip_path, self.extract_dir, 'zip')

    def cleanup_temp_workspace(self):
        """清理临时工作空间"""
        if self.temp_dir and os.path.exists(self.temp_dir):
            shutil.rmtree(self.temp_dir)

    def extract_image_id(self, text):
        """从字符串中提取图片ID"""
        match = re.search(r'ID_[A-F0-9]+', text)
        return match.group() if match else None

    def get_cell_image_mapping(self, sheet_xml_path):
        """
        从sheet.xml文件中提取单元格和图片ID的映射关系
        Args:
            sheet_xml_path: sheet.xml文件路径
        Returns:
            dict: 单元格位置和图片ID的映射字典
        """
        cell_image_dict = {}

        # 检查文件是否存在
        if not os.path.exists(sheet_xml_path):
            return cell_image_dict

        # 读取并解析XML文件
        with open(sheet_xml_path, 'r', encoding='utf-8') as file:
            xml_content = file.read()
            sheet_dict = xmltodict.parse(xml_content)

        # 遍历worksheet中的sheetData下的row数据
        for row in sheet_dict['worksheet']['sheetData']['row']:
            # 遍历每行中的单元格数据
            if 'c' in row:
                for cell in row['c']:
                    # 检查单元格是否包含DISPIMG函数
                    if 'v' in cell and 'DISPIMG' in cell['v']:
                        cell_pos = cell['@r']
                        image_id = self.extract_image_id(cell['v'])
                        if image_id:
                            cell_image_dict[cell_pos] = image_id

        return cell_image_dict

    def get_image_rId_mapping(self, cellimages_xml):
        """
        从cellimages.xml文件中提取图片ID和rId的映射关系
        Args:
            cellimages_xml: cellimages.xml文件路径
        Returns:
            dict: 图片ID和rId的映射字典
        """
        image_rId = {}

        # 读取并解析XML文件
        with open(cellimages_xml, 'r', encoding='utf-8') as file:
            xml_content = file.read()
            cellimages_dict = xmltodict.parse(xml_content)

        # 遍历cellimages_dict中的图片数据
        for image in cellimages_dict['etc:cellImages']['etc:cellImage']:
            image_id = image['xdr:pic']['xdr:nvPicPr']['xdr:cNvPr']['@name']
            r_id = image['xdr:pic']['xdr:blipFill']['a:blip']['@r:embed']
            image_rId[image_id] = r_id

        return image_rId

    def get_cellimages_rels(self, cellimages_rels_xml):
        """
        从cellimages.xml.rels文件中读取并解析关系映射
        Args:
            cellimages_rels_xml: cellimages.xml.rels文件路径
        Returns:
            dict: rId和目标文件的映射字典
        """
        rels_dict = {}

        # 读取并解析XML文件
        with open(cellimages_rels_xml, 'r', encoding='utf-8') as file:
            xml_content = file.read()
            rels = xmltodict.parse(xml_content)

        # 遍历Relationships中的Relationship数据
        for rel in rels['Relationships']['Relationship']:
            r_id = rel['@Id']
            # 确保路径以 media/ 开头
            target = rel['@Target']
            if not target.startswith('media/'):
                target = f"media/{target}"
            rels_dict[r_id] = target

        return rels_dict

    def process_excel(self):
        """处理Excel文件并提取图片映射关系"""
        # 创建临时工作空间
        self.create_temp_workspace()

        # 构建解压后的文件路径
        sheet_xml = os.path.join(self.extract_dir, "xl/worksheets/sheet1.xml")
        cellimages_xml = os.path.join(self.extract_dir, "xl/cellimages.xml")
        rels_xml = os.path.join(self.extract_dir, "xl/_rels/cellimages.xml.rels")

        # 获取各层映射
        cell_to_id = self.get_cell_image_mapping(sheet_xml)
        id_to_rid = self.get_image_rId_mapping(cellimages_xml)
        rid_to_file = self.get_cellimages_rels(rels_xml)

        # 构建单元格到文件位置的直接映射
        cell_to_file = {}
        for cell, image_id in cell_to_id.items():
            rid = id_to_rid[image_id]
            file_path = rid_to_file[rid]
            cell_to_file[cell] = file_path

        # 读取Excel文件
        df = pd.read_excel(self.excel_path)

        return df, cell_to_file

    def copy_and_rename_images(self, df, cell_to_file):
        """
        复制并重命名图片
        Args:
            df: DataFrame对象
            cell_to_file: 单元格到文件路径的映射
        """
        # 创建输出目录
        if not os.path.exists(self.output_dir):
            os.makedirs(self.output_dir)

        # 获取图片列的列号
        image_column_idx = None
        for idx, col in enumerate(df.columns):
            if col == self.image_column:
                image_column_idx = idx
                break
        column_letter = chr(65 + image_column_idx)

        # 处理每一行
        for index, row in df.iterrows():
            id_value = row[self.id_column]
            cell_ref = f"{column_letter}{index + 2}"

            if cell_ref in cell_to_file:
                # 获取源图片路径
                image_rel_path = cell_to_file[cell_ref]
                # 修正图片路径,确保包含完整的xl路径
                image_path = os.path.join(self.extract_dir, "xl", image_rel_path)

                # 获取文件扩展名
                _, ext = os.path.splitext(image_rel_path)

                # 构建新的文件名和路径
                new_filename = f"{id_value}{ext}"
                new_path = os.path.join(self.output_dir, new_filename)

                # 复制并重命名图片
                if os.path.exists(image_path):
                    shutil.copy2(image_path, new_path)
                else:
                    print(f"警告: 找不到图片文件 {image_path}")

    def process(self):
        """处理主流程"""
        try:
            # 处理Excel获取映射关系
            df, cell_to_file = self.process_excel()

            # 复制并重命名图片
            self.copy_and_rename_images(df, cell_to_file)

            print(f"处理完成!图片已保存到 {self.outpythonput_dir} 目录")

        except Exception as e:
            print(f"处理过程中出现错误: {str(e)}")
            raise
        finally:
            # 在所有操作完成后再清理临时目录
            self.cleanup_temp_workspace()


def main():
    # 使用示例
    """
        传入 Excel 路径、命名列、图片列 三个参数
        自动根据顺序命名图片,并导出到 “图片输出” 文件夹
    """
    if not os.path.exists('./图片输出/'):
        os.makedirs('./图片输出/')
    excel_path = "./数据源/" + os.listdir('./数据源/')[0]
    processor = ExcelImageProcessor(
        excel_path=excel_path,
        id_column="订单号",
        image_column="图片"
    )
    processor.process()


if __name__ == "__main__":
    main()

5. 注意事项

请各位友友按照自己的情况修改一下参数

Python实现提取Excel嵌入图片并重命名

效果如下

Python实现提取Excel嵌入图片并重命名

到此这篇关于Python实现提取Excel嵌入图片并重命名的文章就介绍到这了,更多相关Python提取Excel嵌入图片内容请搜索编程客栈(www.cppcnswww.devze.com.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新开发

开发排行榜