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

image

1. 场景

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

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

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

2. 实现步骤

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

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

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

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

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

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

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

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

image

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

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

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

image

第 3 步,破解数据库

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

# 安装sqlcipher命令行(Mac)
brew install sqlcipher

# Win可以去下载sqlcipher命令行文件

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

image

第 4 步,分析数据库

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

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

image

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

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

image

第 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. 最后

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

image

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

我已经将全部源码上传到后台,关注公众号「 AirPython 」后回复「 微信群聊 」即可获得全部源码。

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

推荐阅读

我花 1 分钟写了一段爬虫,帮助小姐姐解放了双手

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

为了追到小姐姐,我用 Python 制作了一个机器人

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容