Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >谁偷偷删了你的微信?别慌!Python 帮你都揪出来了

谁偷偷删了你的微信?别慌!Python 帮你都揪出来了

作者头像
吴延宝
发布于 2019-08-01 06:54:50
发布于 2019-08-01 06:54:50
1.1K00
代码可运行
举报
运行总次数:0
代码可运行

1

目 标 场 景

不知道你有没有经历过,想联系一位很长时间没有联系的朋友,发现对方很早以前已经把你删除了,而你还一无所知。

相信每个人的微信通信录里都存在一些「僵尸粉」,他们默默地躺在联系人列表中,你以为对方还是朋友,那就真是太年轻、太天真的;实际上,对方早就把从好友列表中删了,那如何来筛选出这群人呢?

网上的很大量检测僵尸粉的工具,检测的时候会给微信通信录内的每一个好友发送一条检测信息,严重「打扰」到对方;另外一部分软件在检测的时候,会植入一些代码病毒,暗箱操作显得很不安全。

本篇文章的目的是自动化操作微信 App,通过「模拟给好友转账」来筛选出所有的僵尸粉,并一键删除它们。

2

准 备 工 作

在开始编写脚本之前,需要做好如下准备工作

  • 一部 Root 后的 Android 手机或者模拟器,如果没有 Root 的设备,推荐使用网易 MuMu 模拟器
  • Android 开发环境、Android Studio
  • sqlcipher 图形化工具
  • 自动化工具:Python 虚拟环境下安装 pocoui

3

编 写 脚 本

整个操作分为 3 步骤,分别是破解微信数据库筛选出通信录中的好友、模拟给好友转账得到僵尸粉数据、删除所有僵尸粉。

第 1 步,我们需要破解微信 App 的数据库。

ps:这里只是简单的说一下破解流程,想一键破解微信通信录数据,可以跳过这一步,直接使用文末提供的 APK。

首先,我们使用 Android Studio 新建一个项目,在项目初始化的时候,授予应用管理员权限以及修改微信目录的读写权限。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//微信 App 的目录
public static final String WX_ROOT_PATH = "/data/data/com.tencent.mm/";

/**
 * 执行linux指令
 *
 * @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();
    }
}

//获取权限
RootUtils.execRootCmd("chmod 777 -R " + WX_ROOT_PATH);

然后,获取微信数据库的密码。

微信数据库的密码是由设备的 imei 和微信的 uid 进过 md5 算法生成的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 根据imei和uin生成的md5码,获取数据库的密码(去前七位的小写字母)
 *
 * @param imei
 * @param uin
 * @return
 */
public static 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();
}

接着,就可以使用 SQLCipher 依赖库来对微信数据库进行查询,我们需要为项目添加如下依赖,方便操作数据库。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//我们需要对项目增加依赖
implementation 'net.zetetic:android-database-sqlcipher:3.5.4@aar'

利用上面得到的密码打开加密数据库,然后查询「rcontact」表获取微信通讯录内所有的好友的微信号、昵称、用户名等数据。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 连接数据库
 * <p>
 * 常用库介绍:【rcontact】联系人表,【message】聊天消息表
 *
 * @param dbFile
 */
private void openWxDb(File dbFile, String db_pwd)
{
    //所有联系人
    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的数据库
        }
    };

    try
    {
        //打开数据库连接
        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbFile, db_pwd, null, hook);
         //查询所有联系人
         //过滤掉本人、群聊、公众号、服务号等一些联系人
         //verifyFlag != 0:公众号、服务号
         //注意黑名单用户,我-设置-隐私-通讯录黑名单

         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", "微信通讯录中,联系人数目:" + 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", "读取数据库信息失败" + e.toString());
          Toast.makeText(this, "读取微信通信录失败!", Toast.LENGTH_SHORT).show();
    }

    Toast.makeText(this, "读取微信通信录成功!", Toast.LENGTH_SHORT).show();
}

需要注意的是,数据库中 rcontact 表的数据比较杂乱,除了正常的好友数据,黑名单好友、已删除好友、公众号、微信群等数据也包含在内,需要我们通过 type 和 verifyFlag 字段进行筛选。

为了便于 Python 操作,最后将查询的好友数据写入到 csv 文件中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/***
 * 写入数据到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 步,我们需要模拟给好友转账,来判断这个好友关系是否正常。

首先,我们需要初始化 Airtest,然后利用 adb 把第 1 步生成的数据从手机里导出到本地。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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):
    """
    从手机中导出通信录数据
    :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))

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

打开微信,遍历好友列表,拿到每一个好友的微信号去搜索好友,跳转到好友的聊天界面。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 是否存在对应的联系人,如果存在就在第一个子View布局下
        # 注意:可能出现最常用的聊天列表,这里需要进行判断
        index_tips = 0
        for index, element_search_result in enumerate(element_search_result_list.children()):
            # 联系人的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、点击第一个联系人进入聊天界面
        element_search_result_list.children()[index_tips + 1].click()

接着尝试着给对方转账,如果好友关系正常,就会跳出一个支付页面让输入密码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def __judge_is_friend(self, weixin_id, weixin_name):
        """
        判断是不是微信好友
        :param weixin_id: 微信号
        :return:
        """
        # 尝试给好友转账,设置一个小额度,以防止刷脸直接支付了
        # 如果对方是你的好友,接下来会让你输入密码,关掉页面就行了
        # 如果对方不是你的好友,会提示不是你的好友,不能继续操作了
        # 5、点击好友界面的+按钮
        self.poco(self.id_chat_more_button).click()

        # 6、点击转账按钮
        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、点击转账按钮
        self.poco(self.id_transfer_account_container).offspring(text=self.text_chat_transfer_account_text).click()

如果是僵尸粉,应用会弹出一个警告对话框,提示你不是收款方好友,没法完成转账的操作。

通过警告对话框是否存在,就可以判断好友关系是否正常。非正常的好友关系,包含:僵尸粉、对方账号异常等。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 10.弹出警告对话框
# 弹出好友关系不正常
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:
         print('注意!%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))
     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好友关系不正常!!!' % 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:
     # 包含正常好友关系和对方账号限制的情况
     print('好友关系正常')
     self.__back_to_home()

最后,模拟点击手机的返回键,一直回退到微信主界面。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

循环上面的操作,就可以判断出哪些是僵尸粉,哪些好友的账号被限制,哪些是正常的好友关系。

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

拿到上面的僵尸粉数据列表,就可以利用上面的方式进行一系列自动化UI 操作,删除掉这些好友。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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()

4

结 果 结 论

编译 Android 项目或者直接运行 APK 就能将微信通信录的好友数据保存到项目文件目录下。

然后运行 Python 程序会遍历通讯录好友数据,自动化去操作微信 App,接着将所有的僵尸粉写入到本地文件中,最后可以选择将这些僵尸粉全部删除掉。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT烂笔头 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
手撸了一个全自动微信清粉小工具(源码详解)
文章链接:https://cloud.tencent.com/developer/article/2464880
南山竹
2024/12/01
2360
手撸了一个全自动微信清粉小工具(源码详解)
太鸡冻了!我用 Python 偷偷查到暗恋女生的名字
不知道你有没有经历过这样一个场景,好不容易拿到一个妹子的手机号,但是又不好意思去搭讪,问一下对方的名字。
小小詹同学
2019/09/25
6630
太鸡冻了!我用 Python 偷偷查到暗恋女生的名字
太鸡冻了!我用 Python 偷偷查到暗恋女生的名字
不知道你有没有经历过这样一个场景,好不容易拿到一个妹子的手机号,但是又不好意思去搭讪,问一下对方的名字。
Python进阶者
2019/10/15
5460
太鸡冻了!我用 Python 偷偷查到暗恋女生的名字
薅羊毛 | Python 自动化带你轻松赚钱
最近,有一个朋友告诉我,她在某平台上购买了一部手机,收到货之后发现商品质量挺好的,价格也不贵。
数据森麟
2019/10/15
1.1K0
薅羊毛 | Python 自动化带你轻松赚钱
闲鱼上哪些商品抢手?Python 分析后告诉你
经常看到有朋友在闲鱼卖些小东西又或是自己擅长的一些技能,都能为他们带来不错的 睡后收入。
龙哥
2019/10/29
8900
闲鱼上哪些商品抢手?Python 分析后告诉你
薅羊毛 | 让Python每天帮你薅一个早餐钱
以今日头条极速版为首,包含趣头条、东方头条、全名小视频在内的 App 都有看新闻、视频送金币的活动,当金币达到一定量后,就可以提现到微信、支付包。
sergiojune
2019/05/15
9400
薅羊毛 | 让Python每天帮你薅一个早餐钱
薅羊毛 | Python 带你抢视频红包,不放过一个红包!
如今短视频横行的时代,以某短视频为首的,背后依靠着强大的资金后盾,疯狂地对平台用户进行红包轰炸。
AirPython
2019/09/20
5920
薅羊毛 | Python 带你抢视频红包,不放过一个红包!
Vue2 全家桶仿 微信App 项目,支持多人在线聊天和机器人聊天
IMWeb前端团队
2017/12/29
1.8K0
数据 | 基于 Python 分析微信好友数据
最近微信迎来了一次重要的更新,允许用户对"发现"页面进行定制。不知道从什么时候开始,微信朋友圈变得越来越复杂,当越来越多的人选择"仅展示最近三天的朋友圈",大概连微信官方都是一脸的无可奈何。逐步泛化的好友关系,让微信从熟人社交逐渐过渡到陌生人社交,而朋友圈里亦真亦幻的状态更新,仿佛在努力证明每一个个体的"有趣"。
前端教程
2018/07/27
9540
数据 | 基于 Python 分析微信好友数据
通过标签清理微信好友:Python自动化脚本解析
文章链接:https://cloud.tencent.com/developer/article/2469689
南山竹
2024/12/02
1430
通过标签清理微信好友:Python自动化脚本解析
用Python找出了删除自己微信的所有人并将他们自动化删除了
你是否有微信被删了好友不自知,还傻傻的给对方发消息,结果出现了下图中那尴尬的一幕的经历呢?其实我们可以用Python提前把他们找出来并自动化删除避免尴尬的。
老虎也淘气
2024/01/30
2460
用Python找出了删除自己微信的所有人并将他们自动化删除了
关于微信和Python的点点滴滴
微信自上线以来,一直没有自动回复的功能,想必是有他们的理念。但是有些人群,确实对此功能有一定需求,我举两个栗子:
IT派
2018/08/10
5290
关于微信和Python的点点滴滴
实现微信机器人开发
首先微信聊天机器人,是一种通过自然语言模拟人类进行对话的程序。通常运行在特定的软件平台上,如PC平台或者移动终端设备平台。
全栈程序员站长
2022/07/02
2.2K0
实现微信机器人开发
python之抓取微信公众号文章系列2
微信公众号历史的所有文章(来源???) 每篇文章的阅读量和点赞量(电脑上浏览文章只显示内容,没有阅读量、点赞量、评论……)
周小董
2019/03/25
4.5K1
python之抓取微信公众号文章系列2
想查看微信好友撤回的消息?Python帮你搞定
比如你现在正和女朋友用微信聊着天,或者跟自己喜欢的女孩子聊着天,一个不留神,你没注意到对方发的消息就被她及时撤回了,这时你很好奇,好奇她到底发了什么?于是你打算问问她发了什么,结果她回一句"没什么"。这一回复,让你的好奇心更加强烈了,顿时就感觉消息撤回这一功能就是用来折磨人的。
wangweijun
2020/01/17
1.2K0
在微信好友信息抓取这一块,这才是最好的python分析技巧!
早些日子有人问我我的微信里面有一共多少朋友,我就随后拉倒了通讯录最下面就找到了微信一共有多少位好友。然后他又问我,这里面你认识多少人?
诸葛青云
2018/09/12
2K0
在微信好友信息抓取这一块,这才是最好的python分析技巧!
python3爬取墨迹天气并发送给微信好
先随便观察一个城市的墨迹天气,例如石家庄市的url为“https://tianqi.moji.com/weather/china/hebei/shijiazhuang”,多观察几个城市的url可发现共同点就是,前面的都一样,后面的是以省拼音/市拼音结尾的。当然直辖市两者拼音一样。当然还有一些额外情况,比如山西和陕西,后者的拼音是Shaanxi,这个用户输入的时候注意一下
py3study
2020/01/03
1.2K0
python3爬取墨迹天气并发送给微信好
Python模拟登陆 —— 征服验证码 8 微信网页版
微信登录界面 微信网页版使用了UUID含义是通用唯一识别码来保证二维码的唯一性。 先用一个伪造的appid获得uuid。 params = { 'appid': 'wx782c26e4c19acffb', 'fun': 'new', 'lang': 'zh_CN', '_': int(time.time()), } 不伪造的话,会有400错误,拿不到uuid。 二维码在网页源代码也是查不到的,这时就需要uuid了。 url =
SeanCheney
2018/04/24
3.5K0
Python模拟登陆 —— 征服验证码 8 微信网页版
用 Python 在朋友圈中游遍全球
十一长假,相信大部分的朋友这会应该是在全国各地浪或者是在浪的路上,朋友圈成为你们表演的场所。
小小詹同学
2019/10/10
9770
用 Python 在朋友圈中游遍全球
简单三步,让你玩转微信自动邀请加群!!!
很多管理大量微信社群的小伙伴都有这样的场景,当微信群的人数达到100人之后,将不能在通过分享的群二维码加入群里,必须自主添加好友后,手动去邀请才能加用户拉入群众,如果有大量的用户加群,就只能一个一个手动的拉,想想心情就很美丽,手动哭泣。。。。
执行上下文
2022/07/26
3K0
推荐阅读
相关推荐
手撸了一个全自动微信清粉小工具(源码详解)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验