2025年4月9日 星期三 乙巳(蛇)年 正月初十 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Python

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

时间:10-12来源:作者:点击数:41

1. 场景

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

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

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

2. 实现步骤

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

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

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

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

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

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

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

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

图片

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

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

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

图片

第 3 步,破解数据库

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

  • # 安装sqlcipher命令行(Mac)
  • brew install sqlcipher
  • # Win可以去下载sqlcipher命令行文件

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

图片

第 4 步,分析数据库

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

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

图片

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

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

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

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

  • import sqlite3
  • def __init__(self, db_path="./weixin.db"):
  •     """
  •     本地数据库初始化
  •     """
  •     self.db = sqlite3.connect(db_path)
  •     self.cursor = self.db.cursor()

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

  • def execute(self, sql, param=None):
  •     """
  •     sql: Sql语句,包含:增、删、改
  •     param:数据,可以为列表、字典,也可以为空
  •     """
  •     try:
  •         if param is None:
  •             self.cursor.execute(sql)
  •         else:
  •             if type(param) is list:
  •                 self.cursor.executemany(sql, param)
  •             else:
  •                 self.cursor.execute(sql, param)
  •             count = self.db.total_changes
  •             self.db.commit()
  •     except Exception as e:
  •         print(e)
  •         return False, e
  •     # 返回结果
  •     return True if count > 0 else False
  • def query(self, sql, param=None):
  •     """
  •     查询语句
  •     sql:Sql语句
  •     param:参数,可以包含空
  •     retutn:成功返回True
  •     """
  •     if param is None:
  •         self.cursor.execute(sql)
  •     else:
  •         self.cursor.execute(sql, param)
  •     # 返回查询的结果
  •     return self.cursor.fetchall()

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

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

  • def __get_chartroom_id(self):
  •     """
  •     获取群聊的id
  •     :return:
  •     """
  •     res = self.db.query('select username from rcontact where nickname=?;', (self.chatroom_name,))
  •     # 群聊id
  •     chatroom_id = res[0][0]
  •     return chatroom_id

第 7 步,获取群聊消息

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

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

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

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

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

图片

第 8步,生成词云

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

  • def generate_wordcloud(self, word):
  •     """
  •     生成词云
  •     :param word:
  •     :return:
  •     """
  •     img = WordCloud(font_path="./DroidSansFallbackFull.ttf", width=2000, height=2000,
  •                         margin=2, collocations=False).generate(word)
  •     plt.imshow(img)
  •     plt.axis("off")
  •     plt.show()
  •     # 保存图片
  •     img.to_file("{}.png".format("群聊"))
  • # 分词
  • temp = " ".join(jieba.cut(words, cut_all=True))
  • # 生成词云
  • generate_wordcloud(temp)

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

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

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

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

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

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

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

  • def get_top_partner(self):
  •     """
  •     排名前15的成员
  •     :return:
  •     """
  •     sql = "SELECT name as 姓名,COUNT(*) as times FROM top GROUP BY name ORDER BY times DESC limit %d;" % self.top_num
  •     result = self.db.query(sql)
  •     for item in result:
  •         # 用户id
  •         id = item[0]
  •         # 发言次数
  •         count = item[1]
  •         # 获取用户的昵称,即:微信昵称
  •         username = self.get_username(id)
  •         self.top_data.append({
  •             'username': username,
  •             'count': count
  •             })

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

  • def draw_image(self):
  •     """
  •     数据可视化
  •     :return:
  •     """
  •     usernames = []
  •     counts = []
  •     for user in self.top_data:
  •          # 去除昵称中的特殊符号
  •          usernames.append(get_ava_string(user.get('username').strip())[0:8])
  •          counts.append(user.get('count'))
  •     def bar_chart() -> Bar:
  •             c = (
  •                 Bar()
  •                     .add_xaxis(usernames)
  •                     .add_yaxis("活跃度", counts)
  •                     .reversal_axis()
  •                     .set_series_opts(label_opts=opts.LabelOpts(position="right"))
  •                     .set_global_opts(title_opts=opts.TitleOpts(title="最活跃的%d个小伙伴" % self.top_num))
  •             )
  •             return c
  •     # 需要安装 snapshot-selenium 或者 snapshot-phantomjs
  •     make_snapshot(driver, bar_chart().render(), "bar.png")

3. 最后

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

图片

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

已经将全部源码上传:https://github.com/xingag/spider_python/tree/master/%E5%BE%AE%E4%BF%A1%E8%81%8A%E5%A4%A9%E8%AE%B0%E5%BD%95。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐