不知道你有沒有經歷過,想聯繫一位很長時間沒有聯繫的朋友,發現對方很早以前已經把你刪除了,你還一無所知。
相信每個人的微信通信錄裡都存在一些「殭屍粉」,他們默默地躺在聯繫人列表中,你以為對方還是朋友,那就真是太年輕、太天真的;實際上,對方早就把從好友列表中刪了,那如何來篩選出這群人呢?
這裡要注意:不管你是剛學Python還是想找python高薪工作,記住:項目開發經驗永遠是核心,如果你沒有python入門到高級實戰視頻教程,可以關注我,後臺私信我 ‘py’ 自動獲取最新python教程資料!還有老司機解答哦!
網上的很大量檢測殭屍粉的工具,檢測的時候會給微信通信錄內的每一個好友發送一條檢測信息,嚴重「打擾」到對方;另外一部分軟件在檢測的時候,會植入一些代碼病毒,暗箱操作顯得很不安全。
本篇文章的目的是自動化操作微信 App,通過「模擬給好友轉賬」來篩選出所有的殭屍粉,並一鍵刪除它們。
2、準 備 工 作
在開始編寫腳本之前,需要做好如下準備工作
- 一部 Root 後的 Android 手機或者模擬器,如果沒有 Root 的設備,推薦使用網易 MuMu 模擬器
- Android 開發環境、Android Studio
- sqlcipher 圖形化工具
- 自動化工具:Python 虛擬環境下安裝 pocoui
3、編 寫 腳 本
整個操作分為 3 步驟,分別是破解微信數據庫篩選出通信錄中的好友、模擬給好友轉賬得到殭屍粉數據、刪除所有殭屍粉。
第 1 步,我們需要破解微信 App 的數據庫。
ps:這裡只是簡單的說一下破解流程,想一鍵破解微信通信錄數據,可以跳過這一步,直接使用文末提供的 APK。
首先,我們使用 Android Studio 新建一個項目,在項目初始化的時候,授予應用管理員權限以及修改微信目錄的讀寫權限。
<code> publicstatic
final
String
WX_ROOT_PATH ="/data/data/com.tencent.mm/"
; publicstatic
void execRootCmd(String
paramString) {try
{ Process localProcess = Runtime.getRuntime().exec("su"
); Object localObject = localProcess.getOutputStream(); DataOutputStream localDataOutputStream = new DataOutputStream((OutputStream) localObject);String
str
=String
.valueOf(paramString); localObject =str
+" "
; localDataOutputStream.writeBytes((String
) localObject); localDataOutputStream.flush(); localDataOutputStream.writeBytes("exit "
); localDataOutputStream.flush(); localProcess.waitFor(); localObject = localProcess.exitValue(); } catch (Exception localException) { localException.printStackTrace(); } } RootUtils.execRootCmd("chmod 777 -R "
+ WX_ROOT_PATH); /<code>
然後,獲取微信數據庫的密碼。
微信數據庫的密碼是由設備的 imei 和微信的 uid 進過 md5 算法生成的。
<code> publicstatic
String
getDbPassword(String
imei,String
uin) {if
(TextUtils.isEmpty(imei) || TextUtils.isEmpty(uin)) { Log.d("xag"
,"初始化數據庫密碼失敗:imei或uid為空"
);return
"密碼錯誤"
; }String
md5 = MD5Utils.md5(imei + uin); assert md5 !=null
;return
md5.substring(0
,7
).toLowerCase(); } /<code>
接著,就可以使用 SQLCipher 依賴庫來對微信數據庫進行查詢,我們需要為項目添加如下依賴,方便操作數據庫。
<code> implementation'net.zetetic:android-database-sqlcipher:3.5.4@aar'
/<code>
利用上面得到的密碼打開加密數據庫,然後查詢「rcontact」表獲取微信通訊錄內所有的好友的微信號、暱稱、用戶名等數據。
<code>private
void
openWxDb
(File dbFile, String db_pwd
) { List contacts =new
ArrayList<>(); SQLiteDatabase.loadLibs(this
); SQLiteDatabaseHook hook =new
SQLiteDatabaseHook() {public
void
preKey
(SQLiteDatabase database
) { }public
void
postKey
(SQLiteDatabase database
) { atabase.rawExecSQL("PRAGMA cipher_migrate;"
); } };try
{ SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbFile, db_pwd,null
, hook); Cursor c1 = db.rawQuery("select * from rcontact where verifyFlag =0 and type not in (2,4,8,9,33,35,256,258,512,2051,32768,32770,32776,33024,65536,65792,98304) and username not like "
%@app" and username not like "
%@qqim" and username not like "
%@chatroom" and encryptUsername!="
""
,null
);while
(c1.moveToNext()) { String userName = c1.getString(c1.getColumnIndex("username"
)); Stringalias
= c1.getString(c1.getColumnIndex("alias"
)); String nickName = c1.getString(c1.getColumnIndex("nickname"
));int
type = c1.getInt(c1.getColumnIndex("type"
)); contacts.add
(new
Contact(userName,alias
, nickName)); } Log.d("xag"
,"微信通訊錄中,聯繫人數目:"
+ contacts.size() +"個"
);for
(int
i =0
; i "xag", contacts.get
(i).getNickName()); } c1.close(); db.close(); }catch
(Exception e) { Log.e("xag"
,"讀取數據庫信息失敗"
+ e.toString()); Toast.makeText(this
,"讀取微信通信錄失敗!"
, Toast.LENGTH_SHORT).show(); } Toast.makeText(this
,"讀取微信通信錄成功!"
, Toast.LENGTH_SHORT).show(); } /<code>
需要注意的是,數據庫中 rcontact 表的數據比較雜亂,除了正常的好友數據,黑名單好友、已刪除好友、公眾號、微信群等數據也包含在內,需要我們通過 type 和 verifyFlag 字段進行篩選。
為了便於 Python 操作,最後將查詢的好友數據寫入到 csv 文件中。
<code>public
static
void
writeCsvFile
(String output_path, List contacts
) {try
{ File file =new
File(output_path);if
(file.exists()) { file.delete(); } BufferedWriter bw =new
BufferedWriter(new
FileWriter(file,true
)); bw.write("userName"
+","
+"alias"
+","
+"nickName"
); bw.newLine();for
(int
i =0
; i get(i).getUserName() +","
+ contacts.get
(i).getAlias() +","
+ contacts.get
(i).getNickName()); bw.newLine(); } bw.close(); }catch
(IOException e) { e.printStackTrace(); } }/<code>
第 2 步,我們需要模擬給好友轉賬,來判斷這個好友關係是否正常。
首先,我們需要初始化 Airtest,然後利用 adb 把第 1 步生成的數據從手機裡導出到本地。
<code>def
__init_airtest
(self)
:""" 初始化Airtest :return: """
device_1 = Android('822QEDTL225T7'
) connect_device("android:///"
) self.poco = AndroidUiautomationPoco(device_1, screenshot_each_action=False
) auto_setup(__file__)def
export_wx_db_from_phone
(target_path)
:""" 從手機中導出通信錄數據 :param target_path: :return: """
wx_db_source_path ="/data/data/com.xingag.crack_wx/wx_data.csv"
os.popen('adb pull %s %s'
% (wx_db_source_path, target_path)) /<code>
然後就是一系列自動化操作。
打開微信,遍歷好友列表,拿到每一個好友的微信號去搜索好友,跳轉到好友的聊天界面。
<code>def
__to_friend_chat_page
(self, weixin_id)
:""" 點擊到一個好友的聊天界面 :param weixin_id: :param weixin_name: :return: """
element_search = self.__wait_for_element_exists(self.id_search) element_search.click() print('點擊搜索'
) element_search_input = self.__wait_for_element_exists(self.id_search_input) element_search_input.set_text(weixin_id) element_search_result_list = self.__wait_for_element_exists(self.id_search_result_list) index_tips =0
for
index, element_search_resultin
enumerate(element_search_result_list.children()):if
element_search_result.offspring(text=self.text_contact_tips).exists(): index_tips = indexbreak
element_search_result_list.children()[index_tips +1
].click() /<code>
接著嘗試著給對方轉賬,如果好友關係正常,就會跳出一個支付頁面讓輸入密碼。
<code>def
__judge_is_friend
(
self
, weixin_id, weixin_name):""
" 判斷是不是微信好友 :param weixin_id: 微信號 :return: "
""
self
.poco(self
.id_chat_more_button).click()self
.poco(self
.id_chat_more_container).offspring(text=self
.text_chat_transfer_account_text).click()self
.poco(self
.id_transfer_account_input).set_text(self
.money)self
.poco(self
.id_transfer_account_container).offspring(text=self
.text_chat_transfer_account_text).click() /<code>
如果是殭屍粉,應用會彈出一個警告對話框,提示你不是收款方好友,沒法完成轉賬的操作。
通過警告對話框是否存在,就可以判斷好友關係是否正常。非正常的好友關係,包含:殭屍粉、對方賬號異常等。
<code>if
element_transfer_account_result_button: ransfer_account_result_tips =self
.poco(self
.id_transfer_account_result_tips).get_text()if
self
.text_friend_no_tips in transfer_account_result_tips:'注意!%s已經把你拉黑了!!!'
% weixin_name)self
.friend_black_list.append({'id'
: weixin_id,'nickName'
: weixin_name }) write_to_file(self
.path_black_list,'id:%s,nickName:%s'
% (weixin_id, weixin_name)) elifself
.text_friend_limit_tips in transfer_account_result_tips:'%s賬號收到限制!!!'
% weixin_name) write_to_file(self
.path_account_limit,'id:%s,nickName:%s'
% (weixin_id, weixin_name)) elifself
.text_friend_is_norm in transfer_account_result_tips:'%s好友關係不正常!!!'
% weixin_name) write_to_file(self
.path_relationship_unnormal,'id:%s,nickName:%s'
% (weixin_id, weixin_name)) element_transfer_account_result_button.click()self
.__back_to_home()else
:'好友關係正常'
)self
.__back_to_home() /<code>
最後,模擬點擊手機的返回鍵,一直回退到微信主界面。
<code>def
__back_to_home
(self)
:""" 回退到主界面 :return: """
print('準備回退到主界面'
) home_tips = ['微信'
,'通訊錄'
,'發現'
,'我'
]while
True
: keyevent('BACK'
) is_home =False
if
self.poco(text=home_tips[0
]).exists()and
self.poco(text=home_tips[1
]).exists()and
self.poco( text=home_tips[2
]).exists()and
self.poco(text=home_tips[3
]).exists(): is_home =True
if
is_home: print('已經回到微信首頁~'
)break
/<code>
循環上面的操作,就可以判斷出哪些是殭屍粉,哪些好友的賬號被限制,哪些是正常的好友關係。
第 3 步,刪除上面獲取到的殭屍粉列表。
拿到上面的殭屍粉數據列表,就可以利用上面的方式進行一系列自動化UI 操作,刪除掉這些好友。
<code>def
del_friend_black
(
self
, weixin_id):""
" 刪除黑名單好友 :return: "
""
self
.__to_friend_chat_page(weixin_id)self
.poco(self
.id_person_msg_button).click()self
.poco(self
.id_person_head_url).click()self
.poco(self
.id_person_manage_menu).click()self
.poco.swipe([0
.5
,0
.9
], [0
.5
,0
.3
], duration=0
.2
)self
.poco(self
.id_person_del, text=self
.text_person_del).click()self
.poco(self
.id_person_del_sure, text=self
.text_person_del).click()/<code>
4、結 果 結 論
編譯 Android 項目或者直接運行 APK 就能將微信通信錄的好友數據保存到項目文件目錄下。
然後運行 Python 程序會遍歷通訊錄好友數據,自動化去操作微信 App,接著將所有的殭屍粉寫入到本地文件中,最後可以選擇將這些殭屍粉全部刪除掉。
最後注意:不管你是剛學Python還是想找python高薪工作,記住:項目開發經驗永遠是核心,如果你缺新項目練習或者沒有python入門到高級實戰視頻教程,可以關注我,後臺私信我 ‘py’ 自動獲取最新python教程資料!還有老司機解答哦!
本文的文字及圖片來源於網絡加上自己的想法,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。