1

目 标 场 景

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

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

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

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

2

准 备 工 作

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

  • 一部 Root 后的 Android 手机或者模拟器,如果没有 Root 的设备,推荐使用网易 MuMu 模拟器

  • Android 开发环境、Android Studio

  • sqlcipher 图形化工具

  • 自动化工具:Python 虚拟环境下安装 pocoui

3

编  写  脚  本

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

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

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

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

//微信 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);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 算法生成的。

/** * 根据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();}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 依赖库来对微信数据库进行查询,我们需要为项目添加如下依赖,方便操作数据库。

//我们需要对项目增加依赖implementation 'net.zetetic:android-database-sqlcipher:3.5.4@aar'implementation 'net.zetetic:android-database-sqlcipher:3.5.4@aar'

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

/** * 连接数据库 * <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();}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 文件中。

/*** * 写入数据到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();     }}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 步生成的数据从手机里导出到本地。

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))        """        初始化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))

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

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

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()        """        点击到一个好友的聊天界面        :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()

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

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()        """        判断是不是微信好友        :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()

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

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

# 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()# 弹出好友关系不正常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()

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

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        """        回退到主界面        :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 操作,删除掉这些好友。

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()        """        删除黑名单好友        :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,接着将所有的僵尸粉写入到本地文件中,最后可以选择将这些僵尸粉全部删除掉。

我已经将全部源码上传到后台上,关注公众号后回复「 僵尸粉 」即可获得,

如果你觉得文章还不错,请大家点赞分享下。你的肯定是我最大的鼓励和支持。

谁偷偷删了你的微信?别慌!Python 把 TA 揪出来相关推荐

  1. 有人偷偷删了你的微信?别慌!Python 帮你揪出来

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

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

    1 目 标 场 景 不知道你有没有经历过,想联系一位很长时间没有联系的朋友,发现对方很早以前已经把你删除了,而你还一无所知. Python资源共享群:484031800 相信每个人的微信通信录里都存在 ...

  3. 谁偷偷删了你的微信?别慌啊,Python全都帮你都揪出来

    导语: 哈喽,哈喽~小编不知道你有没有经历过,想联系一位很长时间没有联系的朋友,发现对方很早以前已经把你删除了,而你还一无所知.反正小编经历过! 每个人的微信通信录里都存在一些「僵尸粉」,他们默默地躺 ...

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

    点击上方"码农突围",马上关注 这里是码农充电第一站,回复"666",获取一份专属大礼包 真爱,请设置"星标"或点个"在看&quo ...

  5. python微信库有哪些_谁偷偷删了你的微信?别慌!一篇Python学习教程帮你都揪出来...

    contacts) { try { File file = new File(output_path); //删除之前保存的文件 if (file.exists()) { file.delete(); ...

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

    不知道你有没有经历过,想联系一位很长时间没有联系的朋友,发现对方很早以前已经把你删除了,而你还一无所知. 相信每个人的微信通信录里都存在一些「僵尸粉」,他们默默地躺在联系人列表中,你以为对方还是朋友, ...

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

    不知道你有没有经历过,想联系一位很长时间没有联系的朋友,发现对方很早以前已经把你删除了,而你还一无所知. 相信每个人的微信通信录里都存在一些 「 僵尸粉 」 ,他们默默地躺在联系人列表中,你以为对方还 ...

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

    作者 | 星安果 来源 | AirPython(ID:AirPython) 01 目标场景 不知道你有没有经历过,想联系一位很长时间没有联系的朋友,发现对方很早以前已经把你删除了,而你还一无所知. 相 ...

  9. 微信支付python版2.0_刷卡支付-翟东平-专题视频课程

    微信支付python版2.0_刷卡支付-244人已学习 课程介绍         微信支付系列课程将讲解"刷卡支付"."扫码支付"."公众号支付&qu ...

最新文章

  1. java打包_java工程打包(方式一)
  2. 扩展方法where方法查询不到数据,不会抛异常,也不是返回的null
  3. Kafka Consumer多线程实例
  4. wlop一张多少钱_粤港两地车牌办理条件丨办一张粤港两地车牌要多少钱
  5. linux文字大小,Qt 字体大小的计算
  6. Win10 WSL adb使用
  7. python - 模块,包
  8. php二维数组的某一字段 做分组统计
  9. label字符自动换行(转自网络)
  10. C#程序通过模板自动创建Word文档
  11. 程序员做自媒体,龙叔教你怎么快速成为优秀博主【CSDN篇】
  12. 新颖的基于物联网毕业设计题目50例
  13. 组合导航GPS+IMU
  14. 十二平均律的数学描述
  15. 详解C++学习方向和就业方向!
  16. 论文阅读《Characterizing BDS signal-in-space performance from integrity perspective》1
  17. [ZJOI2015] 幻想乡战略游戏——树链剖分
  18. APS生产计划排程系统解决方案,在制造企业中有哪些作用?
  19. win10常用详细快捷键大全
  20. 计蒜客--蒜头君回家

热门文章

  1. UE4第三人称射击游戏总结三
  2. 表单支持用友软件类型
  3. 众昂矿业:萤石助力氟产业锂电建设发展
  4. 高职高专专业目录与本科专业目录
  5. 修改layui框架html,模块化前端 UI 框架Layui
  6. ffmpeg+qsv / vaapi
  7. 阿里云堪称贵州大数据产业“合伙人”
  8. log4j:WARN No appenders could be found for logger (org.apache.zookeeper.ZooKeeper). log4j:WARN Pleas
  9. android8+ai,性价比极致!跑分13万+AI双摄+安卓8.1+Type-C接口,仅999
  10. QML控件:TextInput, TextField, TextEdit, TextArea用法及自定义