如何用Pillow提取图像拍摄时间并构建文件名-时间数组?
搞定Pillow EXIF提取+构建目标数组,一步步来
先帮你把核心概念掰明白,再给你完整的可运行代码,包你看懂!
先搞懂你贴的代码里的关键模块
1. Image._getexif() 到底干啥?
这是Pillow用来读取图片EXIF元数据的方法(新版本更推荐用getexif(),因为_getexif()是私有方法,但功能一致)。它会返回一个字典:
- 键是数字形式的EXIF标签ID(这些是EXIF标准统一规定的,比如36867代表原始拍摄时间)
- 值就是对应标签的内容(比如拍摄时间字符串、相机型号等)
如果图片没有EXIF数据(比如截图、被编辑过的图),它会返回None。
2. PIL.ExifTags.TAGS 是啥?
刚才说的数字标签ID根本看不懂对吧?TAGS就是Pillow给我们准备的「翻译字典」——它把每个数字ID映射成人类能看懂的字符串(比如把36867翻译成"DateTimeOriginal")。代码里的TAGS.get(tag, tag)就是:能翻译就用翻译后的名称,翻译不了就保留原数字,避免报错。
接下来实现你的需求:文件夹图片+文件名+带毫秒的拍摄时间数组
我给你写了完整的代码,每一步都加了注释,你直接改文件夹路径就能用:
from PIL import Image from PIL.ExifTags import TAGS import os def extract_shot_time(image_path): """提取单张图片的拍摄时间(带毫秒)""" try: with Image.open(image_path) as img: # 获取EXIF数据,用getexif()更规范(替代私有方法_getexif()) exif_dict = img.getexif() if not exif_dict: return None # 图片无EXIF数据 # 把数字标签ID转成可读名称 decoded_exif = {} for tag_id, value in exif_dict.items(): tag_name = TAGS.get(tag_id, tag_id) decoded_exif[tag_name] = value # 获取原始拍摄时间和毫秒部分 original_datetime = decoded_exif.get("DateTimeOriginal") subsec_ms = decoded_exif.get("SubsecTimeOriginal", "000") # 无毫秒则补000 if not original_datetime: return None # 无拍摄时间标签 # 格式化时间:从YYYY:MM:DD HH:MM:SS里提取时间部分,拼接毫秒 time_segment = original_datetime.split(" ")[1] # 拿到HH:MM:SS # 两种格式二选一,注释掉不需要的 formatted_time = f"{time_segment}:{subsec_ms}" # hh:mm:ss:msmsms格式 # formatted_time = f"{time_segment.replace(':', '')}{subsec_ms}" # hhmmssmsmsms格式 return formatted_time except Exception as e: print(f"处理图片 {image_path} 时出错:{str(e)}") return None # 替换成你的图片文件夹路径 target_folder = "./your_image_directory" # 初始化目标数组:每个元素是[文件名, 拍摄时间] image_info_array = [] # 遍历文件夹里的所有图片文件 for filename in os.listdir(target_folder): # 筛选常见图片格式,可根据需要添加(比如.heic) if filename.lower().endswith(('.jpg', '.jpeg', '.png', '.tiff', '.bmp')): full_path = os.path.join(target_folder, filename) shot_time = extract_shot_time(full_path) # 成功获取时间才加入数组 if shot_time: image_info_array.append([filename, shot_time]) # 打印结果(或者导出成CSV/Excel都可以) for item in image_info_array: print(f"文件名: {item[0]}, 拍摄时间: {item[1]}")
关键细节说明
- 毫秒处理:
SubsecTimeOriginal标签存的是毫秒的字符串(比如"123"),有些图片可能没有这个标签,所以我们默认补"000",避免空值报错。 - 兼容性:用
getexif()替代_getexif(),因为私有方法可能在未来版本被移除,getexif()是官方推荐的公开方法。 - 异常处理:处理了图片打不开、无EXIF数据等情况,不会因为一张坏图导致整个程序崩溃。
- 格式切换:代码里写了两种时间格式,你注释掉不需要的那个就行。
内容的提问来源于stack exchange,提问作者user2882635
相关产品推荐
相关产品推荐

