基于Python制作一個(gè)全自動(dòng)微信清粉小工具
在當(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 GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5窗口布局控件QStackedWidget詳細(xì)使用方法
這篇文章主要介紹了python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5窗口布局控件QStackedWidget詳細(xì)使用方法,需要的朋友可以參考下2020-02-02python項(xiàng)目下生成requirements.txt方法
這篇文章主要介紹了python項(xiàng)目下生成requirements.txt的方法,很多小伙伴不知道如何生成requirements.txt,本文就通過(guò)代碼示例給大家詳細(xì)介紹如何生成,,需要的朋友可以參考下2023-06-06Python列表元組字典集合存儲(chǔ)結(jié)構(gòu)詳解
本文詳細(xì)介紹了Python中列表、元組、字典和集合等數(shù)據(jù)結(jié)構(gòu)的定義、操作和用法,包括數(shù)據(jù)類型的相互嵌套、常用操作方法、循環(huán)遍歷等2025-02-02python定時(shí)器(Timer)用法簡(jiǎn)單實(shí)例
這篇文章主要介紹了python定時(shí)器(Timer)用法,以一個(gè)簡(jiǎn)單實(shí)例形式分析了定時(shí)器(Timer)實(shí)現(xiàn)延遲調(diào)用的技巧,需要的朋友可以參考下2015-06-06python如何使用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-11Django 自定義權(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的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07Python基于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