Python從Excel中按行提取圖片的實(shí)現(xiàn)方法
前言
在Excel表格中批量導(dǎo)出圖片,并按行首字段命名保存,是許多辦公場(chǎng)景的剛需。本文提供兩個(gè)完整可運(yùn)行的Python版本:
- 版本一:保持圖片原始格式(PNG、JPG等各自保留)
- 版本二:統(tǒng)一將所有圖片轉(zhuǎn)換為JPG格式(節(jié)省空間、格式統(tǒng)一)
兩個(gè)版本均實(shí)現(xiàn)了:按工作表分文件夾 → 根據(jù)圖片所在行的A列值命名 → 自動(dòng)處理重名和非法字符。
一、版本一:保持原始格式
該版本完全保留圖片原始格式(.png / .jpg / .gif等),其他功能完整。
import openpyxl
from PIL import Image as PILImage
import io
import os
def extract_images_from_excel(excel_path, output_dir=None):
"""
按行提取 Excel 中的圖片,存儲(chǔ)到以 Sheet 名稱(chēng)命名的文件夾下,
圖片命名為該行第一個(gè)字段的值(即A列),保持原始格式。
"""
if output_dir is None:
output_dir = os.path.dirname(os.path.abspath(excel_path))
os.makedirs(output_dir, exist_ok=True)
wb = openpyxl.load_workbook(excel_path)
extracted_count = 0
for sheet_name in wb.sheetnames:
ws = wb[sheet_name]
print(f"處理工作表: {sheet_name}")
safe_sheet_name = "".join(
c for c in sheet_name if c not in r'\/:*?"<>|'
).strip()
sheet_dir = os.path.join(output_dir, safe_sheet_name)
os.makedirs(sheet_dir, exist_ok=True)
# 收集每行A列的值
row_first_cell = {}
for row in range(1, ws.max_row + 1):
cell_value = ws.cell(row=row, column=1).value
if cell_value is not None:
row_first_cell[row] = str(cell_value)
for image in ws._images:
anchor = image.anchor
if hasattr(anchor, '_from'):
row_num = anchor._from.row + 1
elif hasattr(anchor, 'row'):
row_num = anchor.row + 1
else:
print(f" ?? 無(wú)法確定圖片行號(hào),跳過(guò)")
continue
first_cell_value = row_first_cell.get(row_num, None)
if first_cell_value is None:
print(f" ?? 第{row_num}行第一個(gè)字段為空,跳過(guò)")
continue
safe_name = "".join(
c for c in first_cell_value if c not in r'\/:*?"<>|'
).strip()
if not safe_name:
safe_name = f"row_{row_num}"
img_data = image._data()
img = PILImage.open(io.BytesIO(img_data))
# 獲取原始格式
img_format = img.format.lower() if img.format else 'png'
filename = f"{safe_name}.{img_format}"
filepath = os.path.join(sheet_dir, filename)
counter = 1
base_name = safe_name
while os.path.exists(filepath):
filename = f"{base_name}_{counter}.{img_format}"
filepath = os.path.join(sheet_dir, filename)
counter += 1
img.save(filepath)
extracted_count += 1
print(f" ? 第{row_num}行 -> {safe_sheet_name}/{filename}")
print(f"\n?? 完成!共提取 {extracted_count} 張圖片,保存至: {output_dir}")
if __name__ == '__main__':
excel_path = 'cards.xlsx' # 修改為你的文件
extract_images_from_excel(excel_path, output_dir='images')
二、版本二:統(tǒng)一存儲(chǔ)為JPG格式
該版本將所有提取的圖片統(tǒng)一轉(zhuǎn)換為JPG格式(背景自動(dòng)填充白色以處理透明通道),可設(shè)置JPG質(zhì)量。適合需要統(tǒng)一格式、減小體積的場(chǎng)景。
import openpyxl
from PIL import Image as PILImage
import io
import os
def extract_images_as_jpg(excel_path, output_dir=None, jpg_quality=85):
"""
按行提取 Excel 中的圖片,統(tǒng)一轉(zhuǎn)換為 JPG 格式存儲(chǔ)。
參數(shù):
excel_path: Excel 文件路徑
output_dir: 輸出根目錄
jpg_quality: JPG 壓縮質(zhì)量 (1-100),默認(rèn)85
"""
if output_dir is None:
output_dir = os.path.dirname(os.path.abspath(excel_path))
os.makedirs(output_dir, exist_ok=True)
wb = openpyxl.load_workbook(excel_path)
extracted_count = 0
for sheet_name in wb.sheetnames:
ws = wb[sheet_name]
print(f"處理工作表: {sheet_name}")
safe_sheet_name = "".join(
c for c in sheet_name if c not in r'\/:*?"<>|'
).strip()
sheet_dir = os.path.join(output_dir, safe_sheet_name)
os.makedirs(sheet_dir, exist_ok=True)
# 收集每行A列的值
row_first_cell = {}
for row in range(1, ws.max_row + 1):
cell_value = ws.cell(row=row, column=1).value
if cell_value is not None:
row_first_cell[row] = str(cell_value)
for image in ws._images:
anchor = image.anchor
if hasattr(anchor, '_from'):
row_num = anchor._from.row + 1
elif hasattr(anchor, 'row'):
row_num = anchor.row + 1
else:
print(f" ?? 無(wú)法確定圖片行號(hào),跳過(guò)")
continue
first_cell_value = row_first_cell.get(row_num, None)
if first_cell_value is None:
print(f" ?? 第{row_num}行第一個(gè)字段為空,跳過(guò)")
continue
safe_name = "".join(
c for c in first_cell_value if c not in r'\/:*?"<>|'
).strip()
if not safe_name:
safe_name = f"row_{row_num}"
img_data = image._data()
img = PILImage.open(io.BytesIO(img_data))
# ----- 轉(zhuǎn)換為 JPG 的關(guān)鍵代碼 -----
# 若圖片為 RGBA(帶透明通道),需轉(zhuǎn)換為 RGB(白色背景)
if img.mode in ('RGBA', 'LA', 'P'):
# 創(chuàng)建白色背景
background = PILImage.new('RGB', img.size, (255, 255, 255))
# 將原圖粘貼到背景(使用透明通道作為掩碼)
if img.mode == 'P':
img = img.convert('RGBA')
background.paste(img, mask=img.split()[-1] if img.mode == 'RGBA' else None)
img = background
elif img.mode != 'RGB':
img = img.convert('RGB')
# -----------------------------
filename = f"{safe_name}.jpg"
filepath = os.path.join(sheet_dir, filename)
counter = 1
base_name = safe_name
while os.path.exists(filepath):
filename = f"{base_name}_{counter}.jpg"
filepath = os.path.join(sheet_dir, filename)
counter += 1
# 保存為 JPG,可指定質(zhì)量
img.save(filepath, 'JPEG', quality=jpg_quality)
extracted_count += 1
print(f" ? 第{row_num}行 -> {safe_sheet_name}/{filename} (JPG質(zhì)量={jpg_quality})")
print(f"\n?? 完成!共提取 {extracted_count} 張圖片,已統(tǒng)一為JPG格式,保存至: {output_dir}")
if __name__ == '__main__':
excel_path = 'cards.xlsx' # 修改為你的文件
extract_images_as_jpg(excel_path, output_dir='images_jpg', jpg_quality=85)
三、兩個(gè)版本的核心區(qū)別
| 特性 | 版本一(原格式) | 版本二(統(tǒng)一JPG) |
|---|---|---|
| 輸出擴(kuò)展名 | .png / .jpg / .gif 等原樣保留 | 統(tǒng)一為 .jpg |
| 透明背景處理 | 保留原圖(PNG透明通道) | 白色背景填充 |
| 壓縮控制 | 無(wú)(原樣保存) | 可調(diào)節(jié) quality 參數(shù) |
| 適用場(chǎng)景 | 需要保留原始質(zhì)量/透明效果 | 統(tǒng)一瀏覽、減小體積 |
| 輸出文件夾 | images/ | images_jpg/ |
四、使用步驟(通用)
安裝依賴(lài)
pip install openpyxl pillow
準(zhǔn)備Excel文件
- 確保圖片是“嵌入”到單元格中的(而非浮動(dòng)鏈接)。
- 每個(gè)含圖片的行,A列 必須有值,該值將作為圖片文件名。
選擇版本并修改路徑
將代碼末尾的 excel_path = 'cards.xlsx' 改為實(shí)際文件路徑,可修改 output_dir。
運(yùn)行腳本
python extract_images.py # 或 extract_as_jpg.py
結(jié)果
在輸出目錄下會(huì)按工作表名稱(chēng)創(chuàng)建子文件夾,圖片按 A列值 命名存放。
五、注意事項(xiàng)
- 圖片定位:腳本依賴(lài) openpyxl 的圖片錨點(diǎn)屬性,對(duì)于合并單元格或跨行圖片可能定位不準(zhǔn),建議將圖片完整置于某一行內(nèi)。
- 命名沖突:同一工作表中不同行的 A列值相同時(shí),會(huì)自動(dòng)添加
_1、_2后綴。 - 非法字符:文件名中的
/ \ : * ? " < > |會(huì)被自動(dòng)去除。 - JPG 版本:原圖為 GIF 動(dòng)圖時(shí),只會(huì)提取第一幀并轉(zhuǎn)為 JPG;原圖為 CMYK 模式會(huì)自動(dòng)轉(zhuǎn)為 RGB。
六、擴(kuò)展建議
- 修改命名列:將
column=1改為column=2即可使用B列命名。 - 批量處理多個(gè)Excel:可在外層增加循環(huán),依次調(diào)用函數(shù)。
- 支持更多輸出格式:在版本二中將
'JPEG'改為'PNG'即可輸出 PNG,但體積較大。 - 保留透明通道轉(zhuǎn)PNG:若希望統(tǒng)一為 PNG 并保留透明,可將版本二的轉(zhuǎn)換代碼去掉,直接保存為 PNG。
七、總結(jié)
本文提供了兩個(gè)完整、可直接運(yùn)行的 Python 腳本,分別滿(mǎn)足“原格式保留”和“統(tǒng)一轉(zhuǎn) JPG”的常見(jiàn)需求。你只需要替換文件路徑即可運(yùn)行,大大提升從 Excel 批量導(dǎo)出圖片的效率。選擇適合自己的版本,開(kāi)始自動(dòng)化辦公吧!
以上就是Python從Excel中按行提取圖片的方法實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Python Excel按行提取圖片的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python簡(jiǎn)單實(shí)現(xiàn)Base64編碼和解碼的方法
這篇文章主要介紹了Python簡(jiǎn)單實(shí)現(xiàn)Base64編碼和解碼的方法,結(jié)合具體實(shí)例形式分析了Python實(shí)現(xiàn)base64編碼解碼相關(guān)函數(shù)與使用技巧,需要的朋友可以參考下2017-04-04
基于logstash實(shí)現(xiàn)日志文件同步elasticsearch
這篇文章主要介紹了基于logstash實(shí)現(xiàn)日志文件同步elasticsearch,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
Python3 urllib 使用指南及注意事項(xiàng)
本文介紹了Python3中urllib模塊的基本用法,包括發(fā)送請(qǐng)求、解析響應(yīng)以及HTML解析,本文將詳細(xì)介紹 Python3 中 urllib 模塊的使用方法,包括其基本功能、常見(jiàn)用法以及注意事項(xiàng),感興趣的朋友跟隨小編一起看看吧2026-01-01
python實(shí)現(xiàn)的config文件讀寫(xiě)功能示例
這篇文章主要介紹了python實(shí)現(xiàn)的config文件讀寫(xiě)功能,結(jié)合實(shí)例形式分析了Python文件讀寫(xiě)相關(guān)操作技巧,需要的朋友可以參考下2019-09-09
Python騷操作完美實(shí)現(xiàn)短視頻偽原創(chuàng)
剪輯的視頻上傳到某平臺(tái)碰到降權(quán)怎么辦?視頻平臺(tái)都有一套自己的鑒別算法,專(zhuān)門(mén)用于處理視頻的二次剪輯,本篇我們來(lái)用python做一些特殊處理2022-02-02
python 利用toapi庫(kù)自動(dòng)生成api
這篇文章主要介紹了python 利用toapi庫(kù)自動(dòng)生成api,幫助大家更好的理解和學(xué)習(xí)python,感興趣的朋友可以了解下2020-10-10
解決win64 Python下安裝PIL出錯(cuò)問(wèn)題(圖解)
這篇文章主要介紹了解決win64 Python下安裝PIL出錯(cuò)問(wèn)題,文中的解決方法也很簡(jiǎn)單,需要的朋友參考下吧2018-09-09
詳解利用OpenCV提取圖像中的矩形區(qū)域(PPT屏幕等)
這篇文章主要介紹了詳解利用OpenCV提取圖像中的矩形區(qū)域(PPT屏幕等),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-07-07
python GUI庫(kù)圖形界面開(kāi)發(fā)之pyinstaller打包python程序?yàn)閑xe安裝文件
這篇文章主要介紹了python GUI庫(kù)圖形界面開(kāi)發(fā)之pyinstaller打包python程序?yàn)閑xe安裝文件,需要的朋友可以參考下2020-02-02

