个人图片分类-按照年分文件夹管理 python处理个人图片

这几年拍了很多照片,有60G数据,很乱,想要按照年分文件夹管理保存起来存储到百度云盘去。

python 复制代码
import os
import shutil
from PIL import Image
from PIL.ExifTags import TAGS
import re
import exifread
import datetime
import time
import pillow_heif
import sys
import zipfile


# 注册 HEIF 插件
pillow_heif.register_heif_opener()


# 源目录和目标目录(分别是桌面的两个文件夹,imagessource里面放了原始图片数据,imagesprocess是处理后的结果)
source_dir = os.path.join(os.path.expanduser('~'), 'Desktop', 'imagessource')
target_dir = os.path.join(os.path.expanduser('~'), 'Desktop', 'imagesprocess')


# 创建目标目录
if not os.path.exists(target_dir):
    os.makedirs(target_dir)

# 创建截屏文件夹
screenshot_dir = os.path.join(target_dir, 'screenshots')
if not os.path.exists(screenshot_dir):
    os.makedirs(screenshot_dir)


def extract_year_from_filename(filename):
    # 定义匹配年份的正则表达式模式
    pattern = r'\d{4}'
    # 使用正则表达式在文件名中查找匹配项
    match = re.search(pattern, filename)
    if match:
        # 如果找到匹配项,返回匹配的年份
        return match.group()
    return None

def get_heic_type_file_date(image_path):
    try:
        # 打开图片
        with Image.open(image_path) as image:
            # 获取 EXIF 数据
            exif_data = image.getexif()

            if exif_data is not None:
                # 遍历 EXIF 数据
                for tag, value in exif_data.items():
                    tag_name = TAGS.get(tag)
                    if tag_name == 'DateTime':
                        return value[:4]
    except Exception as e:
        print(f"Error getting EXIF data: {e}")

    return None

def get_creation_date(filename):
    if filename.endswith(('.heic')):
        return get_heic_type_file_date(filename)
    try:
        fd = open(filename, 'rb')
    except:
        print("Cannot open: ", filename)
        raise ReadFailException
    try:
        data = exifread.process_file(fd)
        if data:
            try:
                t = data['EXIF DateTimeOriginal']
                return str(t).replace(":", ".")[:4]
            except:
                print("No exif: ", filename)
                pass
    finally:
        fd.close()
    state = os.stat(filename)
    print("get state", filename)

    fileNameYear = extract_year_from_filename(filename);
    if fileNameYear:
        return str(fileNameYear)
    return time.strftime("%Y", time.localtime(state[-2]))




def is_screenshot(file_name):
    # 简单判断是否为截屏文件,可根据实际情况调整
    patterns = [r'screenshot', r'screencapture', r'snap']
    for pattern in patterns:
        if re.search(pattern, file_name, re.IGNORECASE):
            return True
    return False


# 遍历源目录,分类处理文件
def processFile():
    for root, dirs, files in os.walk(source_dir):
        for file in files:
            file_path = os.path.join(root, file)
            if file.lower().endswith(('.png', '.jpg', '.jpeg','.heic')):
                if is_screenshot(file):
                    shutil.move(file_path, os.path.join(screenshot_dir, file))
                else:
                    year = get_creation_date(file_path)
                    if year:
                        year_dir = os.path.join(target_dir, year)
                        if not os.path.exists(year_dir):
                            os.makedirs(year_dir)
                        shutil.move(file_path, os.path.join(year_dir, file))
                    else:
                        # 如果无法获取拍摄日期,放到一个单独的文件夹
                        unknown_dir = os.path.join(target_dir, 'unknown_date')
                        if not os.path.exists(unknown_dir):
                            os.makedirs(unknown_dir)
                        shutil.move(file_path, os.path.join(unknown_dir, file))
    


def extract_first_heic(livp_path):
    """
    从.livp文件中提取第一张HEIC图片
    
    参数:
        livp_path (str): .livp文件的路径
        output_dir (str): 输出目录(默认当前目录)
        
    返回:
        str: 提取的HEIC文件路径
        
    异常:
        ValueError: 如果文件无效或无HEIC文件
    """
    # 检查文件是否存在
    if not os.path.isfile(livp_path):
        raise FileNotFoundError(f"文件 '{livp_path}' 不存在")
    
    processSucess = False
    
    try:
        with zipfile.ZipFile(livp_path, 'r') as zf:
            # 筛选HEIC文件(不区分大小写)
            heic_files = [
                f for f in zf.namelist() 
                if os.path.splitext(f)[1].lower() == '.heic'
            ]
            
            if not heic_files:
                return
            
            # 按文件名排序(默认升序)
            heic_files.sort()
            first_heic = heic_files[0]
            
            # 提取文件
            livp_dir = os.path.dirname(livp_path)
            zf.extract(first_heic, livp_dir)
            extracted_path = os.path.join(livp_dir, first_heic)


            # 获取livp_path文件名
            livp_filename = os.path.basename(livp_path)
            print(f"LIVP文件名: {livp_filename}")

            # 修改文件名为 aaa.jpg
            new_path = os.path.join(livp_dir, os.path.basename(livp_path) + first_heic)

            if not os.path.exists(new_path):
                os.rename(extracted_path, new_path)
                # 删除 extracted_path 文件
                if os.path.isfile(extracted_path):
                    os.remove(extracted_path)
                extracted_path = new_path
            
            processSucess = True
            # 返回完整路径
            return os.path.abspath(extracted_path)
    
    except zipfile.BadZipFile:
        raise ValueError("无效的LIVP文件(非ZIP格式)")
    finally:
        # 删除原始文件
        if os.path.isfile(livp_path) and processSucess:
            os.remove(livp_path)

# 格式转换文件 :python 提取 .livp 里面的第一张 heic 图片,并且删除原始 .livp 文件
def livp_to_jpgProcess():
    for root, dirs, files in os.walk(source_dir):
        for file in files:
            file_path = os.path.join(root, file)
            if file.lower().endswith(('.livp')):
                extract_first_heic(file_path)
                

# 第一步 提取 .livp 里面的第一张 heic 图片
# livp_to_jpgProcess()
# 第二步处理数据
processFile()


 
相关推荐
海天胜景34 分钟前
HTTP Error 500.31 - Failed to load ASP.NET Core runtime
后端·asp.net
海天胜景37 分钟前
Asp.Net Core IIS发布后PUT、DELETE请求错误405
数据库·后端·asp.net
源码云商2 小时前
Spring Boot + Vue 实现在线视频教育平台
vue.js·spring boot·后端
RunsenLIu4 小时前
基于Django实现的篮球论坛管理系统
后端·python·django
HelloZheQ6 小时前
Go:简洁高效,构建现代应用的利器
开发语言·后端·golang
caihuayuan56 小时前
[数据库之十四] 数据库索引之位图索引
java·大数据·spring boot·后端·课程设计
风象南7 小时前
Redis中6种缓存更新策略
redis·后端
程序员Bears7 小时前
Django进阶:用户认证、REST API与Celery异步任务全解析
后端·python·django
非晓为骁8 小时前
【Go】优化文件下载处理:从多级复制到零拷贝流式处理
开发语言·后端·性能优化·golang·零拷贝
北极象8 小时前
Golang中集合相关的库
开发语言·后端·golang