利用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\x0
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值