python 提取excel 数据并提取表格中的图片
·
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Excel读取工具 - 支持图片提取
遍历每个sheet,从第二行开始读取数据,并提取图片保存到本地
"""
import os
import sys
from pathlib import Path
import shutil
def install_requirements():
"""安装必要的依赖包"""
import subprocess
packages = ['openpyxl', 'Pillow']
for package in packages:
try:
if package == 'Pillow':
import PIL
else:
__import__(package)
except ImportError:
print(f"正在安装 {package}...")
subprocess.check_call([sys.executable, '-m', 'pip', 'install', package])
def extract_images_from_excel(file_path, output_dir="excel_images"):
"""
从Excel文件中提取图片并保存到本地
Args:
file_path (str): Excel文件路径
output_dir (str): 图片保存目录
Returns:
dict: 包含图片信息的字典
"""
try:
import openpyxl
from openpyxl.drawing.image import Image as ExcelImage
from PIL import Image
import io
print(f"正在从Excel文件中提取图片...")
print("=" * 50)
# 创建图片保存目录
if os.path.exists(output_dir):
shutil.rmtree(output_dir)
os.makedirs(output_dir, exist_ok=True)
# 打开Excel文件
workbook = openpyxl.load_workbook(file_path)
sheet_names = workbook.sheetnames
print(f"发现 {len(sheet_names)} 个sheet: {sheet_names}")
all_images = {}
image_counter = 1
for sheet_name in sheet_names:
print(f"\n处理sheet: {sheet_name}")
print("-" * 30)
sheet = workbook[sheet_name]
sheet_images = []
# 遍历sheet中的所有图片
for image in sheet._images:
try:
# 获取图片数据
image_data = image._data()
# 创建PIL图片对象
pil_image = Image.open(io.BytesIO(image_data))
# 生成图片文件名
image_filename = f"{sheet_name}_image_{image_counter:03d}.png"
image_path = os.path.join(output_dir, image_filename)
# 保存图片
pil_image.save(image_path, 'PNG')
# 获取图片在Excel中的位置信息
anchor = image.anchor
if hasattr(anchor, '_from'):
row = anchor._from.row + 1 # Excel行号从1开始
col = anchor._from.col + 1 # Excel列号从1开始
else:
row = 1
col = 1
image_info = {
'filename': image_filename,
'path': image_path,
'sheet': sheet_name,
'row': row,
'col': col,
'size': pil_image.size,
'format': pil_image.format
}
sheet_images.append(image_info)
print(f" 保存图片: {image_filename} (位置: 行{row}, 列{col})")
image_counter += 1
except Exception as e:
print(f" 处理图片时出错: {e}")
continue
all_images[sheet_name] = sheet_images
print(f" Sheet '{sheet_name}' 提取了 {len(sheet_images)} 张图片")
workbook.close()
return all_images
except Exception as e:
print(f"提取图片失败: {e}")
return {}
def read_excel_with_images(file_path, start_row=2, output_dir="excel_images"):
"""
读取Excel文件并提取图片
Args:
file_path (str): Excel文件路径
start_row (int): 开始读取的行号
output_dir (str): 图片保存目录
Returns:
tuple: (数据字典, 图片信息字典)
"""
try:
import openpyxl
print(f"正在读取Excel文件: {file_path}")
print("=" * 50)
# 读取数据
workbook = openpyxl.load_workbook(file_path, data_only=True)
sheet_names = workbook.sheetnames
all_data = {}
all_images = {}
image_counter = 1
# 创建图片保存目录
if os.path.exists(output_dir):
shutil.rmtree(output_dir)
os.makedirs(output_dir, exist_ok=True)
for sheet_name in sheet_names:
print(f"\n处理sheet: {sheet_name}")
print("-" * 30)
sheet = workbook[sheet_name]
# 读取数据
data_rows = []
row_count = 0
for row in sheet.iter_rows(min_row=start_row, values_only=True):
row_count += 1
row_data = []
for cell in row:
if cell is None:
row_data.append("")
else:
row_data.append(str(cell))
if not all(cell.strip() == '' for cell in row_data):
data_rows.append(row_data)
all_data[sheet_name] = data_rows
# 提取图片
sheet_images = []
for image in sheet._images:
try:
import io
from PIL import Image
# 获取图片数据
image_data = image._data()
# 创建PIL图片对象
pil_image = Image.open(io.BytesIO(image_data))
# 生成图片文件名
image_filename = f"{sheet_name}_image_{image_counter:03d}.png"
image_path = os.path.join(output_dir, image_filename)
# 保存图片
pil_image.save(image_path, 'PNG')
# 获取图片位置
anchor = image.anchor
if hasattr(anchor, '_from'):
row = anchor._from.row + 1
col = anchor._from.col + 1
else:
row = 1
col = 1
image_info = {
'filename': image_filename,
'path': image_path,
'sheet': sheet_name,
'row': row,
'col': col,
'size': pil_image.size,
'format': pil_image.format
}
sheet_images.append(image_info)
print(f" 保存图片: {image_filename} (位置: 行{row}, 列{col})")
image_counter += 1
except Exception as e:
print(f" 处理图片时出错: {e}")
continue
all_images[sheet_name] = sheet_images
print(f" 数据行数: {len(data_rows)}")
print(f" 图片数量: {len(sheet_images)}")
workbook.close()
return all_data, all_images
except Exception as e:
print(f"读取Excel失败: {e}")
return {}, {}
def create_data_with_images(data, images):
"""
将图片信息关联到数据数组中
Args:
data (dict): 数据字典
images (dict): 图片信息字典
Returns:
dict: 包含图片关联的数据字典
"""
print("\n" + "=" * 50)
print("关联图片信息到数据")
print("=" * 50)
enhanced_data = {}
for sheet_name in data.keys():
print(f"\n处理sheet: {sheet_name}")
print("-" * 30)
sheet_data = data[sheet_name]
sheet_images = images.get(sheet_name, [])
# 为每行数据添加关联的图片信息
enhanced_sheet_data = []
for row_idx, row_data in enumerate(sheet_data):
# 计算实际行号(从第二行开始)
actual_row = row_idx + 2
# 查找该行关联的图片
row_images = []
for img_info in sheet_images:
if img_info['row'] == actual_row:
row_images.append({
'filename': img_info['filename'],
'path': img_info['path'],
'size': img_info['size'],
'col': img_info['col']
})
# 创建增强的行数据
enhanced_row = {
'row_number': actual_row,
'data': row_data,
'images': row_images,
'image_count': len(row_images)
}
enhanced_sheet_data.append(enhanced_row)
if row_images:
print(f" 行 {actual_row}: 关联了 {len(row_images)} 张图片")
for img in row_images:
print(f" - {img['filename']} (列{img['col']})")
enhanced_data[sheet_name] = enhanced_sheet_data
print(f" Sheet '{sheet_name}': {len(enhanced_sheet_data)} 行数据,{len(sheet_images)} 张图片")
return enhanced_data
def save_enhanced_data(enhanced_data, output_file="enhanced_excel_data.json"):
"""保存增强的数据到JSON文件"""
try:
import json
# 转换为可序列化的格式
serializable_data = {}
for sheet_name, sheet_data in enhanced_data.items():
serializable_data[sheet_name] = []
for row_info in sheet_data:
serializable_data[sheet_name].append({
'row_number': row_info['row_number'],
'data': row_info['data'],
'images': row_info['images'],
'image_count': row_info['image_count']
})
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(serializable_data, f, ensure_ascii=False, indent=2)
print(f"\n增强数据已保存到: {output_file}")
except Exception as e:
print(f"保存数据失败: {e}")
def create_image_index(images, output_file="image_index.txt"):
"""创建图片索引文件"""
try:
with open(output_file, 'w', encoding='utf-8') as f:
f.write("Excel图片索引\n")
f.write("=" * 50 + "\n\n")
total_images = 0
for sheet_name, sheet_images in images.items():
f.write(f"Sheet: {sheet_name}\n")
f.write("-" * 30 + "\n")
if sheet_images:
for img in sheet_images:
f.write(f"文件: {img['filename']}\n")
f.write(f" 位置: 行{img['row']}, 列{img['col']}\n")
f.write(f" 尺寸: {img['size'][0]}x{img['size'][1]}\n")
f.write(f" 格式: {img['format']}\n")
f.write(f" 路径: {img['path']}\n\n")
total_images += 1
else:
f.write("无图片\n\n")
f.write(f"\n总计: {total_images} 张图片\n")
print(f"图片索引已保存到: {output_file}")
except Exception as e:
print(f"创建图片索引失败: {e}")
def main():
"""主函数"""
print("Excel读取工具 - 支持图片提取")
print("=" * 40)
# 查找Excel文件
excel_files = []
for f in os.listdir('.'):
if f.lower().endswith(('.xlsx', '.xls')) and not f.startswith('~$'):
excel_files.append(f)
if not excel_files:
print("当前目录下没有找到Excel文件")
return
print(f"找到 {len(excel_files)} 个Excel文件:")
for i, excel_file in enumerate(excel_files, 1):
print(f"{i}. {excel_file}")
# 选择文件
if len(excel_files) == 1:
selected_file = excel_files[0]
print(f"\n自动选择: {selected_file}")
else:
try:
choice = int(input(f"\n请选择文件 (1-{len(excel_files)}): ")) - 1
selected_file = excel_files[choice]
except (ValueError, IndexError):
selected_file = excel_files[0]
# 安装依赖
install_requirements()
# 读取Excel数据和图片
data, images = read_excel_with_images(selected_file, start_row=2)
if not data:
print("没有读取到任何数据")
return
# 关联图片信息到数据
enhanced_data = create_data_with_images(data, images)
# 保存增强数据
save_enhanced_data(enhanced_data)
# 创建图片索引
create_image_index(images)
# 显示统计信息
print("\n" + "=" * 50)
print("处理完成统计")
print("=" * 50)
total_rows = 0
total_images = 0
for sheet_name in enhanced_data.keys():
sheet_data = enhanced_data[sheet_name]
sheet_images = images.get(sheet_name, [])
rows = len(sheet_data)
img_count = len(sheet_images)
total_rows += rows
total_images += img_count
print(f"Sheet '{sheet_name}': {rows} 行数据, {img_count} 张图片")
print(f"\n总计: {total_rows} 行数据, {total_images} 张图片")
print(f"图片保存目录: excel_images/")
print(f"数据文件: enhanced_excel_data.json")
print(f"图片索引: image_index.txt")
if __name__ == "__main__":
main()
更多推荐


所有评论(0)