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的值,也就是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这三个表。
微信的所有文字聊天记录都存储在消息数据表中,包括:聊天内容、发件人、消息类型、创建时间等。
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表:聊天记录表
# 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 步,新建排名表,插入数据
为了统计群聊活跃度排名,我们需要新建一张表,包含3个字段:id、微信昵称、消息内容。
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和发送内容这两个字段插入到新建的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. 最后
以上操作,通过生成的词云,了解过去一段时间内当前群聊的话题和价值,通过聊天记录的数据分析得到微信群聊的活跃度排名。
本文为原创文章,版权归知行编程网所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Python3 枚举类比较的局限性是什么?12/22
- ♥ 如何解决python导出excel乱码10/29
- ♥ 如何传递python函数的参数?12/06
- ♥ Python单向循环链表的创建01/06
- ♥ 如何在python中打开带有乱码的中文文件名10/22
- ♥ python如何启动idle09/22
内容反馈