基于Python怎么编写微信清理工具
发表于:2025-11-06 作者:千家信息网编辑
千家信息网最后更新 2025年11月06日,这篇"基于Python怎么编写微信清理工具"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这
千家信息网最后更新 2025年11月06日基于Python怎么编写微信清理工具
这篇"基于Python怎么编写微信清理工具"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"基于Python怎么编写微信清理工具"文章吧。
主要功能
它可以自动删除 PC 端微信自动下载的大量文件、视频、图片等数据内容,释放几十 G 的空间占用,而且不会删除文字的聊天记录,可以放心使用。
工作以后,微信的群聊实在太多了,动不动就被拉入一个群中,然后群聊里大部分都是与自己无关的各大群聊中的文件、视频、图片等内容,会非常占用存储空间。
自动识别微信账号,支持用户选择自定义路径;
同时管理多个账号,保留配置参数,打开即用;
自由设置想要删除的文件类型,包括图片类缓存、文件、图片、视频;
自由设置需要删除的文件的距离时间,默认 365 天;
删除后的文件放置在回收站中,检查后自行清空,防止删错文件;
支持删除进度的显示;
工具的主界面如下
运行环境
Windows,后续可能会支持 Mac。
核心代码
import sysfrom PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsDropShadowEffect, QListWidgetItem, QListView, QWidget, \ QLabel, QHBoxLayout, QFileDialogfrom PyQt5.QtCore import Qt, QPropertyAnimation, QEasingCurve, QThread, pyqtSignal, QMutex, QSize, QEvent, QPointfrom PyQt5.QtGui import QMouseEvent, QCursor, QColorfrom PyQt5.uic import loadUifrom pathlib import Path, PureWindowsPathfrom dateutil import relativedeltaimport utils.resourcesimport os, datetime, time, re, math, shutil, jsonfrom utils.deleteThread import *from utils.multiDeleteThread import multiDeleteThreadfrom utils.selectVersion import *from utils.selectVersion import check_dir, existing_user_configworking_dir = os.path.split(os.path.realpath(__file__))[0]# 主窗口class Window(QMainWindow): def mousePressEvent(self, event): # 重写一堆方法使其支持拖动 if event.button() == Qt.LeftButton: self.m_drag = True self.m_DragPosition = event.globalPos() - self.pos() event.accept() # self.setCursor(QCursor(Qt.OpenHandCursor)) def mouseMoveEvent(self, QMouseEvent): try: if Qt.LeftButton and self.m_drag: self.move(QMouseEvent.globalPos() - self.m_DragPosition) QMouseEvent.accept() except: pass def mouseReleaseEvent(self, QMouseEvent): self.m_drag = False # self.setCursor(QCursor(Qt.ArrowCursor)) def _frame(self): # 边框 self.setWindowFlags(Qt.FramelessWindowHint) self.setAttribute(Qt.WA_TranslucentBackground, True) # 阴影 effect = QGraphicsDropShadowEffect(blurRadius=12, xOffset=0, yOffset=0) effect.setColor(QColor(25, 25, 25, 170)) self.mainFrame.setGraphicsEffect(effect) def doFadeIn(self): # 动画 self.animation = QPropertyAnimation(self, b'windowOpacity') # 持续时间250ms self.animation.setDuration(250) try: # 尝试先取消动画完成后关闭窗口的信号 self.animation.finished.disconnect(self.close) except: pass self.animation.stop() # 透明度范围从0逐渐增加到1 self.animation.setEasingCurve(QEasingCurve.InOutCubic) self.animation.setStartValue(0) self.animation.setEndValue(1) self.animation.start() def doFadeOut(self): self.animation.stop() # 动画完成则关闭窗口 self.animation.finished.connect(self.close) # 透明度范围从1逐渐减少到0s self.animation.setEasingCurve(QEasingCurve.InOutCubic) self.animation.setStartValue(1) self.animation.setEndValue(0) self.animation.start() def setWarninginfo(self, text): self.lab_info.setStyleSheet(""" .QLabel { border:1px solid #ffccc7; border-radius:3px; line-height: 140px; padding: 5px; color: #434343; background: #fff2f0; } """) self.lab_info.setText(text) def setSuccessinfo(self, text): self.lab_info.setStyleSheet(""" .QLabel { border:1px solid #b7eb8f; border-radius:3px; line-height: 140px; padding: 5px; color: #434343; background: #f6ffed; } """) self.lab_info.setText(text)class ConfigWindow(Window): Signal_OneParameter = pyqtSignal(int) config = {} def _connect(self): self.combo_user.currentIndexChanged.connect(self.refresh_ui) self.btn_close.clicked.connect(self.save_config) self.btn_file.clicked.connect(self.open_file) def open_file(self): openfile_path = QFileDialog.getExistingDirectory(self, '选择微信数据目录', '') if not openfile_path or openfile_path == '': return False if check_dir(openfile_path) == 0: self.setSuccessinfo('读取路径成功!') list_ = os.listdir(openfile_path) user_list = [ elem for elem in list_ if elem != 'All Users' and elem != 'Applet' ] # 如果已有用户配置,那么写入新的用户配置,否则默认写入新配置 dir_list = [] user_config = [] existing_user_config_dic = existing_user_config() for user_wx_id in user_list: dir_list.append(os.path.join(openfile_path, user_wx_id)) if user_wx_id in existing_user_config_dic: user_config.append(existing_user_config_dic[user_wx_id]) else: user_config.append({ "wechat_id": user_wx_id, "clean_days": "365", "is_clean": False, "clean_pic_cache": True, "clean_file": False, "clean_pic": True, "clean_video": True, "is_timer": True, "timer": "0h" }) config = {"data_dir": dir_list, "users": user_config} with open( working_dir + "/config.json", "w", encoding="utf-8") as f: json.dump(config, f) self.load_config() else: self.setWarninginfo('请选择正确的文件夹!一般是WeChat Files文件夹。') def save_config(self): self.update_config() self.doFadeOut() def check_wechat_exists(self): self.selectVersion = selectVersion() self.version_scan = self.selectVersion.getAllPath()[0] self.users_scan = self.selectVersion.getAllPath()[1] if len(self.version_scan) == 0: return False else: return True def load_config(self): fd = open(working_dir + "/config.json", encoding="utf-8") self.config = json.load(fd) self.combo_user.clear() for value in self.config["users"]: self.combo_user.addItem(value["wechat_id"]) self.line_gobackdays.setText( str(self.config["users"][0]["clean_days"])) self.check_is_clean.setChecked(self.config["users"][0]["is_clean"]) self.check_picdown.setChecked(self.config["users"][0]["clean_pic"]) self.check_files.setChecked(self.config["users"][0]["clean_file"]) self.check_video.setChecked(self.config["users"][0]["clean_video"]) self.check_picscache.setChecked( self.config["users"][0]["clean_pic_cache"]) self.setSuccessinfo("加载配置文件成功") def refresh_ui(self): self.config = open(working_dir + "/config.json", encoding="utf-8") self.config = json.load(self.config) for value in self.config["users"]: if value["wechat_id"] == self.combo_user.currentText(): self.line_gobackdays.setText(str(value["clean_days"])) self.check_is_clean.setChecked(value["is_clean"]) self.check_picdown.setChecked(value["clean_pic"]) self.check_files.setChecked(value["clean_file"]) self.check_video.setChecked(value["clean_video"]) self.check_picscache.setChecked(value["clean_pic_cache"]) def create_config(self): true = True if not os.path.exists(working_dir + "/config.json"): if not self.check_wechat_exists(): self.setWarninginfo("默认位置没有微信,请自定义位置") return self.config = {"data_dir": self.version_scan, "users": []} for value in self.users_scan: self.config["users"].append({ "wechat_id": value, "clean_days": 365, "is_clean": False, "clean_pic_cache": true, "clean_file": False, "clean_pic": true, "clean_video": true, "is_timer": true, "timer": "0h" }) with open( working_dir + "/config.json", "w", encoding="utf-8") as f: json.dump(self.config, f) self.load_config() self.setSuccessinfo("加载配置文件成功") else: self.setSuccessinfo("加载配置文件成功") self.load_config() def update_config(self): if not len(self.config): return else: for value in self.config["users"]: if value["wechat_id"] == self.combo_user.currentText(): try: days = int(self.line_gobackdays.text()) if days < 0: value["clean_days"] = "0" else: value["clean_days"] = self.line_gobackdays.text() except ValueError: value["clean_days"] = "0" value["is_clean"] = self.check_is_clean.isChecked() value["clean_pic"] = self.check_picdown.isChecked() value["clean_file"] = self.check_files.isChecked() value["clean_video"] = self.check_video.isChecked() value["clean_pic_cache"] = self.check_picscache.isChecked() with open(working_dir + "/config.json", "w", encoding="utf-8") as f: json.dump(self.config, f) self.setSuccessinfo("更新配置文件成功") self.Signal_OneParameter.emit(1) def __init__(self): super().__init__() loadUi(working_dir + "/images/config.ui", self) self._frame() self._connect() self.doFadeIn() self.create_config() self.show()class MainWindow(Window): def deal_emit_slot(self, set_status): if set_status and not self.config_exists: self.setSuccessinfo("已经准备好,可以开始了!") self.config_exists = True def closeEvent(self, event): sys.exit(0) def eventFilter(self, object, event): if event.type() == QEvent.MouseButtonPress: if object == self.lab_close: self.doFadeOut() return True elif object == self.lab_clean: try: self.setSuccessinfo("正在清理中...") self.justdoit() except: self.setWarninginfo("清理失败,请检查配置文件后重试") return True elif object == self.lab_config: cw = ConfigWindow() cw.Signal_OneParameter.connect(self.deal_emit_slot) return True return False def _eventfilter(self): # 事件过滤 self.lab_close.installEventFilter(self) self.lab_clean.installEventFilter(self) self.lab_config.installEventFilter(self) def get_fileNum(self, path, day, picCacheCheck, fileCheck, picCheck, videoCheck, file_list, dir_list): dir_name = PureWindowsPath(path) # Convert path to the right format for the current operating system correct_path = Path(dir_name) now = datetime.datetime.now() if picCacheCheck: path_one = correct_path / 'Attachment' path_two = correct_path / 'FileStorage/Cache' self.getPathFileNum(now, day, path_one, path_two, file_list, dir_list) if fileCheck: path_one = correct_path / 'Files' path_two = correct_path / 'FileStorage/File' self.getPathFileNum(now, day, path_one, path_two, file_list, dir_list) if picCheck: path_one = correct_path / 'Image/Image' path_two = correct_path / 'FileStorage/Image' self.getPathFileNum(now, day, path_one, path_two, file_list, dir_list) if videoCheck: path_one = correct_path / 'Video' path_two = correct_path / 'FileStorage/Video' self.getPathFileNum(now, day, path_one, path_two, file_list, dir_list) def pathFileDeal(self, now, day, path, file_list, dir_list): if os.path.exists(path): filelist = [ f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f)) ] for i in range(0, len(filelist)): file_path = os.path.join(path, filelist[i]) if os.path.isdir(file_path): continue timestamp = datetime.datetime.fromtimestamp( os.path.getmtime(file_path)) diff = (now - timestamp).days if diff >= day: file_list.append(file_path) def getPathFileNum(self, now, day, path_one, path_two, file_list, dir_list): # caculate path_one self.pathFileDeal(now, day, path_one, file_list, dir_list) td = datetime.datetime.now() - datetime.timedelta(days=day) td_year = td.year td_month = td.month # caculate path_two if os.path.exists(path_two): osdir = os.listdir(path_two) dirlist = [] for i in range(0, len(osdir)): file_path = os.path.join(path_two, osdir[i]) if os.path.isdir(file_path): dirlist.append(osdir[i]) for i in range(0, len(dirlist)): file_path = os.path.join(path_two, dirlist[i]) if os.path.isfile(file_path): continue if re.match('\d{4}(\-)\d{2}', dirlist[i]) != None: cyear = int(dirlist[i].split('-', 1)[0]) cmonth = int(dirlist[i].split('-', 1)[1]) if self.__before_deadline(cyear, cmonth, td_year, td_month): dir_list.append(file_path) else: if cmonth == td_month: self.pathFileDeal(now, day, file_path, file_list, dir_list) def __before_deadline(self, cyear, cmonth, td_year, td_month): if cyear < td_year: return True elif cyear > td_year: return False elif cyear == td_year: return cmonth < td_month def callback(self, v): value = v / int((self.total_file + self.total_dir)) * 100 self.bar_progress.setValue(value) if value == 100: out = "本次共清理文件" + str(self.total_file) + "个,文件夹" + str( self.total_dir) + "个。请前往回收站检查并清空。" self.setSuccessinfo(out) return def justdoit(self): # 这个Api设计的太脑残了,其实dir可以直接放在user里的... 有时间改吧 fd = open(working_dir + "/config.json", encoding="utf-8") self.config = json.load(fd) i = 0 need_clean = False thread_list = [] total_file = 0 total_dir = 0 share_thread_arr = [0] for value in self.config["users"]: file_list = [] dir_list = [] if value["is_clean"]: self.get_fileNum(self.config["data_dir"][i], int(value["clean_days"]), value["clean_pic_cache"], value["clean_file"], value["clean_pic"], value["clean_video"], file_list, dir_list) if len(file_list) + len(dir_list) != 0: need_clean = True total_file += len(file_list) total_dir += len(dir_list) thread_list.append( multiDeleteThread(file_list, dir_list, share_thread_arr)) thread_list[-1].delete_process_signal.connect(self.callback) i = i + 1 if not need_clean: self.setWarninginfo("没有需要清理的文件") else: self.total_file = total_file self.total_dir = total_dir for thread in thread_list: thread.run() def __init__(self): super().__init__() loadUi(working_dir + "/images/main.ui", self) self._frame() self._eventfilter() self.doFadeIn() self.config_exists = True # 判断配置文件是否存在 if not os.path.exists(working_dir + "/config.json"): self.setWarninginfo("配置文件不存在!请单击"设置"创建配置文件") self.config_exists = False self.show()if __name__ == '__main__': app = QApplication([]) win = MainWindow() app.exec_()以上就是关于"基于Python怎么编写微信清理工具"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。
文件
配置
内容
utf-8
工具
成功
图片
支持
动画
文件夹
时间
用户
视频
选择
自由
位置
回收站
大部分
数据
文章
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
杭州众栋网络技术有限公司
怎么建立网页数据库
软件开发 实战视频
在公司怎么从数据库中提取数据
vb查询数据库代码
陕西服务器机箱哪里有云空间
思科网络安全大会
西门子m55数据库
软件开发网络工程哪个比较好
战地五服务器名称保存不了
数据库完全恢复的步骤
mysql数据库 1068
网络安全保障是
多网站数据库如何全部备份
墨迹天气每天早上显示服务器异常
高校网络安全意识形态制度
服务器网络延迟波动大
软件开发的原理
软件开发净利润
文本文字在数据库当中用什么类型
失落的方舟捏脸数据库
网络安全大赛专业术语
摆渡人小说软件开发
库存软件开发代码
旅游服务管理软件开发
济南中中网络技术有限公司介绍
raid卡的服务器如何安装系统
数据库id自增好还是随机数好
山东省浪潮存储服务器哪家好
对日软件开发没落2018