欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Python編寫微信清理工具的示例代碼

 更新時間:2022年05月19日 11:11:39   作者:somenzz  
這篇文章主要和大家分享一個用Python語言編寫的微信清理小工具的示例代碼,而且該工具不會刪除文字的聊天記錄,感興趣的可以了解一下

前幾天網(wǎng)上找了一款 PC 端微信自動清理工具,用了一下,電腦釋放了 30GB 的存儲空間,而且不會刪除文字的聊天記錄,很好用,感覺很多人都用得到,就在此分享一下,而且是用 Python 寫的,喜歡 Python 的小伙伴可以探究一下。

主要功能

它可以自動刪除 PC 端微信自動下載的大量文件、視頻、圖片等數(shù)據(jù)內(nèi)容,釋放幾十 G 的空間占用,而且不會刪除文字的聊天記錄,可以放心使用。

工作以后,微信的群聊實在太多了,動不動就被拉入一個群中,然后群聊里大部分都是與自己無關的各大群聊中的文件、視頻、圖片等內(nèi)容,會非常占用存儲空間。

  • 自動識別微信賬號,支持用戶選擇自定義路徑;
  • 同時管理多個賬號,保留配置參數(shù),打開即用;
  • 自由設置想要刪除的文件類型,包括圖片類緩存、文件、圖片、視頻;
  • 自由設置需要刪除的文件的距離時間,默認 365 天;
  • 刪除后的文件放置在回收站中,檢查后自行清空,防止刪錯文件;
  • 支持刪除進度的顯示;

工具的主界面如下

運行環(huán)境

Windows,后續(xù)可能會支持 Mac。

核心代碼

import sys

from PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsDropShadowEffect, QListWidgetItem, QListView, QWidget, \
    QLabel, QHBoxLayout, QFileDialog
from PyQt5.QtCore import Qt, QPropertyAnimation, QEasingCurve, QThread, pyqtSignal, QMutex, QSize, QEvent, QPoint
from PyQt5.QtGui import QMouseEvent, QCursor, QColor
from PyQt5.uic import loadUi

from pathlib import Path, PureWindowsPath
from dateutil import relativedelta
import utils.resources
import os, datetime, time, re, math, shutil, json

from utils.deleteThread import *
from utils.multiDeleteThread import multiDeleteThread
from utils.selectVersion import *
from utils.selectVersion import check_dir, existing_user_config

working_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')
        # 持續(xù)時間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, '選擇微信數(shù)據(jù)目錄', '')
        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("已經(jīng)準備好,可以開始了!")
            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("配置文件不存在!請單擊“設置”創(chuàng)建配置文件")
            self.config_exists = False

        self.show()


if __name__ == '__main__':
    app = QApplication([])
    win = MainWindow()
    app.exec_()

完整代碼

源代碼獲取地址 提取碼:vuud

到此這篇關于基于Python編寫微信清理工具的示例代碼的文章就介紹到這了,更多相關Python微信清理工具內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Python命令行參數(shù)解析包argparse的使用詳解

    Python命令行參數(shù)解析包argparse的使用詳解

    argparse?是?python?自帶的命令行參數(shù)解析包,可以用來方便的服務命令行參數(shù)。本文將通過示例和大家詳細講講argparse的使用,需要的可以參考一下
    2022-09-09
  • python中 ? : 三元表達式的使用介紹

    python中 ? : 三元表達式的使用介紹

    剛剛學python的時候,時常糾結于python中沒有C語言中 ? : 的實現(xiàn),今天終于發(fā)現(xiàn)了兩種python的實現(xiàn)方式
    2013-10-10
  • 一文詳解Python中的Map,Filter和Reduce函數(shù)

    一文詳解Python中的Map,Filter和Reduce函數(shù)

    這篇文章主要介紹了一文詳解Python中的Map,Filter和Reduce函數(shù),本文重點介紹Python中的三個特殊函數(shù)Map,Filter和Reduce,以及如何使用它們進行代碼編程
    2022-08-08
  • python爬取鏈家二手房的數(shù)據(jù)

    python爬取鏈家二手房的數(shù)據(jù)

    相信大家買房前都會在網(wǎng)上找找資料,看看行情,問問朋友,今天就用python帶大家扒一扒《鏈家二手房》的數(shù)據(jù)
    2021-05-05
  • python的幾種矩陣相乘的公式詳解

    python的幾種矩陣相乘的公式詳解

    這篇文章主要介紹了python的幾種矩陣相乘的公式詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07
  • python繪制動態(tài)曲線教程

    python繪制動態(tài)曲線教程

    今天小編就為大家分享一篇python繪制動態(tài)曲線教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-02-02
  • scipy稀疏數(shù)組dok_array的具體使用

    scipy稀疏數(shù)組dok_array的具體使用

    本文主要介紹了scipy稀疏數(shù)組dok_array的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-02-02
  • Python實現(xiàn)獲取漢字偏旁部首的方法示例【測試可用】

    Python實現(xiàn)獲取漢字偏旁部首的方法示例【測試可用】

    這篇文章主要介紹了Python實現(xiàn)獲取漢字偏旁部首的方法,涉及Python基于第三方模塊進行漢字處理的相關操作技巧,需要的朋友可以參考下
    2018-12-12
  • Django中redis的使用方法(包括安裝、配置、啟動)

    Django中redis的使用方法(包括安裝、配置、啟動)

    下面小編就為大家分享一篇Django中redis的使用方法(包括安裝、配置、啟動),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • python使用雙豎線分割的實現(xiàn)

    python使用雙豎線分割的實現(xiàn)

    本文主要介紹了python使用雙豎線分割的實現(xiàn),通過接收用戶輸入的字符串,使用split()方法進行分割,并將結果輸出給用戶,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01

最新評論