利用Python将照片按“拍摄日期”分类——包括JPG、PNG、GIF、HEIC

        一切的起因是因为换了新手机 (-,-),旧手机上的照片实在是太多了所以想腾出大部分到PC上面来释放一些存储空间。但是首先出现的问题就是照片有6000多个文件而且全都集中在一起,没有进行任何的分类。

        所以我初步的想法,是按照日期时间进行分类,而且对应到的是【拍摄时间】而非【创建时间、修改时间、访问时间】这三个。如:照片是2019.6.20照的,就根据他的日期给分类到 "盘符:\某文件夹\2019\2019-06\"这个目录下。

        那么接下来就直接动工了。首先我使用的还是自己熟悉的Python语言来进行,因为毕竟python三方所提供的各类库能够提供许多方便。

        那么先要安装PIL库(Python Image Library):Pillow库是一个用于图像处理的第三方库,它支持多种图像格式,并提供了一系列图像处理功能,如图像存储、显示、缩放、裁剪、叠加以及图像的基本处理(如像素操作)、颜色处理等。调出CMD命令行执行安装:

pip install pillow
  • 处理PNG, JPG, GIF为扩展名的文件


        在PIL库里面我们主要是要应用到里面的“ExifTags”模块,这个模块公开了几个 enum.IntEnum 类,这些类为各种常见的EXIF标记提供常量和明文名称。而照片的各类元信息(Exif)头部插入了数码照片的信息,包括拍摄时的光圈、快门、白平衡、ISO、焦距、日期时间等各种和拍摄条件以及相机品牌、型号、色彩编码、拍摄时录制的声音以及GPS全球定位系统数据、缩略图等。

        接下来就开始编码了,我们先导入几个库再编写一个函数

from PIL import Image
from PIL.ExifTags import TAGS
import os

# image_path为传入的路径字符参数
def get_datetime_original(image_path):

#   打开文件
    image = Image.open(image_path)
#   读取exif内容
    exif_data = image._getexif()
    

    if exif_data is None:
        return None
    
# 设置两个变量tag_id和value,分别获取exif里面对应的‘信息名称’和‘具体数据’
    for tag_id, value in exif_data.items():
        tag_name = TAGS.get(tag_id, tag_id)
# 获取里面的“DateTimeOriginal”信息名称,该元数据就是“拍摄日期”
        if tag_name == 'DateTimeOriginal':
            return value
            image.close()
    return None
    image.close()

        通过这个函数我们就可以返回某个照片文件的“拍摄日期”。

        再往下,我们设置路径folder_path,和一个空列表file_names。并且通过os库来相应地读取在folder_path路径下所有的文件名称(含扩展名)。并且把它们append到列表file_names上. 再设置一个循环来遍历列表内的文件名称, 判断文件的扩展名是否是 PNG, JPG, GIF 结尾的文件

        之后根据创建好的函数get_datetime_original获取对应文件的拍摄日期, 使用os库来创建和判断路径是否存在, 再使用os.path.join()函数来拼接路径, 根据完整路径month_dir,利用os.rename()函数把原路径下的文件移动到new_file_path新路径下.

# 设置照片所在路径,和一个空列表file_names
folder_path = "E:/照片备份/"
file_names = []

# 通过os库来相应地读取在folder_path路径下所有的文件名称(含扩展名)
# 并且把它们append到列表file_names上
for file in os.listdir(folder_path):
    if not os.path.isdir(os.path.join(folder_path, file)):
        file_names.append(file)
        
print("该文件夹下的所有文件名如下:")
# 计数变量x
x = 0

# 设置一个循环来遍历列表内的文件名称
for name in file_names:
#   判断当前文件的扩展名是否是 PNG, JPG, GIF 结尾的文件
    if any([name.endswith(ext) for ext in [".PNG", ".png", ".JPG", ".jpg", ".GIF", ".gif"]]):
        x += 1
#       根据照片名称来完整一下路径  
        datetime_original = get_datetime_original("E:/照片备份/"+ name)
        if datetime_original:
#           如果文件没问题那就print出【文件名,拍摄时间,计数x】  
            print(name,"【拍摄时间】", datetime_original,x)
#           再print出对应的拍摄时间,由于时间字符都是固定格式的,所以我直接利用字符切分方法切分出年月
            print('Year:',datetime_original[0:4],'Month:',datetime_original[5:7])
    
#           接下来就是设置按年月分出的文件夹路径了
#           我们使用os库来创建和判断路径是否存在,先设置年月的字符变量year和month
            year = datetime_original[0:4]
            month = year + "-" + datetime_original[5:7]
#           使用os.path.join()函数来拼接路径,路径应该以字符串形式传递
            year_dir = os.path.join(folder_path, year)
            month_dir = os.path.join(year_dir, month)
#           如果路径不存在则使用os.mkdir()创建路径
            if not os.path.exists(year_dir):
                os.mkdir(year_dir)
            if not os.path.exists(month_dir):
                os.mkdir(month_dir)
#           如果路径没问题则根据完整路径month_dir,利用os.rename()函数把原路径下的文件移动到new_file_path新路径下.      
            new_file_path = os.path.join(month_dir, os.path.basename(name))
            os.rename("E:/照片备份/"+ name, new_file_path)
        else:
            print('未找到拍摄日期和时间信息')
    else:
#       跳过异常  
        continue

        至此如果你的代码可以完整运行, 那么对于PNG, JPG, GIF格式的文件分类应该已经完成了。那接下来就是要处理 HEIC 这个鬼屎的照片格式了。

  • 处理HEIC格式文件


        为什么单独把HEIC格式文件单拎出来讲, 是因为windows上python的各类第三方库都不能够完整兼容地处理HEIC. 在MacOS上有pyheif这个库可以处理但是windows上不行,所以需要单独找一种方法来处理。

        我所使用的方法大致与刚才无异,但是需要多做几个步骤。第一还是先要安装两个库“pillow_heif”和“exifread”

pip install pillow_heif
pip install exifread

        然后我们测试着做一下如下代码

from PIL import Image
from pillow_heif import register_heif_opener
import io
import exifread


# 创建register_heif_opener模块里的一个类然后再Image.open打开HEIC文件
register_heif_opener()
# 打开你自己的HEIC照片文件
image = Image.open("E:/iPhone照片备份/2018/2018-04/IMG_0186.HEIC")
# image.info里存放着照片的各类信息数据,当然也包括exif信息
print(image.info)

        之后可以得到如下的输出内容:

{'primary': True, 'bit_depth': 8, 'exif': b'Exif\x00\x00MM\x00*\x00\x00\x00\x08\x00\x0b\x01\x0f\x00\x02\x00\x00\x00\x06\x00\x00\x00\x92\x01\x10\x00\x02\x00\x00\x00\t\x00\x00\x00\x98\x01\x12\x00\x03\x00\x00\x00\x01\x00\x01\x00\x00\x01\x1a\x00\x05\x00\x00\x00\x01\x00\x00\x00\xa2\x01\x1b\x00\x05\x00\x00\x00\x01\x00\x00\x00\xaa\x01(\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\x011\x00\x02\x00\x00\x00\x07\x00\x00\x00\xb2\x012\x00\x02\x00\x00\x00\x14\x00\x00\x00\xba\x02\x13\x00\x03\x00\x00\x00\x01\x00\x01\x00\x00\x87i\x00\x04\x00\x00\x00\x01\x00\x00\x00\xce\x88%\x00\x04\x00\x00\x00\x01\x00\x00\x06\xc2\x00\x00\x00\x00Apple\x00iPhone X\x00\x00\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00H\x00\x00\x00\x0111.2.6\x00\x002018:04:29 13:20:43\x00\x00!\x82\x9a\x00\x05\x00\x00\x00\x01\x00\x00\x02`\x82\x9d\x00\x05\x00\x00\x00\x01\x00\x00\x02h\x88"\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\x88\'\x00\x03\x00\x00\x00\x01\x00\x14\x00\x00\x90\x00\x00\x07\x00\x00\x00\x040221\x90\x03\x00\x02\x00\x00\x00\x14\x00\x00\x02p\x90\x04\x00\x02\x00\x00\x00\x14\x00\x00\x02\x84\x91\x01\x00\x07\x00\x00\x00\x04\x01\x02\x03\x00\x92\x01\x00\n\x00\x00\x00\x01\x00\x00\x02\x98\x92\x02\x00\x05\x00\x00\x00\x01\x00\x00\x02\xa0\x92\x03\x00\n\x00\x00\x00\x01\x00\x00\x02\xa8\x92\x04\x00\n\x00\x00\x00\x01\x00\x00\x02\xb0\x92\x07\x00\x03\x00\x00\x00\x01\x00\x05\x00\x00\x92\t\x00\x03\x00\x00\x00\x01\x00\x10\x00\x00\x92\n\x00\x05\x00\x00\x00\x01\x00\x00\x02\xb8\x92\x14\x00\x03\x00\x00\x00\x04\x00\x00\x02\xc0\x92|\x00\x07\x00\x00\x03\xb0\x00\x00\x02\xc8\x92\x91\x00\x02\x00\x00\x00\x04021\x00\x92\x92\x00\x02\x00\x00\x00\x04021\x00\xa0\x00\x00\x07\x00\x00\x00\x040100\xa0\x01\x00\x03\x00\x00\x00\x01\xff\xff\x00\x00\xa0\x02\x00\x04\x00\x00\x00\x01\x00\x00\x0f\xc0\xa0\x03\x00\x04\x00\x00\x00\x01\x00\x00\x0b\xd0\xa2\x17\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\xa3\x01\x00\x07\x00\x00\x00\x01\x01\x00\x00\x00\xa4\x01\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\xa4\x02\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\xa4\x03\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\xa4\x05\x00\x03\x00\x00\x00\x01\x00\x1c\x00\x00\xa4\x06\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\xa42\x00\x05\x00\x00\x00\x04\x00\x00\x06x\xa43\x00\x02\x00\x00\x00\x06\x00\x00\x06\x98\xa44\x00\x02\x00\x00\x00$\x00\x00\x06\x9e\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x01\\\x00\x00\x00\t\x00\x00\x00\x052018:04:29 13:20:43\x002018:04:29 13:20:43\x00\x00\x00\x16\xb8\x00\x00\x02\xb1\x00\x00\x08o\x00\x00\x04\xf9\x00\x00$8\x00\x00\x04\xa5\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x01\t\xa1\x08\xf3\x01\xf8\x01\xf5Apple iOS\x00\x00\x01MM\x00\x12\x00\x01\x00\t\x00\x00\x00\x01\x00\x00\x00\t\x00\x02\x00\x07\x00\x00\x02.\x00\x00\x00\xec\x00\x03\x00\x07\x00\x00\x00h\x00\x00\x03\x1a\x00\x04\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x05\x00\t\x00\x00\x00\x01\x00\x00\x00\xc1\x00\x06\x00\t\x00\x00\x00\x01\x00\x00\x00\xb1\x00\x07\x00\t\x00\x00\x00\x01\x00\x00\x00\x01\x00\x08\x00\n\x00\x00\x00\x03\x00\x00\x03\x82\x00\n\x00\t\x00\x00\x00\x01\x00\x00\x00\x02\x00\x0c\x00\n\x00\x00\x00\x02\x00\x00\x03\x9a\x00\r\x00\t\x00\x00\x00\x01\x00\x00\x00\x1c\x00\x0e\x00\t\x00\x00\x00\x01\x00\x00\x00\x04\x00\x10\x00\t\x00\x00\x00\x01\x00\x00\x00\x01\x00\x14\x00\t\x00\x00\x00\x01\x00\x00\x00\x03\x00\x17\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x19\x00\t\x00\x00\x00\x01\x00\x00\x00\x02\x00\x1a\x00\x02\x00\x00\x00\x06\x00\x00\x03\xaa\x00\x1f\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00bplist00O\x11\x02\x00=\x01\x1d\x03M\x05\x0f\x03\xa9\x00\xaa\x00\xbb\x00\xbf\x00\xb1\x00\x02\x02\x91\x02\xc3\x02\x96\x01}\x01\xa0\x01n\x01\xd4\x00\x8c\x01V\x04\x88\x03\x9b\x00\x98\x00\xa0\x00\xab\x00\xa5\x005\x01\xf4\x01\r\x01\xe1\x00\x13\x01g\x01Y\x01\x96\x00\xec\x00\xbb\x02\xcc\x03\x7f\x00v\x00\x84\x00\x88\x00\x9c\x00H\x01\x1f\x02\xd6\x00\xb8\x00\xe3\x00\x1a\x01\xd9\x00\x81\x00\xca\x00\xf5\x01`\x03p\x00i\x00z\x00\x7f\x00\x91\x00\xd2\x00*\x01\xb4\x00\xa7\x00\xa0\x00\xc1\x00@\x01{\x00\x88\x00\xb0\x00\x0f\x01}\x00k\x00t\x00o\x00\x87\x00\xd8\x00S\x01\xb6\x00\xb4\x00u\x00\x9c\x00\x07\x01\x84\x00\xd8\x00\xbc\x00\x83\x00\x87\x00o\x00y\x00\x82\x00\x99\x00\n\x01\xfb\x00\x17\x01\xb0\x00\x80\x00w\x00\x92\x00\x8c\x00\xcc\x00\x9b\x00\x9e\x00\x8d\x00\x84\x00\xdd\x00\xb9\x00\xa5\x00\xfc\x00\xe6\x00\xd2\x00\xf2\x00\xa3\x00\x99\x00\xd7\x00y\x00n\x00\x9c\x00\xaa\x00\xd7\x00\x9e\x00!\x01\xe4\x00\xde\x00\x9c\x00H\x01\xc8\x00\xdb\x00\xe2\x00\xc6\x00\xa4\x00o\x00\xbc\x00_\x01\x9c\x00\xa5\x00\xfd\x00]\x01\xbc\x00\xcf\x00\x8d\x00\xcd\x00o\x00\x9d\x00&\x01\xd3\x00\x96\x00\xb9\x00\xca\x00\xc1\x00\xec\x00\xb6\x00\x01\x01\xdb\x00\xab\x00\xaa\x00\x0b\x01\xe7\x00\x84\x00\xf7\x00\xd2\x00!\x01\x8d\x00U\x01k\x00\x92\x00\xbf\x00\xb4\x00\x10\x01\x8f\x01\xb1\x009\x01f\x01\xce\x00\xaf\x00\xa3\x00\xd5\x00\'\x01\r\x01$\x01D\x00\x85\x00\xe5\x00\xa4\x00\xb6\x00\xd8\x00\xe1\x00\x1e\x01\xe2\x00]\x00\x9f\x00q\x00\xa7\x00\x1f\x01V\x01\x8f\x00E\x00\xbf\x00\xec\x00b\x00R\x00k\x00\xe8\x00\xf8\x00\xda\x00b\x00W\x008\x00t\x00\xa9\x00\xc6\x00O\x00v\x00\xfc\x00\xf9\x00:\x008\x00H\x00\xa6\x00\xeb\x00\xaa\x00\x8b\x00W\x00.\x00U\x00f\x00a\x00I\x00\xa7\x00O\x00\x14\x01/\x00-\x001\x00\x96\x00\xbd\x00\xb5\x00\x82\x00N\x00?\x00\xad\x00O\x00H\x00b\x00\xa6\x00v\x00\xdc\x00\'\x00*\x00+\x00\xac\x00\xe6\x00\xc6\x00f\x00j\x00\x8b\x00\xc4\x00P\x005\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x0cbplist00\xd4\x01\x02\x03\x04\x05\x06\x07\x08UflagsUvalueYtimescaleUepoch\x10\x01\x13\x00\x00xYpr\xa3\x0c\x12;\x9a\xca\x00\x10\x00\x08\x11\x17\x1d\'-/8=\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xff\xff\xf5\xf9\x00\x00\n\x1b\xff\xff\xfd\x15\x00\x00\x1b\x08\xff\xff\xfd\xc1\x00\x00\x11t\x00\x00\x0cg\x00\x00\x01\x00\x00\x00\n\xf9\x00\x00\x00\x80q825s\x00\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00\t\x00\x00\x00\x05\x00\x00\x00\x0c\x00\x00\x00\x05Apple\x00iPhone X back dual camera 4mm f/1.8\x00\x00\x0f\x00\x01\x00\x02\x00\x00\x00\x02N\x00\x00\x00\x00\x02\x00\x05\x00\x00\x00\x03\x00\x00\x07|\x00\x03\x00\x02\x00\x00\x00\x02W\x00\x00\x00\x00\x04\x00\x05\x00\x00\x00\x03\x00\x00\x07\x94\x00\x05\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x06\x00\x05\x00\x00\x00\x01\x00\x00\x07\xac\x00\x07\x00\x05\x00\x00\x00\x03\x00\x00\x07\xb4\x00\x0c\x00\x02\x00\x00\x00\x02K\x00\x00\x00\x00\r\x00\x05\x00\x00\x00\x01\x00\x00\x07\xcc\x00\x10\x00\x02\x00\x00\x00\x02T\x00\x00\x00\x00\x11\x00\x05\x00\x00\x00\x01\x00\x00\x07\xd4\x00\x17\x00\x02\x00\x00\x00\x02T\x00\x00\x00\x00\x18\x00\x05\x00\x00\x00\x01\x00\x00\x07\xdc\x00\x1d\x00\x02\x00\x00\x00\x0b\x00\x00\x07\xe4\x00\x1f\x00\x05\x00\x00\x00\x01\x00\x00\x07\xf0\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00\x01\x00\x00\x000\x00\x00\x00\x01\x00\x00\n0\x00\x00\x00d\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00!\x00\x00\x00\x01\x00\x00\x07\xa5\x00\x00\x00d\x00\x00{[\x00\x00\x01}\x00\x00\x00\x0c\x00\x00\x00\x01\x00\x00\x00\x14\x00\x00\x00\x01\x00\x00\x10\x03\x00\x00\x00d\x00\x00\t\xb6\x00\x00\x14\xf7\x00\x00\n   \n      \n         \n            \n               \n                  \n                     \n                        0.75800000000000001\n                        0.125\n                        0.61150000000000004\n                        0.16600000000000004\n                        normalized\n                     \n                     Face\n                     \n                        90\n                        0\n                        402\n                        3175810256281\n                        45\n                     \n                  \n                  \n                     \n                        0.49650000000000005\n                        0.070999999999999952\n                        0.50849999999999995\n                        0.095000000000000029\n                        normalized\n                     \n                     Face\n                     \n                        315\n                        0\n                        420\n                        3175810256281\n                        44\n                     \n                  \n                  \n                     \n                        0.56150000000000011\n                        0.03999999999999998\n                        0.29400000000000004\n                        0.053000000000000047\n                        normalized\n                     \n                     Face\n                     \n                        0\n                        330\n                        459\n                        3175810256281\n                        43\n                     \n                  \n                  \n                     \n                        0.54800000000000004\n                        0.059999999999999942\n                        0.6339999999999999\n                        0.07999999999999996\n                        normalized\n                     \n                     Face\n                     \n                        45\n                        0\n                        694\n                        3175810256281\n                        46\n                     \n                  \n               \n            \n            \n               3024\n               4032\n               pixel\n            \n         \n      \n   \n\n', 'metadata': [], 'thumbnails': [320], 'depth_images': [], 'icc_profile': b'\x00\x00\x02$appl\x04\x00\x00\x00mntrRGB XYZ \x07\xe1\x00\x07\x00\x07\x00\r\x00\x16\x00 acspAPPL\x00\x00\x00\x00APPL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3-appl\xca\x1a\x95\x82%\x7f\x10M8\x99\x13\xd5\xd1\xea\x15\x82\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ndesc\x00\x00\x00\xfc\x00\x00\x00ecprt\x00\x00\x01d\x00\x00\x00#wtpt\x00\x00\x01\x88\x00\x00\x00\x14rXYZ\x00\x00\x01\x9c\x00\x00\x00\x14gXYZ\x00\x00\x01\xb0\x00\x00\x00\x14bXYZ\x00\x00\x01\xc4\x00\x00\x00\x14rTRC\x00\x00\x01\xd8\x00\x00\x00 chad\x00\x00\x01\xf8\x00\x00\x00,bTRC\x00\x00\x01\xd8\x00\x00\x00 gTRC\x00\x00\x01\xd8\x00\x00\x00 desc\x00\x00\x00\x00\x00\x00\x00\x0bDisplay P3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00text\x00\x00\x00\x00Copyright Apple Inc., 2017\x00\x00XYZ \x00\x00\x00\x00\x00\x00\xf3Q\x00\x01\x00\x00\x00\x01\x16\xccXYZ \x00\x00\x00\x00\x00\x00\x83\xdf\x00\x00=\xbf\xff\xff\xff\xbbXYZ \x00\x00\x00\x00\x00\x00J\xbf\x00\x00\xb17\x00\x00\n\xb9XYZ \x00\x00\x00\x00\x00\x00(8\x00\x00\x11\x0b\x00\x00\xc8\xb9para\x00\x00\x00\x00\x00\x03\x00\x00\x00\x02ff\x00\x00\xf2\xa7\x00\x00\rY\x00\x00\x13\xd0\x00\x00\n[sf32\x00\x00\x00\x00\x00\x01\x0cB\x00\x00\x05\xde\xff\xff\xf3&\x00\x00\x07\x93\x00\x00\xfd\x90\xff\xff\xfb\xa2\xff\xff\xfd\xa3\x00\x00\x03\xdc\x00\x00\xc0n', 'icc_profile_type': 'prof', 'original_orientation': None}

        我们不难发现这里明显存在着“exif”这个字眼,那就好说了,直接获取它:

print(image.info["exif"])

        输出后我们又得到如下的内容数据:

b'Exif\x00\x00MM\x00*\x00\x00\x00\x08\x00\x0b\x01\x0f\x00\x02\x00\x00\x00\x06\x00\x00\x00\x92\x01\x10\x00\x02\x00\x00\x00\t\x00\x00\x00\x98\x01\x12\x00\x03\x00\x00\x00\x01\x00\x01\x00\x00\x01\x1a\x00\x05\x00\x00\x00\x01\x00\x00\x00\xa2\x01\x1b\x00\x05\x00\x00\x00\x01\x00\x00\x00\xaa\x01(\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\x011\x00\x02\x00\x00\x00\x07\x00\x00\x00\xb2\x012\x00\x02\x00\x00\x00\x14\x00\x00\x00\xba\x02\x13\x00\x03\x00\x00\x00\x01\x00\x01\x00\x00\x87i\x00\x04\x00\x00\x00\x01\x00\x00\x00\xce\x88%\x00\x04\x00\x00\x00\x01\x00\x00\x06\xc2\x00\x00\x00\x00Apple\x00iPhone X\x00\x00\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00H\x00\x00\x00\x0111.2.6\x00\x002018:04:29 13:20:43\x00\x00!\x82\x9a\x00\x05\x00\x00\x00\x01\x00\x00\x02`\x82\x9d\x00\x05\x00\x00\x00\x01\x00\x00\x02h\x88"\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\x88\'\x00\x03\x00\x00\x00\x01\x00\x14\x00\x00\x90\x00\x00\x07\x00\x00\x00\x040221\x90\x03\x00\x02\x00\x00\x00\x14\x00\x00\x02p\x90\x04\x00\x02\x00\x00\x00\x14\x00\x00\x02\x84\x91\x01\x00\x07\x00\x00\x00\x04\x01\x02\x03\x00\x92\x01\x00\n\x00\x00\x00\x01\x00\x00\x02\x98\x92\x02\x00\x05\x00\x00\x00\x01\x00\x00\x02\xa0\x92\x03\x00\n\x00\x00\x00\x01\x00\x00\x02\xa8\x92\x04\x00\n\x00\x00\x00\x01\x00\x00\x02\xb0\x92\x07\x00\x03\x00\x00\x00\x01\x00\x05\x00\x00\x92\t\x00\x03\x00\x00\x00\x01\x00\x10\x00\x00\x92\n\x00\x05\x00\x00\x00\x01\x00\x00\x02\xb8\x92\x14\x00\x03\x00\x00\x00\x04\x00\x00\x02\xc0\x92|\x00\x07\x00\x00\x03\xb0\x00\x00\x02\xc8\x92\x91\x00\x02\x00\x00\x00\x04021\x00\x92\x92\x00\x02\x00\x00\x00\x04021\x00\xa0\x00\x00\x07\x00\x00\x00\x040100\xa0\x01\x00\x03\x00\x00\x00\x01\xff\xff\x00\x00\xa0\x02\x00\x04\x00\x00\x00\x01\x00\x00\x0f\xc0\xa0\x03\x00\x04\x00\x00\x00\x01\x00\x00\x0b\xd0\xa2\x17\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\xa3\x01\x00\x07\x00\x00\x00\x01\x01\x00\x00\x00\xa4\x01\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\xa4\x02\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\xa4\x03\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\xa4\x05\x00\x03\x00\x00\x00\x01\x00\x1c\x00\x00\xa4\x06\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\xa42\x00\x05\x00\x00\x00\x04\x00\x00\x06x\xa43\x00\x02\x00\x00\x00\x06\x00\x00\x06\x98\xa44\x00\x02\x00\x00\x00$\x00\x00\x06\x9e\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x01\\\x00\x00\x00\t\x00\x00\x00\x052018:04:29 13:20:43\x002018:04:29 13:20:43\x00\x00\x00\x16\xb8\x00\x00\x02\xb1\x00\x00\x08o\x00\x00\x04\xf9\x00\x00$8\x00\x00\x04\xa5\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x01\t\xa1\x08\xf3\x01\xf8\x01\xf5Apple iOS\x00\x00\x01MM\x00\x12\x00\x01\x00\t\x00\x00\x00\x01\x00\x00\x00\t\x00\x02\x00\x07\x00\x00\x02.\x00\x00\x00\xec\x00\x03\x00\x07\x00\x00\x00h\x00\x00\x03\x1a\x00\x04\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x05\x00\t\x00\x00\x00\x01\x00\x00\x00\xc1\x00\x06\x00\t\x00\x00\x00\x01\x00\x00\x00\xb1\x00\x07\x00\t\x00\x00\x00\x01\x00\x00\x00\x01\x00\x08\x00\n\x00\x00\x00\x03\x00\x00\x03\x82\x00\n\x00\t\x00\x00\x00\x01\x00\x00\x00\x02\x00\x0c\x00\n\x00\x00\x00\x02\x00\x00\x03\x9a\x00\r\x00\t\x00\x00\x00\x01\x00\x00\x00\x1c\x00\x0e\x00\t\x00\x00\x00\x01\x00\x00\x00\x04\x00\x10\x00\t\x00\x00\x00\x01\x00\x00\x00\x01\x00\x14\x00\t\x00\x00\x00\x01\x00\x00\x00\x03\x00\x17\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x19\x00\t\x00\x00\x00\x01\x00\x00\x00\x02\x00\x1a\x00\x02\x00\x00\x00\x06\x00\x00\x03\xaa\x00\x1f\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00bplist00O\x11\x02\x00=\x01\x1d\x03M\x05\x0f\x03\xa9\x00\xaa\x00\xbb\x00\xbf\x00\xb1\x00\x02\x02\x91\x02\xc3\x02\x96\x01}\x01\xa0\x01n\x01\xd4\x00\x8c\x01V\x04\x88\x03\x9b\x00\x98\x00\xa0\x00\xab\x00\xa5\x005\x01\xf4\x01\r\x01\xe1\x00\x13\x01g\x01Y\x01\x96\x00\xec\x00\xbb\x02\xcc\x03\x7f\x00v\x00\x84\x00\x88\x00\x9c\x00H\x01\x1f\x02\xd6\x00\xb8\x00\xe3\x00\x1a\x01\xd9\x00\x81\x00\xca\x00\xf5\x01`\x03p\x00i\x00z\x00\x7f\x00\x91\x00\xd2\x00*\x01\xb4\x00\xa7\x00\xa0\x00\xc1\x00@\x01{\x00\x88\x00\xb0\x00\x0f\x01}\x00k\x00t\x00o\x00\x87\x00\xd8\x00S\x01\xb6\x00\xb4\x00u\x00\x9c\x00\x07\x01\x84\x00\xd8\x00\xbc\x00\x83\x00\x87\x00o\x00y\x00\x82\x00\x99\x00\n\x01\xfb\x00\x17\x01\xb0\x00\x80\x00w\x00\x92\x00\x8c\x00\xcc\x00\x9b\x00\x9e\x00\x8d\x00\x84\x00\xdd\x00\xb9\x00\xa5\x00\xfc\x00\xe6\x00\xd2\x00\xf2\x00\xa3\x00\x99\x00\xd7\x00y\x00n\x00\x9c\x00\xaa\x00\xd7\x00\x9e\x00!\x01\xe4\x00\xde\x00\x9c\x00H\x01\xc8\x00\xdb\x00\xe2\x00\xc6\x00\xa4\x00o\x00\xbc\x00_\x01\x9c\x00\xa5\x00\xfd\x00]\x01\xbc\x00\xcf\x00\x8d\x00\xcd\x00o\x00\x9d\x00&\x01\xd3\x00\x96\x00\xb9\x00\xca\x00\xc1\x00\xec\x00\xb6\x00\x01\x01\xdb\x00\xab\x00\xaa\x00\x0b\x01\xe7\x00\x84\x00\xf7\x00\xd2\x00!\x01\x8d\x00U\x01k\x00\x92\x00\xbf\x00\xb4\x00\x10\x01\x8f\x01\xb1\x009\x01f\x01\xce\x00\xaf\x00\xa3\x00\xd5\x00\'\x01\r\x01$\x01D\x00\x85\x00\xe5\x00\xa4\x00\xb6\x00\xd8\x00\xe1\x00\x1e\x01\xe2\x00]\x00\x9f\x00q\x00\xa7\x00\x1f\x01V\x01\x8f\x00E\x00\xbf\x00\xec\x00b\x00R\x00k\x00\xe8\x00\xf8\x00\xda\x00b\x00W\x008\x00t\x00\xa9\x00\xc6\x00O\x00v\x00\xfc\x00\xf9\x00:\x008\x00H\x00\xa6\x00\xeb\x00\xaa\x00\x8b\x00W\x00.\x00U\x00f\x00a\x00I\x00\xa7\x00O\x00\x14\x01/\x00-\x001\x00\x96\x00\xbd\x00\xb5\x00\x82\x00N\x00?\x00\xad\x00O\x00H\x00b\x00\xa6\x00v\x00\xdc\x00\'\x00*\x00+\x00\xac\x00\xe6\x00\xc6\x00f\x00j\x00\x8b\x00\xc4\x00P\x005\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x0cbplist00\xd4\x01\x02\x03\x04\x05\x06\x07\x08UflagsUvalueYtimescaleUepoch\x10\x01\x13\x00\x00xYpr\xa3\x0c\x12;\x9a\xca\x00\x10\x00\x08\x11\x17\x1d\'-/8=\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xff\xff\xf5\xf9\x00\x00\n\x1b\xff\xff\xfd\x15\x00\x00\x1b\x08\xff\xff\xfd\xc1\x00\x00\x11t\x00\x00\x0cg\x00\x00\x01\x00\x00\x00\n\xf9\x00\x00\x00\x80q825s\x00\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00\t\x00\x00\x00\x05\x00\x00\x00\x0c\x00\x00\x00\x05Apple\x00iPhone X back dual camera 4mm f/1.8\x00\x00\x0f\x00\x01\x00\x02\x00\x00\x00\x02N\x00\x00\x00\x00\x02\x00\x05\x00\x00\x00\x03\x00\x00\x07|\x00\x03\x00\x02\x00\x00\x00\x02W\x00\x00\x00\x00\x04\x00\x05\x00\x00\x00\x03\x00\x00\x07\x94\x00\x05\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x06\x00\x05\x00\x00\x00\x01\x00\x00\x07\xac\x00\x07\x00\x05\x00\x00\x00\x03\x00\x00\x07\xb4\x00\x0c\x00\x02\x00\x00\x00\x02K\x00\x00\x00\x00\r\x00\x05\x00\x00\x00\x01\x00\x00\x07\xcc\x00\x10\x00\x02\x00\x00\x00\x02T\x00\x00\x00\x00\x11\x00\x05\x00\x00\x00\x01\x00\x00\x07\xd4\x00\x17\x00\x02\x00\x00\x00\x02T\x00\x00\x00\x00\x18\x00\x05\x00\x00\x00\x01\x00\x00\x07\xdc\x00\x1d\x00\x02\x00\x00\x00\x0b\x00\x00\x07\xe4\x00\x1f\x00\x05\x00\x00\x00\x01\x00\x00\x07\xf0\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00\x01\x00\x00\x000\x00\x00\x00\x01\x00\x00\n0\x00\x00\x00d\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00!\x00\x00\x00\x01\x00\x00\x07\xa5\x00\x00\x00d\x00\x00{[\x00\x00\x01}\x00\x00\x00\x0c\x00\x00\x00\x01\x00\x00\x00\x14\x00\x00\x00\x01\x00\x00\x10\x03\x00\x00\x00d\x00\x00\t\xb6\x00\x00\x14\xf7\x00\x00

        又一次,很明显地看到输出的内容是【b’ Exif xxxxxxxx...】,那说明输出的Exif数据格式是二进制的,所以后面内容我们看到的都是乱码。那也好说了,我们直接把它二进制解码就可以了,使用io.BytesIO()方法来对二进制进行解码,但是需要注意这里我们要对image.info[exif]的内容进行一点切分,要把【b’Exif】后面的内容进行解码,所以最后要传入io.BytesIO()的参数内容应该是image.info[‘exif’][6:]

fstream = io.BytesIO(image.info["exif"][6:])
print("解码为",fstream)

        解码输出后的内容:

解码为 <_io.BytesIO object at 0x0000012C6394E4F0>

        还没完事,为了看到完整的内容,我们需要使用exifread.process_file()来进一步解码里面的具体数据,所以要确保各位已经安装好了exifread模块

exifdata = exifread.process_file(fstream,details=False)
print(exifdata)

        之后我们就可以看到这个HEIC照片文件的具体元数据信息了:

{'Image Make': (0x010F) ASCII=Apple @ 146, 'Image Model': (0x0110) ASCII=iPhone X @ 152, 'Image Orientation': (0x0112) Short=Horizontal (normal) @ 42, 'Image XResolution': (0x011A) Ratio=72 @ 162, 'Image YResolution': (0x011B) Ratio=72 @ 170, 'Image ResolutionUnit': (0x0128) Short=Pixels/Inch @ 78, 'Image Software': (0x0131) ASCII=11.2.6 @ 178, 'Image DateTime': (0x0132) ASCII=2018:04:29 13:20:43 @ 186, 'Image YCbCrPositioning': (0x0213) Short=Centered @ 114, 'Image ExifOffset': (0x8769) Long=206 @ 126, 'GPS GPSLatitudeRef': (0x0001) ASCII=N @ 1740, 'GPS GPSLatitude': (0x0002) Ratio=[53, 48, 652/25] @ 1916, 'GPS GPSLongitudeRef': (0x0003) ASCII=W @ 1764, 'GPS GPSLongitude': (0x0004) Ratio=[1, 33, 1957/100] @ 1940, 'GPS GPSAltitudeRef': (0x0005) Byte=0 @ 1788, 'GPS GPSAltitude': (0x0006) Ratio=31579/381 @ 1964, 'GPS GPSTimeStamp': (0x0007) Ratio=[12, 20, 4099/100] @ 1972, 'GPS GPSSpeedRef': (0x000C) ASCII=K @ 1824, 'GPS GPSSpeed': (0x000D) Ratio=2486/5367 @ 1996, 'GPS GPSImgDirectionRef': (0x0010) ASCII=T @ 1848, 'GPS GPSImgDirection': (0x0011) Ratio=15466/145 @ 2004, 'GPS GPSDestBearingRef': (0x0017) ASCII=T @ 1872, 'GPS GPSDestBearing': (0x0018) Ratio=15466/145 @ 2012, 'GPS GPSDate': (0x001D) ASCII=2018:04:29 @ 2020, 'GPS Tag 0x001F': (0x001F) Ratio=12 @ 2032, 'Image GPSInfo': (0x8825) Long=1730 @ 138, 'EXIF ExposureTime': (0x829A) Ratio=1/348 @ 608, 'EXIF FNumber': (0x829D) Ratio=9/5 @ 616, 'EXIF ExposureProgram': (0x8822) Short=Program Normal @ 240, 'EXIF ISOSpeedRatings': (0x8827) Short=20 @ 252, 'EXIF ExifVersion': (0x9000) Undefined=0221 @ 264, 'EXIF DateTimeOriginal': (0x9003) ASCII=2018:04:29 13:20:43 @ 624, 'EXIF DateTimeDigitized': (0x9004) ASCII=2018:04:29 13:20:43 @ 644, 'EXIF ComponentsConfiguration': (0x9101) Undefined=YCbCr @ 300, 'EXIF ShutterSpeedValue': (0x9201) Signed Ratio=5816/689 @ 664, 'EXIF ApertureValue': (0x9202) Ratio=2159/1273 @ 672, 'EXIF BrightnessValue': (0x9203) Signed Ratio=9272/1189 @ 680, 'EXIF ExposureBiasValue': (0x9204) Signed Ratio=0 @ 688, 'EXIF MeteringMode': (0x9207) Short=Pattern @ 360, 'EXIF Flash': (0x9209) Short=Flash did not fire, compulsory flash mode @ 372, 'EXIF FocalLength': (0x920A) Ratio=4 @ 696, 'EXIF SubjectArea': (0x9214) Short=[2465, 2291, 504, 501] @ 704, 'EXIF SubSecTimeOriginal': (0x9291) ASCII=021 @ 420, 'EXIF SubSecTimeDigitized': (0x9292) ASCII=021 @ 432, 'EXIF FlashPixVersion': (0xA000) Undefined=0100 @ 444, 'EXIF ColorSpace': (0xA001) Short=Uncalibrated @ 456, 'EXIF ExifImageWidth': (0xA002) Long=4032 @ 468, 'EXIF ExifImageLength': (0xA003) Long=3024 @ 480, 'EXIF SensingMethod': (0xA217) Short=One-chip color area @ 492, 'EXIF SceneType': (0xA301) Undefined=Directly Photographed @ 504, 'EXIF CustomRendered': (0xA401) Short=2 @ 516, 'EXIF ExposureMode': (0xA402) Short=Auto Exposure @ 528, 'EXIF WhiteBalance': (0xA403) Short=Auto @ 540, 'EXIF FocalLengthIn35mmFilm': (0xA405) Short=28 @ 552, 'EXIF SceneCaptureType': (0xA406) Short=Standard @ 564, 'EXIF LensSpecification': (0xA432) Ratio=[4, 6, 9/5, 12/5] @ 1656, 'EXIF LensMake': (0xA433) ASCII=Apple @ 1688, 'EXIF LensModel': (0xA434) ASCII=iPhone X back dual camera 4mm f/1.8 @ 1694}

        好了,到这其实问题差不多就解决了,我们只需要获取这个变量当中【Image DateTime】这个信息就可以了。

imageDateTime = str(exifdata.get("Image DateTime"))
print(imageDateTime)

# 输出结果为: 2018:04:29 13:20:43

完整处理代码:

from PIL import Image
from PIL.ExifTags import TAGS
import pillow_heif
from pillow_heif import register_heif_opener
import io
import exifread
import os
# 创建register_heif_opener模块里的一个类然后再Image.open打开HEIC文件
register_heif_opener()

# 获取HEIC格式文件"拍摄日期"的函数
def get_datetime_original(image_path):
    image = Image.open(image_path)
    fstream = io.BytesIO(image.info["exif"][6:])
    exifdata = exifread.process_file(fstream,details=False)
    imageDateTime = str(exifdata.get("Image DateTime"))
    
    return imageDateTime
    
    

# 后面的内容基本就不变了
folder_path = "E:/照片备份/"
file_names = []
 
for file in os.listdir(folder_path):
    if not os.path.isdir(os.path.join(folder_path, file)):
        file_names.append(file)
        
print("该文件夹下的所有文件名如下:")
x = 0
for name in file_names:
# 只需要在这里改一下for ext in [".HEIC"]就可以了
    if any([name.endswith(ext) for ext in [".HEIC"]]):
        x += 1
        datetime_original = get_datetime_original("E:/照片备份/"+ name)
        if datetime_original:
            print(name,"【时间】", datetime_original,x)
            print('Year:',datetime_original[0:4],'Month:',datetime_original[5:7])
            year = datetime_original[0:4]
            month = year + "-" + datetime_original[5:7]
            year_dir = os.path.join(folder_path, year)
            month_dir = os.path.join(year_dir, month)
            if not os.path.exists(year_dir):
                os.mkdir(year_dir)
            if not os.path.exists(month_dir):
                os.mkdir(month_dir)
            new_file_path = os.path.join(month_dir, os.path.basename(name))
            os.rename("E:/照片备份/"+ name, new_file_path)
        else:
            print('未找到拍摄日期和时间信息')
    else:        
        continue

        到这里所有的对于照片分类处理的方法就完成了,我那天晚上也尝试了很多的方式,只有这种是可以在windows系统下执行的,也希望所有遇到这类问题的小伙伴可以顺利解决。就这样~

Happy coding~!

你可能感兴趣的:(python,开发语言,分类)