公告
  
重要通知:网站网络变更中可能出现站点图片无法加载的问题,点击此处可解决!
更多资讯可访问:点击查看消息详情!

朕已阅

整理大量照片的小工具

admin 千秋月 关注 管理组 论坛神话
发表于程序代码版块 技术杂文

最近我用华为手机助手将手机上的几千张照片导出了电脑,打算好好整理一下。然而,一看到这么多照片需要整理,我就有些头疼了。


于是,我决定用Python编写一个小工具,帮助我按“年月”将照片整理到不同的文件夹中。这样一来,照片管理就变得更加轻松有序。


pillow模块安装命令


pip install pillow


代码:


import os
import shutil
from PIL import Image
from PIL.ExifTags import TAGS
from tkinter import Tk, Button, Label, filedialog, Checkbutton, Text, Scrollbar, BooleanVar, Frame, END

class MediaOrganizer:
    def __init__(self, root):
        self.root = root
        self.root.title("Media Files Organizer")
        self.selected_folder = None
        self.tmp = ""

        self.create_widgets()

    def create_widgets(self):
        # 创建Frame来组织复选框和按钮
        control_frame = Frame(self.root)
        control_frame.pack(pady=10)
        # 创建选择文件夹的按钮
        select_button = Button(control_frame, text="选择文件夹", command=self.select_folder)
        select_button.pack(side='left', padx=5)

        # 创建复选框
        self.audio_var = BooleanVar()
        self.image_var = BooleanVar()
        self.video_var = BooleanVar()

        self.audio_check = Checkbutton(control_frame, text="声音", variable=self.audio_var)
        self.image_check = Checkbutton(control_frame, text="图片", variable=self.image_var)
        self.video_check = Checkbutton(control_frame, text="视频", variable=self.video_var)

        self.audio_check.pack(side='left', padx=5)
        self.image_check.pack(side='left', padx=5)
        self.video_check.pack(side='left', padx=5)

        # 绑定鼠标事件
        self.audio_check.bind("<Enter>", lambda event: self.show_tooltip(event, self.audio_check))
        self.audio_check.bind("<Leave>", self.hide_tooltip)
        self.image_check.bind("<Enter>", lambda event: self.show_tooltip(event, self.image_check))
        self.image_check.bind("<Leave>", self.hide_tooltip)
        self.video_check.bind("<Enter>", lambda event: self.show_tooltip(event, self.video_check))
        self.video_check.bind("<Leave>", self.hide_tooltip)

        # 创建开始按钮
        start_button = Button(control_frame, text="开始整理", command=self.start_organizing)
        start_button.pack(side='left', padx=5)

        # 创建状态标签
        self.status_label = Label(self.root, text="将所选文件夹中的媒体文件按照年月分别整理到不同文件夹(例如 202411)中\n需要媒体文件包含EXIF信息,仅整理所选文件夹中的文件,不包含子文件夹")
        self.status_label.pack(pady=10)

        # 创建文本框
        log_frame = Frame(self.root)
        log_frame.pack(pady=10, fill='both', expand=True)

        self.log_text = Text(log_frame, height=20, width=80)
        self.log_text.pack(side='left', fill='both', expand=True)

        scrollbar = Scrollbar(log_frame, command=self.log_text.yview)
        scrollbar.pack(side='right', fill='y')

        self.log_text.config(yscrollcommand=scrollbar.set)

    def get_exif_data(self, image_path):
        try:
            image = Image.open(image_path)
            exif_data = image._getexif()
            if exif_data is None:
                return None
            exif = {
                TAGS[k]: v
                for k, v in exif_data.items()
                if k in TAGS
            }
            return exif
        except Exception as e:
            self.log_text.insert(END, f"读取EXIF数据失败: {e}\n")

            self.log_text.see(END)
            self.root.update_idletasks()  # 强制更新界面
            return None

    def get_date_taken(self, exif_data):
        return exif_data.get('DateTimeOriginal', None)

    def organize_photos(self, folder_path, file_types):
        for filename in os.listdir(folder_path):
            if any(filename.lower().endswith(ext) for ext in file_types):
                file_path = os.path.join(folder_path, filename)
                exif_data = self.get_exif_data(file_path)
                if exif_data:
                    date_taken = self.get_date_taken(exif_data)
                    if date_taken:
                        year_month = date_taken[:7].replace(':', '')
                        year_month_folder = os.path.join(folder_path, year_month)
                        if not os.path.exists(year_month_folder):
                            os.makedirs(year_month_folder)
                        shutil.move(file_path, os.path.join(year_month_folder, filename))
                        self.log_text.insert(END, f"移动 {filename} 到 {year_month_folder}\n")

                        self.log_text.see(END)
                        self.root.update_idletasks()  # 强制更新界面
                    else:
                        self.log_text.insert(END, f"没有日期数据的文件: {filename}\n")

                        self.log_text.see(END)
                        self.root.update_idletasks()  # 强制更新界面
                else:
                    self.log_text.insert(END, f"没有EXIF的文件: {filename}\n")

                    self.log_text.see(END)
                    self.root.update_idletasks()  # 强制更新界面

    def select_folder(self):
        self.selected_folder = filedialog.askdirectory()
        if self.selected_folder:
            self.status_label.config(text=f"选择了文件夹: {self.selected_folder}")

    def start_organizing(self):
        if self.selected_folder:
            file_types = []
            if self.audio_var.get():
                file_types.extend(['.mp3', '.wav', '.flac', '.aac'])
            if self.image_var.get():
                file_types.extend(['.png', '.jpg', '.jpeg', '.tiff', '.bmp', '.gif'])
            if self.video_var.get():
                file_types.extend(['.mp4', '.avi', '.mov', '.mkv'])

            self.organize_photos(self.selected_folder, file_types)
            self.status_label.config(text=f"{self.selected_folder} 中的文件整理好了。")
        else:
            self.status_label.config(text="请选择一个文件夹。")

    def show_tooltip(self, event, widget):
        self.tmp = self.status_label.cget("text")
        if widget == self.audio_check:
            self.status_label.config(text="声音文件包括: .mp3, .wav, .flac, .aac")
        elif widget == self.image_check:
            self.status_label.config(text="图片文件包括: .png, .jpg, .jpeg, .tiff, .bmp, .gif")
        elif widget == self.video_check:
            self.status_label.config(text="视频文件包括: .mp4, .avi, .mov, .mkv")

    def hide_tooltip(self, event):
        self.status_label.config(text=self.tmp)

if __name__ == "__main__":
    root = Tk()
    app = MediaOrganizer(root)
    root.mainloop()

本文章最后由 admin2024-11-28 00:16 编辑
评论列表 评论
发布评论

评论: 整理大量照片的小工具



点击进入免费吃瓜群!吃大瓜! 广告位支持代码、文字、图片展示 Image


免责声明
本站资源,均来自网络,版权归原作者,所有资源和文章仅限用于学习和研究目的 。 不得用于商业或非法用途,否则,一切责任由该用户承担 !

请求资源或报告无效资源,请点击[反馈中心]


侵权删除请致信 E-Mail:chengfengad@gmail.com
已有0次打赏
(0) 分享
分享
取消