Python實現(xiàn)提取Excel嵌入圖片并重命名
1. 背景介紹
我們在日常辦公的時候經(jīng)常需要將Excel中嵌入單元的圖片進行提取,并在提取的時候?qū)⑵渲械哪骋涣凶鳛樘崛〕鰣D片的命名,然后將圖片存放好!
為此我們可以利用Python將圖片進行提取然后進行保存!
2. 庫的安裝
| 庫 | 用途 | 安裝 |
|---|---|---|
| xmltodict | 讀取xml文件 | pip install xmltodict -i https://pypi.tuna.tsinghua.edu.cn/simple/ |
| pandas | Excel讀寫 | pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple/ |
| os | 獲取路徑 | 內(nèi)置庫無需安裝 |
| json | 讀寫json文件 | 內(nèi)置庫無需安裝 |
| re | 正則表達式 | 內(nèi)置庫無需安裝 |
| shutil | 文件操作 | 內(nèi)置庫無需安裝 |
| tempfile | 創(chuàng)建臨時文件和目錄 | 內(nèi)置庫無需安裝 |
3. 主要類與方法
ExcelImageProcessor 類
- 初始化 (__init__):接收Excel文件路徑、用于重命名的依據(jù)列名(id_column)、包含圖片的列名(image_column)。
- 創(chuàng)建臨時工作空間 (create_temp_workspace):創(chuàng)建臨時目錄,將Excel文件復制到臨時目錄并解壓為.zip格式。
- 清理臨時工作空間 (cleanup_temp_workspace):刪除臨時目錄及其內(nèi)容。
- 提取圖片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):調(diào)用上述方法,構(gòu)建單元格到圖片文件路徑的直接映射。
- 復制并重命名圖片 (copy_and_rename_images):根據(jù)映射關(guān)系,將圖片復制到輸出目錄并重命名。
- 主流程 (process):調(diào)用上述方法完成整個處理流程。
main 函數(shù)
提供使用示例,設(shè)置默認參數(shù)(如“訂單號”和“圖片”列),調(diào)用ExcelImageProcessor類的process方法執(zhí)行圖片提取與重命名。
關(guān)鍵點
- 臨時目錄管理: 使用tempfile.mkdtemp()創(chuàng)建臨時目錄,確保操作完成后通過shutil.rmtree()清理。
- XML解析: 使用xmltodict庫解析Excel內(nèi)部的XML文件,提取所需信息。
- 圖片路徑修正: 確保圖片路徑以media/開頭,并正確拼接完整路徑。
- 異常處理: 在主流程中捕獲異常并打印錯誤信息,確保程序健壯性。
輸出結(jié)果
提取的圖片保存在圖片輸出目錄下,文件名基于指定列(如“訂單號”)重命名。
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: 用于重命名的依據(jù)列名
image_column: 包含圖片的列名
"""
self.excel_path = excel_path
self.id_column = id_column
self.image_column = image_column
self.temp_dir = None
self.extract_dir = None
self.output_dir = "圖片輸出"
def create_temp_workspace(self):
"""創(chuàng)建臨時工作空間并復制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)
# 創(chuàng)建解壓目錄
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的映射關(guān)系
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數(shù)據(jù)
for row in sheet_dict['worksheet']['sheetData']['row']:
# 遍歷每行中的單元格數(shù)據(jù)
if 'c' in row:
for cell in row['c']:
# 檢查單元格是否包含DISPIMG函數(shù)
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的映射關(guān)系
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中的圖片數(shù)據(jù)
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文件中讀取并解析關(guān)系映射
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數(shù)據(jù)
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文件并提取圖片映射關(guān)系"""
# 創(chuàng)建臨時工作空間
self.create_temp_workspace()
# 構(gòu)建解壓后的文件路徑
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)
# 構(gòu)建單元格到文件位置的直接映射
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: 單元格到文件路徑的映射
"""
# 創(chuàng)建輸出目錄
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)
# 構(gòu)建新的文件名和路徑
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獲取映射關(guān)系
df, cell_to_file = self.process_excel()
# 復制并重命名圖片
self.copy_and_rename_images(df, cell_to_file)
print(f"處理完成!圖片已保存到 {self.output_dir} 目錄")
except Exception as e:
print(f"處理過程中出現(xiàn)錯誤: {str(e)}")
raise
finally:
# 在所有操作完成后再清理臨時目錄
self.cleanup_temp_workspace()
def main():
# 使用示例
"""
傳入 Excel 路徑、命名列、圖片列 三個參數(shù)
自動根據(jù)順序命名圖片,并導出到 “圖片輸出” 文件夾
"""
if not os.path.exists('./圖片輸出/'):
os.makedirs('./圖片輸出/')
excel_path = "./數(shù)據(jù)源/" + os.listdir('./數(shù)據(jù)源/')[0]
processor = ExcelImageProcessor(
excel_path=excel_path,
id_column="訂單號",
image_column="圖片"
)
processor.process()
if __name__ == "__main__":
main()5. 注意事項
請各位友友按照自己的情況修改一下參數(shù)

效果如下

到此這篇關(guān)于Python實現(xiàn)提取Excel嵌入圖片并重命名的文章就介紹到這了,更多相關(guān)Python提取Excel嵌入圖片內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python3實現(xiàn)將本地JSON大數(shù)據(jù)文件寫入MySQL數(shù)據(jù)庫的方法
這篇文章主要介紹了Python3實現(xiàn)將本地JSON大數(shù)據(jù)文件寫入MySQL數(shù)據(jù)庫的方法,涉及Python針對json大數(shù)據(jù)文件的逐行讀取、mysql數(shù)據(jù)庫寫入等相關(guān)操作技巧,需要的朋友可以參考下2018-06-06
pycharm打包python項目為exe執(zhí)行文件的實例代碼
這篇文章主要介紹了pycharm打包python項目為exe執(zhí)行文件,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-07-07
python實現(xiàn)的DES加密算法和3DES加密算法實例
這篇文章主要介紹了python實現(xiàn)的DES加密算法和3DES加密算法,以實例形式較為詳細的分析了DES加密算法和3DES加密算法的原理與實現(xiàn)技巧,需要的朋友可以參考下2015-06-06
Django集成Celery之狀態(tài)監(jiān)控與任務(wù)管理詳解
這篇文章主要介紹了Django集成Celery之狀態(tài)監(jiān)控與任務(wù)管理詳解,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-03-03

