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

基于Python制作一個(gè)全自動(dòng)微信清粉小工具

 更新時(shí)間:2024年12月02日 08:41:29   作者:左詩(shī)右碼  
在當(dāng)今社交軟件中,微信是最常用的通訊工具之一,這篇文章主要為大家介紹了一個(gè)使用?Python?和?uiautomator2?庫(kù)編寫(xiě)的微信清粉工具,希望對(duì)大家有所幫助

在當(dāng)今社交軟件中,微信是最常用的通訊工具之一。然而,隨著時(shí)間的推移,我們的好友列表中可能會(huì)出現(xiàn)一些不再活躍的賬號(hào),也就是我們俗稱的“僵尸粉”。

這些賬號(hào)可能是由于長(zhǎng)時(shí)間不使用、賬號(hào)被封禁或者故意將我們刪除或拉黑。為了保持好友列表的清潔和有效溝通,同時(shí)也為了幫助我們更好地管理微信好友,最近我使用 Python 和 uiautomator2 庫(kù)編寫(xiě)了一個(gè)自動(dòng)化工具來(lái)清理這些僵尸粉。

這個(gè)工具會(huì)通過(guò)檢測(cè)好友的狀態(tài)(如是否被刪除、是否被拉黑或是否賬號(hào)出現(xiàn)問(wèn)題)來(lái)批量標(biāo)記并處理這些好友。

這個(gè)工具的主要功能包括:

  • 識(shí)別被刪除或拉黑的好友:通過(guò)模擬轉(zhuǎn)賬操作,檢查與好友的交易是否正常。
  • 標(biāo)記問(wèn)題賬號(hào):對(duì)于賬號(hào)存在問(wèn)題(如被封禁、拉黑、刪除)的好友進(jìn)行標(biāo)記。
  • 記錄和輸出結(jié)果:將檢查結(jié)果記錄到文件中,方便后續(xù)查看和管理。

接下來(lái),我將從代碼的整體結(jié)構(gòu)開(kāi)始分析,介紹如何使用 uiautomator2 來(lái)控制 Android 設(shè)備,并通過(guò)自動(dòng)化方式清理微信中的僵尸粉。

需要注意的是:因?yàn)槲沂诸^上只有一部 OPPO Reno4 Pro 安卓手機(jī),因此只能在這部手機(jī)上做了實(shí)驗(yàn)。不太確定是否在其他機(jī)型上有無(wú)問(wèn)題。

核心類和初始化

這段代碼定義了一個(gè)名為 WXCleanFriends 的類,該類包含了所有執(zhí)行清理操作的核心方法。類內(nèi)部包含多個(gè)常量和狀態(tài)標(biāo)記,用于表示不同的好友狀態(tài),如正常、被刪除、被拉黑等。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
微信清理僵尸粉工具
通過(guò)遍歷微信好友列表,將僵尸粉(被刪除、被拉黑、賬號(hào)問(wèn)題)進(jìn)行標(biāo)記
"""
import json
import time

import uiautomator2 as u2
from uiautomator2 import Direction


class WXCleanFriends:
    """
    微信清理僵尸粉
    運(yùn)行設(shè)備為:OPPO Reno4 pro
    """

    # 檢查好友狀態(tài)時(shí),如果是被對(duì)方刪除的話,需要打上的標(biāo)簽
    TAG_HAS_DELETED = '清粉-被刪除'
    # 檢查好友狀態(tài)時(shí),如果是被對(duì)方拉黑的話,需要打上的標(biāo)簽
    TAG_HAS_BLACK = '清粉-被拉黑'
    # 檢查好友狀態(tài)時(shí),如果是對(duì)方賬號(hào)出現(xiàn)問(wèn)題的話,需要打上的標(biāo)簽
    TAG_ACCOUNT_PROBLEM = '清粉-賬號(hào)問(wèn)題'

    # 好友狀態(tài)
    FRIEND_STATUS_NORMAL = 'normal'  # 正常
    FRIEND_STATUS_HAS_DELETED = 'has_deleted'  # 被刪除
    FRIEND_STATUS_HAS_BLACK = 'has_black'  # 被拉黑
    FRIEND_STATUS_ACCOUNT_PROBLEM = 'account_problem'  # 賬號(hào)問(wèn)題
    FRIEND_STATUS_UNKNOWN = 'unknown'  # 未知

    # 給好友打標(biāo)簽情況
    TAG_NEVER_REMARK = 'never_remark'  # 從來(lái)沒(méi)有打過(guò)標(biāo)簽
    TAG_HAS_JOIN = 'has_join'  # 已經(jīng)加入過(guò)該標(biāo)簽群組
    TAG_HAS_REMARK_OTHER = 'has_remark_other'  # 已經(jīng)打過(guò)標(biāo)簽,但不是【{tag_name}】標(biāo)簽

    def __init__(self,
                 last_friend_wx_code: str,
                 ignore_wx_code: list,
                 max_page_get_friend_list: int = 8
                 ):
        """
        :param last_friend_wx_code: 通訊錄中最后一個(gè)好友的微信號(hào)
        :param ignore_wx_code: 需要被忽略檢測(cè)的微信號(hào)或者微信昵稱
        :param max_page_get_friend_list: 檢查通訊錄中的好友列表最大頁(yè)數(shù)
        """

        # 連接設(shè)備
        self.d = u2.connect()
        # 被檢查的好友列表(可以理解成所有的好友)
        self.friends_list = []
        # 記錄當(dāng)前已經(jīng)被檢測(cè)過(guò)的好友,避免重復(fù)檢測(cè)
        self.friends_has_checked = {}

        # 通訊錄中最后一個(gè)好友的微信號(hào)
        self.last_friend_wx_code = last_friend_wx_code
        # 需要被忽略檢測(cè)的微信號(hào)或者微信昵稱
        self.ignore_wx_code = ignore_wx_code
        self.max_page_get_friend_list = max_page_get_friend_list

    def enable_debug(self):
        """
        開(kāi)啟調(diào)試模式
        :return:
        """

        # 開(kāi)啟日志
        # u2.enable_pretty_logging()
        # 設(shè)置 http 請(qǐng)求超時(shí)時(shí)間
        u2.HTTP_TIMEOUT = 60
        # 開(kāi)啟調(diào)試模式
        # self.d.debug = True

        print(f"設(shè)備信息 ==> {self.d.info}")
        print(f"設(shè)備IP ==> {self.d.wlan_ip} 設(shè)備號(hào) ==> {self.d.serial}")

        # 設(shè)置查找元素等待時(shí)間,單位秒
        self.d.implicitly_wait(30)

        # UI 層次結(jié)構(gòu)
        # xml = d.dump_hierarchy(compressed=False, pretty=True, max_depth=50)
        # print(xml)

初始化方法接受三個(gè)參數(shù):

  • last_friend_wx_code:通訊錄中最后一個(gè)好友的微信號(hào),用于確定清理到哪個(gè)位置停止。
  • ignore_wx_code:一個(gè)列表,包含了需要跳過(guò)檢查的微信號(hào)或昵稱。
  • max_page_get_friend_list:最多獲取多少頁(yè)的好友列表,避免檢測(cè)過(guò)多的好友。

自動(dòng)化打開(kāi)微信

    def weixin_start(self):
        """
        打開(kāi)微信
        :return:
        """
        # self.d.xpath('//android.widget.TextView[@text="微信"]').click(5)

        wx_app = self.d(text='微信', className='android.widget.TextView')
        if wx_app.exists() is False:
            print('當(dāng)前頁(yè)面沒(méi)有微信 APP,請(qǐng)切換到有微信 APP 的頁(yè)面')
            exit(1)

        print("打開(kāi)微信")
        wx_app.click(timeout=5)

weixin_start 方法用于啟動(dòng)微信應(yīng)用。它通過(guò) uiautomator2 來(lái)模擬點(diǎn)擊操作。如果當(dāng)前頁(yè)面沒(méi)有找到微信應(yīng)用,程序?qū)⑼顺觥?/p>

獲取好友信息和狀態(tài)判斷

    def get_personal_info(self):
        """
        獲取好友個(gè)人信息
        :return:
        """
        remark = nickname = wx_code = zone = tag = ''

        remark_elem = self.d(className='android.widget.TextView', resourceId='com.tencent.mm:id/cf8')
        if remark_elem.exists(timeout=3):
            remark = remark_elem.get_text()

        nickname_elem = self.d(className='android.widget.TextView', resourceId='com.tencent.mm:id/cf7')
        if nickname_elem.exists(timeout=3):
            nickname = nickname_elem.get_text().lstrip('昵稱:  ')

        wx_code_elem = self.d(className='android.widget.TextView', resourceId='com.tencent.mm:id/cff')
        if wx_code_elem.exists(timeout=3):
            wx_code = wx_code_elem.get_text().lstrip('微信號(hào):  ')

        zone_elem = self.d(className='android.widget.TextView', resourceId='com.tencent.mm:id/cf6')
        if zone_elem.exists(timeout=3):
            zone = zone_elem.get_text().lstrip('地區(qū):  ')

        tag_elem = self.d(className='android.widget.TextView', resourceId='com.tencent.mm:id/cd4')
        if tag_elem.exists(timeout=3):
            tag = tag_elem.get_text()

        print(
            f"備注名是[{remark}] 昵稱是[{nickname}] 微信號(hào)是[{wx_code}] 地區(qū)是[{zone}] 標(biāo)簽是[{tag}]")

        return {'remark': remark, 'nickname': nickname, 'wx_code': wx_code, 'zone': zone, 'tag': tag}

get_personal_info 方法通過(guò)定位 UI 元素來(lái)提取好友的個(gè)人信息,包括備注名、昵稱、微信號(hào)、地區(qū)和標(biāo)簽等。

    def judge_friend_status(self) -> str:
        """
        判斷當(dāng)前好友的狀態(tài)
        :return:
        """
        # 點(diǎn)擊【發(fā)消息】按鈕
        if self.d(text='發(fā)消息').click_exists(10) == False:
            # if self.d(resourceId='com.tencent.mm:id/cfb').click_exists(timeout=10) == False:
            print('沒(méi)有點(diǎn)擊【發(fā)消息】按鈕')
            exit()
        # 點(diǎn)擊【?】
        if self.d(resourceId='com.tencent.mm:id/bjz').click_exists(timeout=10) == False:
            print('沒(méi)有點(diǎn)擊【?】按鈕')
            exit()
        # 點(diǎn)擊【轉(zhuǎn)賬】按鈕
        if self.d(resourceId='com.tencent.mm:id/a12', text='轉(zhuǎn)賬').click_exists(timeout=10) == False:
            print('沒(méi)有點(diǎn)擊【轉(zhuǎn)賬】按鈕')
            exit()

        time.sleep(1)

        # 先清空轉(zhuǎn)賬金額,以免導(dǎo)致金額輸入錯(cuò)誤或者輸入大額金額
        self.d(resourceId='com.tencent.mm:id/pbn').clear_text(3)
        # 輸入 0.01 元 ---> start
        self.d(resourceId='com.tencent.mm:id/keyboard_0').click_exists(3)
        self.d(resourceId='com.tencent.mm:id/keyboard_dot').click_exists(3)
        self.d(resourceId='com.tencent.mm:id/keyboard_0').click_exists(3)
        self.d(resourceId='com.tencent.mm:id/keyboard_1').click_exists(3)
        # 輸入 0.01 元 ---> end
        time.sleep(1)
        # # 點(diǎn)擊【轉(zhuǎn)賬】按鈕
        self.d(resourceId='com.tencent.mm:id/keyboard_action', text='轉(zhuǎn)賬').click_exists(3)

        # 點(diǎn)擊轉(zhuǎn)賬之后,就可以根據(jù)頁(yè)面元素來(lái)判斷當(dāng)前好友的狀態(tài)

        # 1、如果頁(yè)面中存在【¥0.01】元素,證明當(dāng)前好友沒(méi)有將自己刪除
        is_normal = self.d(text='¥0.01', className='android.widget.TextView').exists(timeout=3)
        if is_normal is True:
            return self.FRIEND_STATUS_NORMAL

        # 判斷是否有彈窗
        alert_elem = self.d(resourceId='com.tencent.mm:id/jlg')
        if alert_elem.exists(timeout=5):
            time.sleep(2)
            # 有彈窗的情況下,通過(guò)彈窗中的文本內(nèi)容來(lái)判斷當(dāng)前好友的狀態(tài)
            alert_text = alert_elem.get_text()
            # 2、判斷是否被拉黑
            if '請(qǐng)確認(rèn)你和他(她)的好友關(guān)系是否正常' in alert_text:
                return self.FRIEND_STATUS_HAS_BLACK
            # 3、判斷是否被刪除
            if '你不是收款方好友,對(duì)方添加你為好友后才能發(fā)起轉(zhuǎn)賬' in alert_text:
                return self.FRIEND_STATUS_HAS_DELETED
            # 4、判斷是否被限制登錄(對(duì)方的賬號(hào)可能出現(xiàn)了問(wèn)題、該賬號(hào)已無(wú)法使用)
            if ('對(duì)方微信號(hào)已被限制登錄,為保障你的資金安全,暫時(shí)無(wú)法完成交易。' in alert_text
                    or '當(dāng)前使用人數(shù)過(guò)多,請(qǐng)稍后再試。' in alert_text
                    or '對(duì)方賬戶有異常行為,已被限制收款,本次交易無(wú)法完成。對(duì)方可通過(guò)微信支付公眾號(hào)上收到的消息查看詳情。' in alert_text
            ):
                return self.FRIEND_STATUS_ACCOUNT_PROBLEM

        # 5、其他情況(未知)
        return self.FRIEND_STATUS_UNKNOWN

judge_friend_status 方法通過(guò)一系列點(diǎn)擊操作模擬轉(zhuǎn)賬行為,根據(jù)頁(yè)面彈窗判斷好友的狀態(tài)。主要判斷的狀態(tài)包括:

  • 正常狀態(tài):好友未刪除,未拉黑,賬號(hào)正常。
  • 被刪除:如果彈出提示“你不是收款方好友”,則說(shuō)明好友已刪除。
  • 被拉黑:如果出現(xiàn)“請(qǐng)確認(rèn)你和他(她)的好友關(guān)系是否正常”,則說(shuō)明好友將你拉黑。
  • 賬號(hào)問(wèn)題:如果彈窗提示賬戶已被限制登錄,則說(shuō)明對(duì)方賬號(hào)存在問(wèn)題。

標(biāo)簽管理

    def has_join_tag_group(self, tag_name: str) -> str:
        """
        判斷當(dāng)前用戶是否已經(jīng)被打了某個(gè)標(biāo)簽
        :param tag_name: 標(biāo)簽名稱 eg: 清粉-被刪除
        :return: never_remark: 從來(lái)沒(méi)有打過(guò)標(biāo)簽
                    has_join: 已經(jīng)加入過(guò)該標(biāo)簽群組
                    has_remark_other: 已經(jīng)打過(guò)標(biāo)簽,但不是【{tag_name}】標(biāo)簽
        """
        # 好友資料頁(yè)面中的【標(biāo)簽】屬性
        tag_elem = self.d(className='android.widget.TextView', resourceId='com.tencent.mm:id/cd4')

        if tag_elem.exists(timeout=5) is False:
            print(f'沒(méi)有找到標(biāo)簽元素,證明沒(méi)有對(duì)該好友打過(guò)任何標(biāo)簽,現(xiàn)在需要對(duì)該好友打上【{tag_name}】標(biāo)簽')
            # 證明沒(méi)有給該好友打過(guò)任何標(biāo)簽
            return self.TAG_NEVER_REMARK

        # 獲取標(biāo)簽元素的文本
        tags = tag_elem.get_text()
        if tag_name in tags:
            print(f'已經(jīng)加入過(guò)【{tag_name}】群組')
            # 證明已經(jīng)加入過(guò)該標(biāo)簽群組
            return self.TAG_HAS_JOIN
        else:
            # 證明已經(jīng)打過(guò)標(biāo)簽,但不是【{tag_name}】標(biāo)簽
            print(f'已經(jīng)打過(guò)標(biāo)簽,但不是【{tag_name}】標(biāo)簽,現(xiàn)在需要對(duì)該好友打上【{tag_name}】標(biāo)簽')
            return self.TAG_HAS_REMARK_OTHER

    def join_tag_group(self, tag_name: str):
        """
        加入標(biāo)簽群組
        :param tag_name: 標(biāo)簽名稱 eg: 清粉-被刪除
        :return:
        """
        print(f'開(kāi)始加入【{tag_name}】標(biāo)簽群組')

        # 這里有 2 種情況:
        # 一種是之前加過(guò)標(biāo)簽的,那么則有“標(biāo)簽”;
        # 一種是沒(méi)有加過(guò)標(biāo)簽的,那么則有“設(shè)置備注和標(biāo)簽”
        # 好友資料頁(yè)面中的【標(biāo)簽】
        tag_zone = self.d(resourceId='com.tencent.mm:id/cd5', text='標(biāo)簽')
        if tag_zone.exists(timeout=5) is False:
            print('之前沒(méi)有給該好友打過(guò)任何標(biāo)簽')
            tag_zone = self.d(className='android.widget.TextView', resourceId='android:id/title', text='設(shè)置備注和標(biāo)簽')
            if tag_zone.exists(timeout=5) is False:
                print('沒(méi)有找到【設(shè)置備注和標(biāo)簽】按鈕')
                exit()

        tag_zone.click(timeout=1)
        # 【設(shè)置備注和標(biāo)簽】頁(yè)面中的【標(biāo)簽】去添加標(biāo)簽
        self.d(resourceId='com.tencent.mm:id/cd8').click(timeout=1)

        # 在標(biāo)簽列表中查找是否有【{tag_name}】標(biāo)簽
        target_tag_elem = self.d(text=tag_name, className='android.widget.TextView')

        if target_tag_elem.exists(timeout=1) is False:
            print(f"沒(méi)有找到【{tag_name}】標(biāo)簽,現(xiàn)在需要?jiǎng)?chuàng)建【{tag_name}】標(biāo)簽")
            # 點(diǎn)擊【新建標(biāo)簽】按鈕
            self.d(resourceId='com.tencent.mm:id/k70', text='新建標(biāo)簽').click(timeout=1)
            create_tag = self.d(resourceId='com.tencent.mm:id/d98', text='標(biāo)簽名稱')
            create_tag.clear_text(timeout=1)
            create_tag.set_text(tag_name, 1)
            time.sleep(1)
            self.d(resourceId='com.tencent.mm:id/kao', text='確定').click(timeout=1)
            time.sleep(1)
            self.d(resourceId='com.tencent.mm:id/fp', text='保存').click(timeout=1)
            time.sleep(1)
            self.d(resourceId='com.tencent.mm:id/fp', text='完成').click(timeout=1)
        else:
            print(f"已經(jīng)存在【{tag_name}】標(biāo)簽,現(xiàn)在只需要添加")
            target_tag_elem.click(timeout=1)
            time.sleep(1)
            self.d(resourceId='com.tencent.mm:id/fp', text='保存').click(timeout=1)
            time.sleep(1)
            self.d(resourceId='com.tencent.mm:id/fp', text='完成').click(timeout=1)

has_join_tag_group 方法用于判斷好友是否已經(jīng)被打上某個(gè)標(biāo)簽,比如“清粉-被刪除”。根據(jù)返回值,程序決定是否為好友添加新標(biāo)簽。

針對(duì)不同的好友狀態(tài)進(jìn)行后續(xù)的操作

    def when_has_deleted(self):
        """
        如果當(dāng)前好友已經(jīng)將自己刪除時(shí)
        :return:
        """
        self.d(resourceId='com.tencent.mm:id/mm_alert_ok_btn', text='我知道了').click_exists(timeout=3)

        # 1、退出【輸入法】頁(yè)面
        # self.d.press("back")
        # time.sleep(1)

        # 1、退出轉(zhuǎn)賬頁(yè)面
        self.d.press("back")
        time.sleep(1)

        # 2、退出【紅包、轉(zhuǎn)賬、語(yǔ)音輸入、我的收藏……】頁(yè)面
        self.d.press("back")
        time.sleep(1)

        # 3、退出聊天頁(yè)面
        self.d.press("back")
        time.sleep(1)

        tag_status = self.has_join_tag_group(self.TAG_HAS_DELETED)
        if tag_status != self.TAG_HAS_JOIN:
            self.join_tag_group(self.TAG_HAS_DELETED)

    def when_has_black(self):
        """
        如果當(dāng)前好友已經(jīng)將自己拉黑時(shí)
        :return:
        """
        self.d(resourceId='com.tencent.mm:id/mm_alert_ok_btn', text='我知道了').click_exists(timeout=3)

        # # 1、退出【輸入法】頁(yè)面
        # self.d.press("back")
        # time.sleep(1)

        # 2、退出轉(zhuǎn)賬頁(yè)面
        self.d.press("back")
        time.sleep(1)

        # 3、退出【紅包、轉(zhuǎn)賬、語(yǔ)音輸入、我的收藏……】頁(yè)面
        self.d.press("back")
        time.sleep(1)

        # 4、退出聊天頁(yè)面
        self.d.press("back")
        time.sleep(1)

        tag_status = self.has_join_tag_group(self.TAG_HAS_BLACK)
        if tag_status != self.TAG_HAS_JOIN:
            self.join_tag_group(self.TAG_HAS_BLACK)

    def when_account_problem(self):
        """
        如果當(dāng)前好友的賬號(hào)出現(xiàn)問(wèn)題時(shí)
        :return:
        """
        self.d(resourceId='com.tencent.mm:id/mm_alert_ok_btn', text='我知道了').click_exists(timeout=3)

        # # 1、退出【輸入法】頁(yè)面
        # self.d.press("back")
        # time.sleep(1)

        # 2、退出轉(zhuǎn)賬頁(yè)面
        self.d.press("back")
        time.sleep(1)

        # 3、退出【紅包、轉(zhuǎn)賬、語(yǔ)音輸入、我的收藏……】頁(yè)面
        self.d.press("back")
        time.sleep(1)

        # 4、退出聊天頁(yè)面
        self.d.press("back")
        time.sleep(1)

        tag_status = self.has_join_tag_group(self.TAG_ACCOUNT_PROBLEM)
        if tag_status != self.TAG_HAS_JOIN:
            self.join_tag_group(self.TAG_ACCOUNT_PROBLEM)

    def when_normal(self):
        """
        如果當(dāng)前好友是正常狀態(tài)時(shí)
        :return:
        """
        # 1、退出【輸入支付密碼】頁(yè)面
        self.d.press("back")
        time.sleep(1)

        # 2、退出【輸入法】頁(yè)面
        self.d.press("back")
        time.sleep(1)

        # 3、退出轉(zhuǎn)賬頁(yè)面
        self.d.press("back")
        time.sleep(1)

        # 4、退出【紅包、轉(zhuǎn)賬、語(yǔ)音輸入、我的收藏……】頁(yè)面
        self.d.press("back")
        time.sleep(1)

        # 5、退出聊天頁(yè)面
        self.d.press("back")
        time.sleep(1)

當(dāng)我們判斷清楚了每一位好友的狀態(tài)之后,我們還需要退回到通訊錄頁(yè)面,方便繼續(xù)檢測(cè)下一位好友。但是極有可能每一個(gè)狀態(tài)返回到通訊錄中的步驟可能不一樣,因此,我們就最好是根據(jù)不同的狀態(tài)來(lái)分別處理。

接下來(lái)就是最重要的步驟了,通過(guò)遍歷通訊錄中的每一個(gè)好友,來(lái)檢測(cè)每一位好友的狀態(tài)如何。

循環(huán)檢查每個(gè)好友

    def check_every_friend(self):
        run_status = 'doing'
        time.sleep(3)
        elems = self.d(resourceId='com.tencent.mm:id/kbq')

        for elem in elems:
            print()

            time.sleep(1)
            friend_nickname = elem.get_text(timeout=10)
            # 點(diǎn)擊進(jìn)入好友詳情頁(yè)面
            print(f'進(jìn)入好友詳情頁(yè)面 --> {friend_nickname}')
            # 判斷是否需要忽略檢測(cè)
            if friend_nickname in self.ignore_wx_code:
                print(f"可以直接忽略檢測(cè)【{friend_nickname}】")
                continue

            elem.click(timeout=5)

            # 獲取好友個(gè)人信息
            personal_info = self.get_personal_info()

            # 判斷是否需要忽略檢測(cè)
            if personal_info['wx_code'] in self.ignore_wx_code or personal_info['nickname'] in self.ignore_wx_code:
                print(f"忽略檢測(cè)【{personal_info['nickname']}】【{personal_info['wx_code']}】")
                self.d.press("back")
                continue

            # 判斷當(dāng)前好友是否已經(jīng)被檢測(cè)過(guò)了
            if personal_info['wx_code'] in self.friends_has_checked:
                print(f"已經(jīng)被檢測(cè)過(guò)了,跳過(guò)檢測(cè)【{personal_info['nickname']}】【{personal_info['wx_code']}】")
                self.d.press("back")
                continue

            # 判斷當(dāng)前好友的狀態(tài)
            status = self.judge_friend_status()
            if status == self.FRIEND_STATUS_HAS_DELETED:
                self.when_has_deleted()
            elif status == self.FRIEND_STATUS_HAS_BLACK:
                self.when_has_black()
            elif status == self.FRIEND_STATUS_ACCOUNT_PROBLEM:
                self.when_account_problem()
            elif status == self.FRIEND_STATUS_NORMAL:
                self.when_normal()
            else:
                print(f'當(dāng)前好友狀態(tài)未知 {status}')
                exit()

            # 將當(dāng)前好友的【狀態(tài)】和【個(gè)人信息】數(shù)據(jù)進(jìn)行合并
            personal_info['status'] = status
            print(personal_info)
            # 存儲(chǔ)當(dāng)前好友的信息
            write_content_to_file('./friends_info.log', personal_info)

            # 記錄所有被檢測(cè)好友的信息
            self.friends_list.append(personal_info)
            # 記錄已經(jīng)被檢測(cè)的好友信息
            self.friends_has_checked[personal_info['wx_code']] = personal_info

            # 判斷是否已經(jīng)檢查到最后一個(gè)好友
            if personal_info['wx_code'] == self.last_friend_wx_code:
                print('已經(jīng)檢查到最后一個(gè)好友')
                run_status = 'done'
                break

            time.sleep(1)
            # 退回到通訊錄列表頁(yè)面(重要!?。。?
            self.d.press("back")

        return run_status

    def all_friends_check(self):
        """
        開(kāi)始檢查所有好友
        :param self:
        :return:
        """
        # 檢查是否有設(shè)置最后一個(gè)好友的微信號(hào)
        if self.last_friend_wx_code == '':
            print('請(qǐng)先設(shè)置最后一個(gè)好友的微信號(hào)')
            return

        # 至少將自己的微信號(hào)加入到忽略檢測(cè)列表中(因?yàn)樽约翰荒芙o自己轉(zhuǎn)賬)
        if len(self.ignore_wx_code) == 0:
            print('至少將自己的微信號(hào)加入到忽略檢測(cè)列表中,否則會(huì)發(fā)生報(bào)錯(cuò)')
            return

        # 根據(jù)設(shè)定的最大頁(yè)數(shù),循環(huán)對(duì)通訊錄中的每一個(gè)好友進(jìn)行檢查
        i = 0
        while True:
            i += 1
            print(f"這是第 {i} 次翻頁(yè)")
            if i >= self.max_page_get_friend_list:
                break

            run_status = self.check_every_friend()
            if run_status == 'done':
                break

            time.sleep(1)
            # 一頁(yè)檢查完了之后,向上滑動(dòng)
            # self.d.swipe(100, 1000, 100, 500)
            self.d.swipe_ext("up", scale=0.9)
            # 向上滑動(dòng)之后,等待一會(huì)兒
            time.sleep(2)

        print('所有好友檢查完畢')

check_every_friend 方法遍歷好友列表,進(jìn)入每個(gè)好友的詳情頁(yè)面,根據(jù)好友的狀態(tài)進(jìn)行相應(yīng)的處理。如果好友狀態(tài)符合刪除、拉黑或賬號(hào)問(wèn)題,程序會(huì)為其打上對(duì)應(yīng)標(biāo)簽。

讓代碼跑起來(lái)

核心代碼已經(jīng)寫(xiě)完了,剩下的步驟就比較簡(jiǎn)單了,讓代碼跑起來(lái)就行了

def write_content_to_file(file_path: str, content):
    """
    將內(nèi)容寫(xiě)入文件
    :param file_path:
    :param content:
    :return:
    """
    content_json = json.dumps(content, ensure_ascii=False)
    with open(file_path, 'a', encoding='utf-8') as file_to_write:
        file_to_write.write(content_json + '\n')


if __name__ == '__main__':
    last_friend_wx_code = '123'

    # 需要被忽略檢測(cè)的微信號(hào)或者微信昵稱
    # 這里至少將自己的微信號(hào)加入到忽略檢測(cè)列表中(因?yàn)樽约翰荒芙o自己轉(zhuǎn)賬)
    # 并且也必須保留以下【微信團(tuán)隊(duì)】和【文件傳輸助手】
    ignore_wx_code = ['微信團(tuán)隊(duì)', '文件傳輸助手']

    max_page_get_friend_list = 8

    wx_clean = WXCleanFriends(last_friend_wx_code, ignore_wx_code, max_page_get_friend_list)

    # wx_clean.test_run()
    # exit()

    # 開(kāi)啟調(diào)試模式
    wx_clean.enable_debug()

    # 打開(kāi)微信
    # wx_clean.weixin_start()
    # 點(diǎn)擊【通訊錄】
    # wx_clean.open_contacts()
    # 讓通訊錄頁(yè)面加載完畢
    # time.sleep(3)

    # 開(kāi)始檢查所有好友
    wx_clean.all_friends_check()

    friends_list = wx_clean.get_friends_list()
    write_content_to_file('./friends_list.json', friends_list)
    print(friends_list)

總結(jié)

這款微信清理僵尸粉工具使用 Python 和 uiautomator2 庫(kù)通過(guò)自動(dòng)化方式幫助我們批量清理微信好友中的不活躍或無(wú)效好友。

通過(guò)檢查好友的狀態(tài)并為其打上標(biāo)簽,工具不僅提高了清理效率,也避免了人工逐個(gè)操作的繁瑣。對(duì)于開(kāi)發(fā)者而言,這個(gè)項(xiàng)目展示了如何結(jié)合 Python 與自動(dòng)化工具進(jìn)行高效的設(shè)備操作和應(yīng)用管理。

到此這篇關(guān)于基于Python制作一個(gè)全自動(dòng)微信清粉小工具的文章就介紹到這了,更多相關(guān)Python微信清粉內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解?python?logging日志模塊

    詳解?python?logging日志模塊

    這篇文章主要介紹了詳解?python?logging日志模塊,記錄日志最簡(jiǎn)單的方法就是在你想要記錄的地方加上一句?print?,?我相信無(wú)論是新手還是老鳥(niǎo)都經(jīng)常這么干。在簡(jiǎn)單的代碼中或者小型項(xiàng)目中這么干一點(diǎn)問(wèn)題都沒(méi)有,需要的朋友可以參考下
    2022-01-01
  • python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5窗口布局控件QStackedWidget詳細(xì)使用方法

    python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5窗口布局控件QStackedWidget詳細(xì)使用方法

    這篇文章主要介紹了python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5窗口布局控件QStackedWidget詳細(xì)使用方法,需要的朋友可以參考下
    2020-02-02
  • python項(xiàng)目下生成requirements.txt方法

    python項(xiàng)目下生成requirements.txt方法

    這篇文章主要介紹了python項(xiàng)目下生成requirements.txt的方法,很多小伙伴不知道如何生成requirements.txt,本文就通過(guò)代碼示例給大家詳細(xì)介紹如何生成,,需要的朋友可以參考下
    2023-06-06
  • Python列表元組字典集合存儲(chǔ)結(jié)構(gòu)詳解

    Python列表元組字典集合存儲(chǔ)結(jié)構(gòu)詳解

    本文詳細(xì)介紹了Python中列表、元組、字典和集合等數(shù)據(jù)結(jié)構(gòu)的定義、操作和用法,包括數(shù)據(jù)類型的相互嵌套、常用操作方法、循環(huán)遍歷等
    2025-02-02
  • python定時(shí)器(Timer)用法簡(jiǎn)單實(shí)例

    python定時(shí)器(Timer)用法簡(jiǎn)單實(shí)例

    這篇文章主要介紹了python定時(shí)器(Timer)用法,以一個(gè)簡(jiǎn)單實(shí)例形式分析了定時(shí)器(Timer)實(shí)現(xiàn)延遲調(diào)用的技巧,需要的朋友可以參考下
    2015-06-06
  • python如何使用requests提交post請(qǐng)求并上傳文件(multipart/form-data)

    python如何使用requests提交post請(qǐng)求并上傳文件(multipart/form-data)

    這篇文章主要給大家介紹了關(guān)于python如何使用requests提交post請(qǐng)求并上傳文件(multipart/form-data)的相關(guān)資料,Python有許多庫(kù)支持,它們可以簡(jiǎn)化HTTP上的數(shù)據(jù)傳輸,requests庫(kù)是最受歡迎的Python包之一,因?yàn)樗诰W(wǎng)絡(luò)刮削中被大量使用,需要的朋友可以參考下
    2023-11-11
  • Django 自定義權(quán)限管理系統(tǒng)詳解(通過(guò)中間件認(rèn)證)

    Django 自定義權(quán)限管理系統(tǒng)詳解(通過(guò)中間件認(rèn)證)

    這篇文章主要介紹了Django 自定義權(quán)限管理系統(tǒng)詳解(通過(guò)中間件認(rèn)證),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-03-03
  • 使用Python在Windows下獲取USB PID&VID的方法

    使用Python在Windows下獲取USB PID&VID的方法

    今天小編就為大家分享一篇使用Python在Windows下獲取USB PID&VID的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-07-07
  • Python基于opencv實(shí)現(xiàn)的簡(jiǎn)單畫(huà)板功能示例

    Python基于opencv實(shí)現(xiàn)的簡(jiǎn)單畫(huà)板功能示例

    這篇文章主要介紹了Python基于opencv實(shí)現(xiàn)的簡(jiǎn)單畫(huà)板功能,結(jié)合實(shí)例形式分析了Python使用opencv模塊進(jìn)行圖形繪制的相關(guān)操作技巧,需要的朋友可以參考下
    2019-03-03
  • Python的函數(shù)使用介紹

    Python的函數(shù)使用介紹

    這篇文章主要介紹了Python的函數(shù)使用,在兩種python循環(huán)語(yǔ)句的使用中,不僅僅是循環(huán)條件達(dá)到才能跳出循環(huán)體。所以,在對(duì)python函數(shù)進(jìn)行闡述之前,先對(duì)跳出循環(huán)的簡(jiǎn)單語(yǔ)句塊進(jìn)行介紹,需要的朋友可以參考一下
    2021-12-12

最新評(píng)論