用 Python 分析微信群聊记录,是怎样一种体验?

开发 后端
前几天,有一位小伙伴在后台给我留言,说自己有几十个微信群,自己精力有限,没法看过来,想要筛选一些高质量的群,让我是否能帮忙想想办法。

 1. 场景

前几天,有一位小伙伴在后台给我留言,说自己有几十个微信群,自己精力有限,没法看过来,想要筛选一些高质量的群,让我是否能帮忙想想办法。

[[322556]]

其实,微信群里的所有聊天记录都在手机本地文件夹内,只需要导出来进行解密,然后来一波数据分析,就可以帮他筛选出高质量的社群。

本篇文章将带大家用 Python 一步步来实现这个功能。

2. 实现步骤

第 1 步,导出微信聊天记录数据库

首先,我们使用一部 Root 后的手机或者模拟器登录微信,找到微信聊天记录数据库,然后导出到本地。

数据库文件的完整路径如下:

 

  1. # 微信聊天记录数据库完整路径 
  2. /data/data/com.tencent.mm/MicroMsg/[当前登录微信的随机字符串]/EnMicroMsg.db 

需要注意的是,如果当前设备没有 Root,可以选择群聊消息进行一次迁移,然后从 Root 设备或模拟器中导出数据库。

第 2 步,获取数据库的密码

微信数据库的密码组成形式为:手机 IMEI + 微信 UIN,然后 md5 加密(32 位小写)的前 7 个数字。

其中,手机的 IMEI 可以通过 *#06# 获取,如果是双卡手机,需要自己做一下判断。

 

 

 

 

微信的 UIN 在下面配置文件中,找到 name 属性为 default_uin 的 value 值,即为 UIN

 

  1. # 当前登录微信的配置文件 
  2. /data/data/com.tencent.mm/shared_prefs/system_config_prefs.xml 

最后,然后将 IMET 和 UIN 组成字符串,然后利用 MD5 进行加密,取 32 位小写的前 7 位即为微信数据库的密码。

 

 

 

 

第 3 步,破解数据库

由于微信数据库是使用 SQLCipher 生成,所以要先安装 sqlcipher 命令行文件

 

  1. # 安装sqlcipher命令行(Mac) 
  2. brew install sqlcipher 
  3.  
  4. # Win可以去下载sqlcipher命令行文件 

然后,输入数据库的密码及解密方式等,导出破解后的数据库。

 

 

 

 

第 4 步,分析数据库

推荐使用 SQLiteSutdio 打开并分析上面破解后的数据库,重点查看 message、rcontact、chatroom 这 3 张表。

微信所有的文字聊天记录都存放在 mesage 数据表中,包含:聊天内容、发送者、消息类型、创建时间等

 

 

 

 

rcontact 为微信通讯录表,包含:微信 ID、昵称、备注名等

chatroom 是群聊信息表,包含:群聊 ID、成员列表等

第 5 步,Python 打开数据库并封装

使用 sqlite3 连接本地数据库文件,获取数据库对象和游标对象

 

  1. import sqlite3 
  2.  
  3. def __init__(self, db_path="./weixin.db"): 
  4.     ""
  5.     本地数据库初始化 
  6.     ""
  7.     self.db = sqlite3.connect(db_path) 
  8.     self.cursor = self.db.cursor() 

接着,对数据库常用的操作,包含:增删改查,进行封装操作。

 

  1. def execute(self, sql, param=None): 
  2.     ""
  3.     sql: Sql语句,包含:增、删、改 
  4.     param:数据,可以为列表、字典,也可以为空 
  5.     ""
  6.     try: 
  7.         if param is None: 
  8.             self.cursor.execute(sql) 
  9.         else
  10.             if type(param) is list: 
  11.                 self.cursor.executemany(sql, param) 
  12.             else
  13.                 self.cursor.execute(sql, param) 
  14.             count = self.db.total_changes 
  15.             self.db.commit() 
  16.     except Exception as e: 
  17.         print(e) 
  18.         return False, e 
  19.  
  20.     # 返回结果 
  21.     return True if count > 0 else False 
  22.  
  23. def query(self, sql, param=None): 
  24.     ""
  25.     查询语句 
  26.     sql:Sql语句 
  27.     param:参数,可以包含空 
  28.     retutn:成功返回True 
  29.     ""
  30.     if param is None: 
  31.         self.cursor.execute(sql) 
  32.     else
  33.         self.cursor.execute(sql, param) 
  34.  
  35.     # 返回查询的结果 
  36.     return self.cursor.fetchall() 

第 6 步,通过群聊名称获取群聊 ID

根据群聊昵称,使用 Sql 语句查询 rcontact 表,可以获取群聊的 ID 值

 

  1. def __get_chartroom_id(self): 
  2.     ""
  3.     获取群聊的id 
  4.     :return
  5.     ""
  6.     res = self.db.query('select username from rcontact where nickname=?;', (self.chatroom_name,)) 
  7.  
  8.     # 群聊id 
  9.     chatroom_id = res[0][0] 
  10.  
  11.     return chatroom_id 

第 7 步,获取群聊消息

拥有群聊 ID 之后,紧接着查询 message 表,获取当前群聊的所有消息内容。

 

  1. # message表:聊天记录表 
  2. # isSend=0:对方发送的;isSend=1:自己发送的 
  3. sql = "SELECT content FROM message WHERE talker='{}' and isSend=0".format(chatroom_id) 
  4.  
  5. # 查询表,获取所有的聊天记录 
  6. result = self.db.query(sql) 

为了获取有效的消息内容,可以清洗掉自己发送的消息、系统消息、红包消息等内容

 

  1. # 循环查询到的所有的消息 
  2. for item in result: 
  3.     # 过滤数据 
  4.     if not item or not item[0] or item[0].find('xml') != -1 or item[0].find('sysmsg') != -1 or item[0].find( 
  5.                     '<msg>') != -1 or item[0].find('chatroom') != -1 or item[0].find('weixinhongbao') != -1: 
  6.          continue 
  7.     # 过滤掉自己发送的内容,不包含: 
  8.     temps = item[0].split(':'
  9.     if len(temps) < 2: 
  10.         # print('自己发送的内容:' + item[0]) 
  11.         continue 
  12.     # 每一条聊天记录,过滤掉发送者,只保留消息正文 
  13.     # 发送者 
  14.     send_from = item[0].split(':')[0] 
  15.  
  16.     # 发送内容 
  17.     send_msg = "".join(item[0].split(':')[1:]).strip().replace("\""""
  18.     # 过长的消息,也过滤掉 
  19.     if len(send_msg) > 200: 
  20.          continue 

对于群其他成员发送的内容,再过滤掉消息内容的前半部分,只保留消息正文

 

 

 

 

第 8 步,生成词云

使用 jieba 对群内有效的消息进行分词,然后使用 wordcloud 生成词云图。

 

  1. def generate_wordcloud(self, word): 
  2.     ""
  3.     生成词云 
  4.     :param word: 
  5.     :return
  6.     ""
  7.  
  8.     img = WordCloud(font_path="./DroidSansFallbackFull.ttf", width=2000, height=2000, 
  9.                         margin=2, collocations=False).generate(word) 
  10.     plt.imshow(img) 
  11.     plt.axis("off"
  12.     plt.show() 
  13.  
  14.     # 保存图片 
  15.     img.to_file("{}.png".format("群聊")) 
  16.  
  17. # 分词 
  18. temp = " ".join(jieba.cut(words, cut_all=True)) 
  19.  
  20. # 生成词云 
  21. generate_wordcloud(temp

第 9 步,新建排名表,插入数据

为了统计群聊活跃度排名,我们需要新建一张表,包含:id、微信昵称、消息内容 3 个字段。

 

  1. def __create_top_table(self): 
  2.    ""
  3.    创建Top表 
  4.    :return
  5.    ""
  6.    # 创建Top表,如果存在就不重新创建 
  7.    result = self.db.execute
  8.             "CREATE TABLE IF NOT EXISTS top(uid integer primary key,name varchar(200),msg varchar(200))"

接着,将上一步的每一条消息中的发送者 ID、发送内容 2 个字段插入到新建的 Top 表内

 

  1. # 定义一个列表,加入所有要统计的数据 
  2. msg_pre = [] 
  3.  
  4. for item in result: 
  5.     # 发送者 
  6.     send_from = item[0].split(':')[0] 
  7.     # 发送内容 
  8.     send_msg = "".join(item[0].split(':')[1:]).strip().replace("\""""
  9.     msg_pre.append((send_from, send_msg)) 
  10.  
  11.  # 把要统计的数据,插入到top表中 
  12.  self.db.execute("insert into top(uid,name,msg) values (NULL,?,?);", msg_pre) 

第 10 步,获取活跃度排名并可视化

从 Top 数据表中,通过微信昵称查询出每一位成员发言的次数,并保存到一个列表中

 

  1. def get_top_partner(self): 
  2.     ""
  3.     排名前15的成员 
  4.     :return
  5.     ""
  6.     sql = "SELECT name as 姓名,COUNT(*) as times FROM top GROUP BY name ORDER BY times DESC limit %d;" % self.top_num 
  7.     result = self.db.query(sql) 
  8.  
  9.     for item in result: 
  10.         # 用户id 
  11.         id = item[0] 
  12.         # 发言次数 
  13.         count = item[1] 
  14.  
  15.         # 获取用户的昵称,即:微信昵称 
  16.         username = self.get_username(id) 
  17.  
  18.         self.top_data.append({ 
  19.             'username': username, 
  20.             'count'count 
  21.             }) 

最后,去除微信昵称的特殊符号,使用 pyecharts 将数据可视化。

 

  1. def draw_image(self): 
  2.     ""
  3.     数据可视化 
  4.     :return
  5.     ""
  6.     usernames = [] 
  7.     counts = [] 
  8.     for user in self.top_data: 
  9.          # 去除昵称中的特殊符号 
  10.          usernames.append(get_ava_string(user.get('username').strip())[0:8]) 
  11.          counts.append(user.get('count')) 
  12.  
  13.     def bar_chart() -> Bar: 
  14.             c = ( 
  15.                 Bar() 
  16.                     .add_xaxis(usernames) 
  17.                     .add_yaxis("活跃度", counts) 
  18.                     .reversal_axis() 
  19.                     .set_series_opts(label_opts=opts.LabelOpts(position="right")) 
  20.                     .set_global_opts(title_opts=opts.TitleOpts(title="最活跃的%d个小伙伴" % self.top_num)) 
  21.             ) 
  22.             return c 
  23.  
  24.     # 需要安装 snapshot-selenium 或者 snapshot-phantomjs 
  25.     make_snapshot(driver, bar_chart().render(), "bar.png"

3. 最后

上面的操作,通过生成的词云了解到当前群聊过去一段时间都在聊的话题及价值,通过对聊天记录的数据分析,获取到微信群聊活跃度排名。

 

 

 

 

当然,也可以分析群成员潜水排名及某一位群成员的数据分析。

责任编辑:华轩 来源: AirPython
相关推荐

2018-03-06 10:46:42

代码Python买水果

2016-01-21 17:49:52

云之家Agora语音会议

2018-03-09 10:09:07

程序媛体验女生

2024-08-08 08:00:00

2017-03-06 14:45:28

戴尔

2018-04-13 17:37:13

SAP上云

2021-02-23 15:18:27

程序员国企工程师

2018-02-26 09:28:42

程序员Bug体验

2021-11-04 17:48:44

编程游戏代码

2017-10-15 10:39:06

2015-11-20 10:37:36

KeystoneOpenStackDocker

2018-06-06 17:17:45

GitHub工程师代码

2018-12-29 10:37:05

HTTP缓存URL

2016-12-30 15:47:39

云计算发展CTO

2017-12-21 14:51:41

程序员转行30岁

2015-11-23 10:02:16

产品设计体验

2021-05-06 16:15:12

Java代码

2015-06-11 11:43:56

NoSQLBI商务智能

2017-10-30 14:54:50

2017-10-12 09:09:24

开发者故事
点赞
收藏

51CTO技术栈公众号