概要
起初在看到社交平台上有关于微信聊天记录可视化的分享,想想自己作为计算机的“未来人才”,应该实现起来不会太难,下面是实现过程和经验分享。(有错千万提出!!)
整体实现流程
针对可视化微信聊天记录的实现,主要会遇到的问题还是关于“聊天记录”的导出,因为微信本身是不提供聊天记录导出功能的。我起初认为,聊天记录只是简单存储在电脑或者手机的固定文件夹下,事实上,聊天记录是有进行加密在数据库中的(好像是这样)。
这个我在自己实践的过程中,在网上有很多相关的教程,大多都是使用电脑上的手机模拟器(模拟器自带的root功能)来破解聊天记录,但我总感觉有点麻烦,最后在GitHub上找到开源项目,它可以帮助我们直接进行提取电脑上的微信聊天记录(聊天记录在手机上的同学,可以先备份到电脑上,这里就不赘述了),导出成csv等文件。
再简单介绍一下这个开源项目,它是提供了简单的可视化,但我这里是只使用到了它的导出聊天记录的部分。其中嫌麻烦的话可以使用这个项目中所提供的下载打包好的exe可执行文件。具体使用就各位自行移步到下面地址。
微信聊天记录提取开源项目地址:
https://github.com/LC044/WeChatMsg.git
在对微信聊天记录进行导出文件后,我这边选择导出的文件格式是csv文件,使用python是实现可视化,python中的可视化工具还是十分便利的。
使用到的工具及技术
- python3.10.9 作为编程语言,可视化便捷
- PyCharm 开发工具
- Github 软件托管平台
具体实现
一、 数据预处理:如下图所示,导出来的聊天记录csv文件大致有这么几个列,其中需要关注的是"Type","IsSender","StrContent","StrTime"这几列,所以在数据预处理部分就可以简单考虑这些。
"Type":聊天内容类型。
"IsSender":标识消息是自己发送还是对方,1表示自己,0表示对方。
"StrContent":聊天内容。
"StrTime":聊天时间。
二、读取文件,这边保留了文本内容(即Type=1),并且过滤数据,只留下 'IsSender','StrContent','StrTime'列。
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import norm
import numpy as np
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为黑体
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 读取CSV文件
df = pd.read_csv('C:/Users/86187/Desktop/MemoTrace/data/聊天记录/小蛋!/小蛋!_utf8.csv')
# TODO 数据预处理(根据需求进行)
# 只保留文本聊天
df = df[df['Type'] == 1]
# 只取'IsSender','StrContent','StrTime'列
selected_columns = ['IsSender', 'StrContent', 'StrTime'] # 将要保留的列名放入一个列表中
df = df[selected_columns]
三、根据聊天时间,进行每天聊天频率的可视化,x轴为日期,y轴为聊天数。首先将'StrTime'列转换成日期时间格式,因为我们是对每天进行统计,所以只保留日期部分。最后以柱状图呈现。
# TODO 每天聊天频率柱状图
# 将StrTime列的数据转换为日期时间格式
df['StrTime'] = pd.to_datetime(df['StrTime'])
# 创建一个新的Date列,只保留日期部分
df['Date'] = df['StrTime'].dt.date
# 根据每一天统计聊天频率
chat_frequency = df['Date'].value_counts().sort_index()
# 生成柱状图
chat_frequency.plot(kind='bar',color='#DF9F9B')
plt.xlabel('Date')
plt.ylabel('Frequency')
plt.title('Chat Frequency by Day')
# 调整刻度标签,只保留月份和日期
date_labels = [date.strftime('%m-%d') for date in chat_frequency.index] # 格式化日期
plt.xticks(range(len(date_labels)), date_labels) # 设置新的刻度标签
plt.xticks(fontsize=5)
plt.show()
四、接下来根据聊天内容进行词频统计,进行Top20的可视化,采用水平直方图展示。
# TODO 双方词频统计
# 双方发送的聊天信息
sent_by_me = df[df['IsSender'] == 1]['StrContent']
sent_by_others = df[df['IsSender'] == 0]['StrContent']
# 统计词频
words_sent_by_me = ' '.join(sent_by_me).lower().split()
words_sent_by_others = ' '.join(sent_by_others).lower().split()
word_freq_sent_by_me = pd.Series(words_sent_by_me).value_counts()
word_freq_sent_by_others = pd.Series(words_sent_by_others).value_counts()
# 可视化
plt.figure(figsize=(10, 6))
# 我发送的聊天信息词频
plt.subplot(121)
word_freq_sent_by_me[:20].plot(kind='barh',color='#009688')
plt.title('Word Frequency (Sent by 蛋总)')
plt.xlabel('Frequency')
# 对方发送的聊天信息词频
plt.subplot(122)
word_freq_sent_by_others[:20].plot(kind='barh',color='#6A0404')
plt.title('Word Frequency (Sent by 小蛋)')
plt.xlabel('Frequency')
plt.tight_layout()
plt.show()
五、用饼状图可视化双方信息发送量的对比。
# TODO 双方信息数量对比
# 统计数量
count_sent_by_me = len(sent_by_me)
count_sent_by_others = len(sent_by_others)
# 创建饼状图
labels = ['蛋总', '小蛋']
sizes = [count_sent_by_me, count_sent_by_others]
colors = ['#264F61', '#9523AA']
explode=(0,0.05)
plt.pie(sizes, explode=explode, labels=labels, colors=colors, autopct='%1.1f%%', shadow=True, startangle=90)
plt.axis('equal')
plt.title('Comparison of the number of chats')
# 添加图例
plt.legend()
# 显示图表
plt.show()
六、根据一天中的每一个小时进行统计聊天频率,并绘制柱状图,并添加曲线变化。可以直观的看到一天中聊天频率最高的时间段。需要将时间字符串转换为时间类型并提取小时。
# TODO 根据一天中的每一个小时进行统计聊天频率,并生成柱状图
# 将时间字符串转换为时间类型并提取小时
df['DateTime'] = pd.to_datetime(df['StrTime'])
df['Hour'] = df['DateTime'].dt.hour
# 统计每个小时的聊天频率
hourly_counts = df['Hour'].value_counts().sort_index().reset_index()
hourly_counts.columns = ['Hour', 'Frequency']
# 绘制柱状图和数据拟合曲线
plt.figure(figsize=(10, 6))
ax = sns.barplot(x='Hour', y='Frequency', data=hourly_counts, color="#E6AAAA" )
# 添加核密度估计曲线
sns.kdeplot(df['Hour'], color='#C64F4F', linewidth=1, ax=ax.twinx())
# 设置图形标题和轴标签
plt.title('Chat Frequency by Hour')
plt.xlabel('Hour of the Day')
plt.ylabel('Frequency')
# 显示图形
plt.show()
七、可视化效果
小结
以上是对聊天记录可视化的简单实现,在可视化部分总体难度不大,没有上升到进行数据分析,后面可以会对此进行进一步的优化与改进,期待后续。感谢阅读,希望有所收获。