溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

誰偷偷刪了你的微信?別慌!一篇Python學(xué)習(xí)教程幫你都揪出來

發(fā)布時間:2020-08-19 07:03:32 來源:ITPUB博客 閱讀:134 作者:千鋒Python唐小強(qiáng) 欄目:編程語言

一. 目標(biāo)場景

不知道你有沒有經(jīng)歷過,想聯(lián)系一位很長時間沒有聯(lián)系的朋友,發(fā)現(xiàn)對方很早以前已經(jīng)把你刪除了,而你還一無所知。

相信每個人的微信通信錄里都存在一些「僵尸粉」,他們默默地躺在聯(lián)系人列表中,你以為對方還是朋友,那就真是太年輕、太天真的;實際上,對方早就把從好友列表中刪了,那如何來篩選出這群人呢?

我倒是知道一個方法,就是給對方轉(zhuǎn)賬,先輸入金額,點確定,如果對方把你刪了,會自動彈出一條,你不是收款方好友。。。這樣就能知道對方是不是把你刪了,但是,幾百號甚至有的伙伴幾千的微信好友,我們是不可能一個個去驗證的。

網(wǎng)上的很大量檢測僵尸粉的工具,檢測的時候會給微信通信錄內(nèi)的每一個好友發(fā)送一條檢測信息,嚴(yán)重「打擾」到對方;另外一部分軟件在檢測的時候,會植入一些代碼病毒,暗箱操作顯得很不安全。

誰偷偷刪了你的微信?別慌!一篇Python學(xué)習(xí)教程幫你都揪出來


這篇Python學(xué)習(xí)教程的目的是自動化操作微信 App,通過「模擬給好友轉(zhuǎn)賬」來篩選出所有的僵尸粉,并一鍵刪除它們。

二 . 準(zhǔn) 備 工 作

在正式的Python學(xué)習(xí)教程編寫腳本之前,需要做好如下準(zhǔn)備工作

  • 一部 Root 后的 Android 手機(jī)或者模擬器,如果沒有 Root 的設(shè)備,推薦使用網(wǎng)易 MuMu 模擬器

  • Android 開發(fā)環(huán)境、Android Studio

  • sqlcipher 圖形化工具

  • 自動化工具:Python 虛擬環(huán)境下安裝 pocoui

三 . 編 寫 腳 本

整個操作分為 3 步驟,分別是破解微信數(shù)據(jù)庫篩選出通信錄中的好友、模擬給好友轉(zhuǎn)賬得到僵尸粉數(shù)據(jù)、刪除所有僵尸粉。

第 1 步,我們需要破解微信 App 的數(shù)據(jù)庫。

ps:這里只是簡單的說一下破解流程,想一鍵破解微信通信錄數(shù)據(jù),可以跳過這一步,直接使用文末提供的 APK。

首先,我們使用 Android Studio 新建一個項目,在項目初始化的時候,授予應(yīng)用管理員權(quán)限以及修改微信目錄的讀寫權(quán)限。

//微信 App 的目錄
public static final String WX_ROOT_PATH = "/data/data/com.tencent.mm/";
/**
* 執(zhí)行l(wèi)inux指令
*
* @param paramString
*/
public static 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 + "\n";
localDataOutputStream.writeBytes((String) localObject);
localDataOutputStream.flush();
localDataOutputStream.writeBytes("exit\n");
localDataOutputStream.flush();
localProcess.waitFor();
localObject = localProcess.exitValue();
} catch (Exception localException)
{
localException.printStackTrace();
}
}
//獲取權(quán)限
RootUtils.execRootCmd("chmod 777 -R " + WX_ROOT_PATH);
然后,獲取微信數(shù)據(jù)庫的密碼。
微信數(shù)據(jù)庫的密碼是由設(shè)備的 imei 和微信的 uid 進(jìn)過 md5 算法生成的。
/**
* 根據(jù)imei和uin生成的md5碼,獲取數(shù)據(jù)庫的密碼(去前七位的小寫字母)
*
* @param imei
* @param uin
* @return
*/
public static String getDbPassword(String imei, String uin)
{
if (TextUtils.isEmpty(imei) || TextUtils.isEmpty(uin))
{
Log.d("xag", "初始化數(shù)據(jù)庫密碼失?。篿mei或uid為空");
return "密碼錯誤";
}
String md5 = MD5Utils.md5(imei + uin);
assert md5 != null;
return md5.substring(0, 7).toLowerCase();
}

接著,就可以使用 SQLCipher 依賴庫來對微信數(shù)據(jù)庫進(jìn)行查詢,我們需要為項目添加如下依賴,方便操作數(shù)據(jù)庫。

//我們需要對項目增加依賴
implementation 'net.zetetic:android-database-sqlcipher:3.5.4@aar'
利用上面得到的密碼打開加密數(shù)據(jù)庫,然后查詢「rcontact」表獲取微信通訊錄內(nèi)所有的好友的微信號、昵稱、用戶名等數(shù)據(jù)。
/**
* 連接數(shù)據(jù)庫
* <p>
* 常用庫介紹:【rcontact】聯(lián)系人表,【message】聊天消息表
*
* @param dbFile
*/
private void openWxDb(File dbFile, String db_pwd)
{
//所有聯(lián)系人
List<Contact> 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;"); //兼容2.0的數(shù)據(jù)庫
}
};
try
{
//打開數(shù)據(jù)庫連接
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbFile, db_pwd, null, hook);
//查詢所有聯(lián)系人
//過濾掉本人、群聊、公眾號、服務(wù)號等一些聯(lián)系人
//verifyFlag != 0:公眾號、服務(wù)號
//注意黑名單用戶,我-設(shè)置-隱私-通訊錄黑名單
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"));
String alias = 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", "微信通訊錄中,聯(lián)系人數(shù)目:" + contacts.size() + "個");
for (int i = 0; i < contacts.size(); i++)
{
Log.d("xag", contacts.get(i).getNickName());
}
c1.close();
db.close();
} catch (Exception e)
{
Log.e("xag", "讀取數(shù)據(jù)庫信息失敗" + e.toString());
Toast.makeText(this, "讀取微信通信錄失敗!", Toast.LENGTH_SHORT).show();
}
Toast.makeText(this, "讀取微信通信錄成功!", Toast.LENGTH_SHORT).show();
}

需要注意的是,數(shù)據(jù)庫中 rcontact 表的數(shù)據(jù)比較雜亂,除了正常的好友數(shù)據(jù),黑名單好友、已刪除好友、公眾號、微信群等數(shù)據(jù)也包含在內(nèi),需要我們通過 type 和 verifyFlag 字段進(jìn)行篩選。


誰偷偷刪了你的微信?別慌!一篇Python學(xué)習(xí)教程幫你都揪出來



為了便于 Python 操作,最后將查詢的好友數(shù)據(jù)寫入到 csv 文件中。

/***
* 寫入數(shù)據(jù)到csv中
* @param output_path
* @param contacts
*/
public static void writeCsvFile(String output_path, List<Contact> 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 < contacts.size(); i++)
{
bw.write(contacts.get(i).getUserName() + "," + contacts.get(i).getAlias() + "," + contacts.get(i).getNickName());
bw.newLine();
}
bw.close();
} catch (IOException e)
{
e.printStackTrace();
}
}

第 2 步,我們需要模擬給好友轉(zhuǎn)賬,來判斷這個好友關(guān)系是否正常。

首先,我們需要初始化 Airtest,然后利用 adb 把第 1 步生成的數(shù)據(jù)從手機(jī)里導(dǎo)出到本地。

def __init_airtest(self):
"""
初始化Airtest
:return:
"""
device_1 = Android('822QEDTL225T7')
# device_1 = Android('emulator-5554')
connect_device("android:///")
self.poco = AndroidUiautomationPoco(device_1, screenshot_each_action=False)
auto_setup(__file__)
def export_wx_db_from_phone(target_path):
"""
從手機(jī)中導(dǎo)出通信錄數(shù)據(jù)
:param target_path:
:return:
"""
# 微信通信錄數(shù)據(jù)
wx_db_source_path = "/data/data/com.xingag.crack_wx/wx_data.csv"
# 導(dǎo)出到本地
os.popen('adb pull %s %s' % (wx_db_source_path, target_path))

然后就是一系列自動化操作。

打開微信,遍歷好友列表,拿到每一個好友的微信號去搜索好友,跳轉(zhuǎn)到好友的聊天界面。

def __to_friend_chat_page(self, weixin_id):
"""
點擊到一個好友的聊天界面
:param weixin_id:
:param weixin_name:
:return:
"""
# 1、點擊搜索
element_search = self.__wait_for_element_exists(self.id_search)
element_search.click()
print('點擊搜索')
# 2、搜索框
element_search_input = self.__wait_for_element_exists(self.id_search_input)
element_search_input.set_text(weixin_id)
# 3、搜索列表
element_search_result_list = self.__wait_for_element_exists(self.id_search_result_list)
# 3.1 是否存在對應(yīng)的聯(lián)系人,如果存在就在第一個子View布局下
# 注意:可能出現(xiàn)最常用的聊天列表,這里需要進(jìn)行判斷
index_tips = 0
for index, element_search_result in enumerate(element_search_result_list.children()):
# 聯(lián)系人的Tips
# if element_search_result_list.children()[0].offspring(self.id_contact_tips).exists():
if element_search_result.offspring(text=self.text_contact_tips).exists():
index_tips = index
break
# 4、點擊第一個聯(lián)系人進(jìn)入聊天界面
element_search_result_list.children()[index_tips + 1].click()

接著嘗試著給對方轉(zhuǎn)賬,如果好友關(guān)系正常,就會跳出一個支付頁面讓輸入密碼。

def __judge_is_friend(self, weixin_id, weixin_name):
"""
判斷是不是微信好友
:param weixin_id: 微信號
:return:
"""
# 嘗試給好友轉(zhuǎn)賬,設(shè)置一個小額度,以防止刷臉直接支付了
# 如果對方是你的好友,接下來會讓你輸入密碼,關(guān)掉頁面就行了
# 如果對方不是你的好友,會提示不是你的好友,不能繼續(xù)操作了
# 5、點擊好友界面的+按鈕
self.poco(self.id_chat_more_button).click()
# 6、點擊轉(zhuǎn)賬按鈕
self.poco(self.id_chat_more_container).offspring(text=self.text_chat_transfer_account_text).click()
# 7、輸入金額
self.poco(self.id_transfer_account_input).set_text(self.money)
# 8、點擊轉(zhuǎn)賬按鈕
self.poco(self.id_transfer_account_container).offspring(text=self.text_chat_transfer_account_text).click()

如果是僵尸粉,應(yīng)用會彈出一個警告對話框,提示你不是收款方好友,沒法完成轉(zhuǎn)賬的操作。


誰偷偷刪了你的微信?別慌!一篇Python學(xué)習(xí)教程幫你都揪出來



通過警告對話框是否存在,就可以判斷好友關(guān)系是否正常。非正常的好友關(guān)系,包含:僵尸粉、對方賬號異常等。

# 10.彈出警告對話框
# 彈出好友關(guān)系不正常
if element_transfer_account_result_button:
# 提示內(nèi)容
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:
print('注意!%s已經(jīng)把你拉黑了!!!' % 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))
elif self.text_friend_limit_tips in transfer_account_result_tips:
print('%s賬號收到限制!!!' % weixin_name)
write_to_file(self.path_account_limit, 'id:%s,nickName:%s' % (weixin_id, weixin_name))
elif self.text_friend_is_norm in transfer_account_result_tips:
print('%s好友關(guān)系不正常!!!' % weixin_name)
write_to_file(self.path_relationship_unnormal, 'id:%s,nickName:%s' % (weixin_id, weixin_name))
# 點擊確認(rèn)按鈕
element_transfer_account_result_button.click()
# 返回到主頁面
self.__back_to_home()
else:
# 包含正常好友關(guān)系和對方賬號限制的情況
print('好友關(guān)系正常')
self.__back_to_home()
最后,模擬點擊手機(jī)的返回鍵,一直回退到微信主界面。
def __back_to_home(self):
"""
回退到主界面
:return:
"""
print('準(zhǔn)備回退到主界面')
home_tips = ['微信', '通訊錄', '發(fā)現(xiàn)', '我']
while True:
keyevent('BACK')
is_home = False
# 判斷是否到達(dá)首頁
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('已經(jīng)回到微信首頁~')
break

循環(huán)上面的操作,就可以判斷出哪些是僵尸粉,哪些好友的賬號被限制,哪些是正常的好友關(guān)系。

第 3 步,刪除上面獲取到的僵尸粉列表。

拿到上面的僵尸粉數(shù)據(jù)列表,就可以利用上面的方式進(jìn)行一系列自動化UI 操作,刪除掉這些好友。

def del_friend_black(self, weixin_id):
"""
刪除黑名單好友
:return:
"""
# 到好友聊天界面
self.__to_friend_chat_page(weixin_id)
# 點擊聊天界面右上角,進(jìn)入到好友的詳細(xì)信息界面
self.poco(self.id_person_msg_button).click()
# 點擊好友頭像
self.poco(self.id_person_head_url).click()
# 點擊個人名片的右上角,彈出好友操作菜單
self.poco(self.id_person_manage_menu).click()
# 查找刪除操作欄
# 注意:對于目前主流的手機(jī),都需要滑動到最底部才能出現(xiàn)【刪除】這一操作欄
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()

四 .結(jié) 論

編譯 Android 項目或者直接運行 APK 就能將微信通信錄的好友數(shù)據(jù)保存到項目文件目錄下。

然后運行 Python 程序會遍歷通訊錄好友數(shù)據(jù),自動化去操作微信 App,接著將所有的僵尸粉寫入到本地文件中,最后可以選擇將這些僵尸粉全部刪除掉。

想試試你的微信好友通訊錄有僵尸粉不,試一下呀!?更多的Python學(xué)習(xí)教程和一些小技巧會不定期為大家更新。大家可以用期待一下下呀!


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI