手把手教你生成你的独家微信聊天年度报告

news/2024/11/24 9:46:57/

大家好,我是机灵鹤。

今天是跟女朋友在一起 10 个月的纪念日,作为一名会 Python 的程序员,我决定将和女朋友的聊天记录导出来,生成一份专属于我们的《2021 恋爱年度报告》。

图片

感兴趣的朋友也可以学起来。

废话不多说,直接进入正题。

0. 导出聊天记录

由于破解微信聊天数据库的操作相对比较敏感,感兴趣的朋友可以移步《微信聊天记录导出教程》。

经过一系列操作,我从微信数据库中导出了跟女朋友的聊天记录。

聊天记录数据表 message.csv 格式如下。

其中,我们只需要关注以下几列即可。

  • type :消息类型,如 1 表示文字,3 表示图片,47 表示表情包
  • status :消息状态,2 表示发送的消息,4 表示接收的消息
  • createTime :发送时间,毫秒级时间戳
  • content :消息内容
  • imgPath :图片路径,如果是图片消息,则显示图片的 md5 值
  • talkerId :聊天对象的 ID

1. 聊天记录分析

本节中,我会使用 Python 对聊天记录文件进行数据分析,生成数据报告。

首先导入用到的模块,如果没有则需要安装。

# 用于读取和处理csv数据
import pandas as pd
# 用于处理日期,时间戳等数据
import time, datetime
# 用于生成直方图等图表
import matplotlib.pyplot as plt
# 用于对聊天内容进行分词处理
import jieba
# 用于生成词云图
from wordcloud import WordCloud,STOPWORDS,ImageColorGenerator
# 用于统计数组中元素出现次数
from collections import Counter
# 用于正则表达式提取数据
import re

然后读取 message.csv 文件。

# 需要读取的数据列
cols = ["type", "status", "createTime", "content", "imgPath", "talkerId"]
# message.csv 文件所在路径
filename = "src/message.csv"
# 女朋友的talkerId
TalkerID = 162
# 读取文件
data = pd.read_csv(filename, usecols=cols)

1.1 聊天消息概况统计

表中 type 列的值与消息类型对应情况,如下:

type对应的消息类型
1文字
2图片
3定位
34语音
43视频
47表情包
49分享链接
10000撤回消息
822083633引用回复
922746929拍一拍
419430449转账红包
486539313公众号分享
754974769视频号分享
1040187441音乐分享
1090519089传文件

注:以上是我通过比对微信聊天记录,大概推测所得,仅供参考,不一定对。

通过以下代码,可以统计得到聊天消息概况。

# 聊天消息总数
chatNum = 0
# 自己发送的消息
sendNum = 0
# 女朋友发送的消息
recvNum = 0
# 自己发送的消息总字数
hhMsgLen = 0
# 女朋友发送的消息总字数
yyMsgLen = 0
# 自己发送的最长消息的字数
hhMaxLen = 0
# 女朋友发送的最长消息的字数
yyMaxLen = 0
# 自己发送的长消息数(字数大于50)
hhLongMsg = 0
# 女朋友发送的长消息数(字数大于50)
yyLongMsg = 0# 文字消息数
textNum = 0
# 图片消息数
imageNum = 0
# 语音消息数
audioNum = 0
# 视频消息数
videoNum = 0
# 表情包数
emojiNum = 0
# 其他未分类消息
other = 0
# 分享消息数
shareNum = 0
# 发送文件数
fileNum = 0
# 引用回复数
replyNum = 0
# 转账红包数
moneyNum = 0
# 定位消息数
locaNum = 0
# 拍一拍数
pypNum = 0
# 撤回消息数
retrNum = 0# 统计消息条数
for index, msgType, status, createTime, content, imgPath, talkerId  in data.itertuples():# 限定聊天对象是女朋友if talkerId == TalkerID:chatNum += 1if status == 2:sendNum += 1elif status == 4:recvNum +=1if msgType == 1:textNum += 1if status == 2:hhMsgLen += len(content)hhMaxLen = max(hhMaxLen, len(content))if len(content) >= 50:hhLongMsg += 1elif status == 4:yyMsgLen += len(content)yyMaxLen = max(yyMaxLen, len(content))if len(content) >= 50:yyLongMsg += 1elif msgType == 3:imageNum += 1elif msgType == 34:audioNum += 1elif msgType == 43:videoNum += 1elif msgType == 47:emojiNum += 1# 链接分享,公众号分享,视频号分享,音乐分享等统一计入分享消息数elif msgType == 49 or msgType == 486539313 or msgType == 754974769 or msgType == 1040187441:shareNum += 1elif msgType == 822083633:replyNum += 1elif msgType == 1090519089:fileNum += 1elif msgType == 419430449 or msgType == 436207665:moneyNum += 1elif msgType == 10000:retrNum += 1elif msgType == 922746929:pypNum += 1elif msgType == 48 or msgType == -1879048186:locaNum += 1else:other += 1# 打印统计结果
print("聊天记录概况统计\n")
print("消息总条数:", chatNum)
print("---"*10)
print("鹤鹤发的消息数:", sendNum)
print("颖颖发的消息数:", recvNum)
print("鹤鹤发送的总字数:", hhMsgLen)
print("颖颖发送的总字数:", yyMsgLen)
print("鹤鹤发送的长消息数:", hhLongMsg, ",最长消息", hhMaxLen, "字")
print("颖颖发送的长消息数:", yyLongMsg, ",最长消息", yyMaxLen, "字")
print("---"*10)
print("文字:", textNum)
print("表情包:", emojiNum)
print("图片:", imageNum)
print("语音:", audioNum)
print("视频:", videoNum)
print("---"*10)
print("链接分享:", shareNum)
print("引用回复:", replyNum)
print("发送文件:", fileNum)
print("红包转账:", moneyNum)
print("撤回消息:", retrNum)
print("拍一拍:", pypNum)
print("发送定位:", locaNum)
print("---"*10)
print("未分类:", other)

运行结果

聊天记录概况统计消息总条数: 107456
------------------------------
鹤鹤发的消息数: 51753
颖颖发的消息数: 55692
鹤鹤发送的总字数: 459031
颖颖发送的总字数: 450474
鹤鹤发送的长消息数: 220 ,最长消息 459 字
颖颖发送的长消息数: 64 ,最长消息 254 字
------------------------------
文字: 93334
表情包: 9227
图片: 2452
语音: 186
视频: 212
------------------------------
链接分享: 102
引用回复: 1541
发送文件: 20
红包转账: 30
撤回消息: 227
拍一拍: 102
发送定位: 9
------------------------------
未分类: 14

1.2 聊天时间段分析

根据数据表中的 createTime 字段,可以获取到消息发送的时间,进而可以进行聊天时间段分析。

1.2.1 每天聊天消息数

# 定义字典,键为日期,值为该天聊天消息数
dayMsgDict = {}# 统计每天的聊天消息数
for index, msgType, status, createTime, content, imgPath, talkerId  in data.itertuples():if talkerId == TalkerID:timeArray = time.localtime(createTime/1000)date = time.strftime('%Y-%m-%d', timeArray)if dayMsgDict.get(date):dayMsgDict[date] += 1else:dayMsgDict.setdefault(date, 1)# 绘制直方图可视化展示
plt.figure(figsize=(15, 10))
plt.bar(range(len(dayMsgDict.keys())), dayMsgDict.values())
plt.show()

运行结果

1.2.2 每月的聊天消息数

# 定义数组,从2020年10月起,至2022年1月,共 16 个月
monMsgArray = [0] * 16# 统计每月的聊天消息数
for index, msgType, status, createTime, content, imgPath, talkerId  in data.itertuples():if talkerId == TalkerID:timeArray = time.localtime(createTime/1000)if timeArray.tm_year == 2020:monMsgArray[timeArray.tm_mon - 10] += 1elif timeArray.tm_year == 2021:monMsgArray[timeArray.tm_mon + 2] += 1if timeArray.tm_year == 2022:monMsgArray[-1] += 1# 绘制直方图可视化展示
plt.figure(figsize=(15, 10))
month_Label = ["20-Oct", "20-Nov", "20-Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "22-Jan"]
plt.bar(range(len(monMsgArray)), monMsgArray, tick_label=month_Label)
plt.show()

运行结果

1.2.3 一周的聊天消息数

# 定义数组,从周一到周日,每天的聊天消息数
weekMsgArray = [0] * 7# 统计从周一到周日,每天的聊天消息数
for index, msgType, status, createTime, content, imgPath, talkerId  in data.itertuples():if talkerId == TalkerID:weekday = datetime.datetime.fromtimestamp(createTime/1000).weekday()weekMsgArray[weekday] += 1# 绘制直方图可视化展示
plt.figure(figsize=(15, 10))
weekday_Label = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
plt.bar(range(len(weekMsgArray)), weekMsgArray, tick_label=weekday_Label)
plt.show()

运行结果

1.2.4 一天的聊天消息数

# 定义数组,一天24小时
hourMsgArray = [0] * 24# 统计一天24小时的聊天消息数
for index, msgType, status, createTime, content, imgPath, talkerId  in data.itertuples():if talkerId == TalkerID:timeArray = time.localtime(createTime/1000)hourMsgArray[timeArray.tm_hour] += 1# 绘制直方图可视化展示
plt.figure(figsize=(15, 10))
hour_Label = [str(i) for i in range(0, 24)]
plt.bar(range(len(hourMsgArray)), hourMsgArray, tick_label=hour_Label)
plt.show()

运行结果

1.2.5 一些特别的日子

聊天最多的一天

# 聊天最多的一天,以及这天的聊天消息数
maxDay = 0
maxVal = 0for key in dayMsgDict:if maxVal < dayMsgDict[key]:maxDay = keymaxVal = dayMsgDict[key]# 打印统计结果
print(maxDay, "这一天,你们无话不谈,聊了", maxVal, "句")

运行结果

2021-03-28 这一天,你们无话不谈,聊了 909 句

聊天最晚的一天

这里我以凌晨 5 点作为分界点,5 点之前属于晚睡,5 点之后属于早起。

# 聊天最晚的一天
latestDay = None# 统计聊天最晚的一天
for index, msgType, status, createTime, content, imgPath, talkerId  in data.itertuples():if talkerId == TalkerID:timeArray = time.localtime(createTime/1000)if timeArray.tm_hour < 5:if latestDay == None:latestDay = timeArraycontinuets1 = timeArray.tm_hour * 3600 + timeArray.tm_min * 60 + timeArray.tm_sects2 = latestDay.tm_hour * 3600 + latestDay.tm_min * 60 + latestDay.tm_secif ts1 > ts2:latestDay = timeArray#打印统计结果
Date = time.strftime('%Y-%m-%d', latestDay)
Time = time.strftime('%H点%M分', latestDay)
print(Date, "这一天,你们睡得很晚,凌晨",Time, "仍在聊天")

运行结果

2021-05-30 这一天,你们睡得很晚,凌晨 04点40分 仍在聊天

起床最早的一天

# 聊天最早的一天
earliestDay = None# 统计聊天最早的一天
for index, msgType, status, createTime, content, imgPath, talkerId  in data.itertuples():if talkerId == TalkerID:timeArray = time.localtime(createTime/1000)if timeArray.tm_hour >= 5:if earliestDay == None:earliestDay = timeArraycontinuets1 = timeArray.tm_hour * 3600 + timeArray.tm_min * 60 + timeArray.tm_sects2 = earliestDay.tm_hour * 3600 + earliestDay.tm_min * 60 + earliestDay.tm_secif ts1 < ts2:earliestDay = timeArray#打印统计结果
Date = time.strftime('%Y-%m-%d', earliestDay)
Time = time.strftime('%H点%M分', earliestDay)
print(Date, "这一天,你们醒得很早,早上",Time, "便已开启新的一天")

运行结果

2021-07-11 这一天,你们醒得很早,早上 05点26分 便已开启新的一天

1.3 聊天内容分析

1.3.1 最常说的词语

# 文字消息字符串
msgContent = ""# 开始统计
for index, msgType, status, createTime, content, imgPath, talkerId  in data.itertuples():if talkerId == TalkerID and msgType == 1:msgContent += content# 剔除 Emoji 表情
pattern = re.compile(r"\[.+?\]")
msgContent = pattern.sub(r"", msgContent)# jieba 分词
msg_all_split = jieba.cut(str(msgContent), cut_all=False)
# 剔除单字
all_ls = [word for word in msg_all_split if len(word)>1]
all_words = ' '.join(all_ls)# 设置停用词
stopwords = STOPWORDS.copy()
stopwords.add('这个')
stopwords.add('就是')
stopwords.add('什么')
stopwords.add('然后')
stopwords.add('可以')
stopwords.add('没有')
stopwords.add('一个')
stopwords.add('不是')
stopwords.add('感觉')
stopwords.add('时候')
stopwords.add('觉得')# 生成词云图
wc = WordCloud(width=1960, height=1080, background_color='white', font_path='STKAITI.TTF', stopwords=stopwords, max_font_size=400, random_state=50, collocations=False)
wc.generate_from_text(all_words)# 词云图显示
plt.figure(figsize=(15, 10))
plt.imshow(wc)
plt.axis('off')
plt.show()

运行结果

我最常说的词语

# 我发送的文字消息
hhMsgContent = ""# 开始统计
for index, msgType, status, createTime, content, imgPath, talkerId  in data.itertuples():if talkerId == TalkerID and msgType == 1:if status == 2:hhMsgContent += content# 剔除 Emoji 表情
pattern = re.compile(r"\[.+?\]")
msgContent = pattern.sub(r"", hhMsgContent)# jieba 分词
msg_all_split = jieba.cut(str(msgContent), cut_all=False)
# 剔除单字
all_ls = [word for word in msg_all_split if len(word)>1]
all_words = ' '.join(all_ls)# 设置停用词
stopwords = STOPWORDS.copy()# 生成词云图
wc = WordCloud(width=1960, height=1080, background_color='white', font_path='STKAITI.TTF', stopwords=stopwords, max_font_size=400, random_state=50, collocations=False)
wc.generate_from_text(all_words)# 词云图显示
plt.figure(figsize=(15, 10))
plt.imshow(wc)
plt.axis('off')
plt.show()

运行结果:

image-20220118135316487

女朋友最常说的词语

# 女朋友发送的文字消息
yyMsgContent = ""# 开始统计
for index, msgType, status, createTime, content, imgPath, talkerId  in data.itertuples():if talkerId == TalkerID and msgType == 1:if status == 4:yyMsgContent += content# 剔除 Emoji 表情
pattern = re.compile(r"\[.+?\]")
msgContent = pattern.sub(r"", yyMsgContent)# jieba 分词
msg_all_split = jieba.cut(str(msgContent), cut_all=False)
# 剔除单字
all_ls = [word for word in msg_all_split if len(word)>1]
all_words = ' '.join(all_ls)# 设置停用词
stopwords = STOPWORDS.copy()# 生成词云图
wc = WordCloud(width=1960, height=1080, background_color='white', font_path='STKAITI.TTF', stopwords=stopwords, max_font_size=400, random_state=50, collocations=False)
wc.generate_from_text(all_words)# 词云图显示
plt.figure(figsize=(15, 10))
plt.imshow(wc)
plt.axis('off')
plt.show()

运行结果

1.3.2 最常用的Emoji表情

# 正则表达式,提取聊天文字中的emoji表情
pattern = re.compile(r"\[.+?\]")# hhMsgContent 为前面统计好的我发的文字消息
hhEmoji = re.findall(pattern, hhMsgContent)
# yyMsgContent 为前面统计好的女朋友发的文字消息
yyEmoji = re.findall(pattern, yyMsgContent)# 按照出现次数统计
hh = Counter(hhEmoji)
yy = Counter(yyEmoji)# 打印统计结果
print("鹤鹤发的表情数:", len(hhEmoji))
print("颖颖发的表情数:", len(yyEmoji))
print("---"*10)
print ("鹤鹤最常用的 10 个表情:\n", hh.most_common(10))
print("---"*10)
print ("颖颖最常用的 10 个表情:\n", yy.most_common(10))

运行结果

鹤鹤发的表情数: 15768
颖颖发的表情数: 21531
------------------------------
鹤鹤最常用的 10 个表情:[('[破涕为笑]', 5083), ('[捂脸]', 4792), ('[偷笑]', 1829), ('[让我看看]', 1361), ('[奸笑]', 373), ('[发呆]', 318), ('[嘿哈]', 268), ('[皱眉]', 223), ('[苦涩]', 208), ('[憨笑]', 122)]
------------------------------
颖颖最常用的 10 个表情:[('[破涕为笑]', 9462), ('[让我看看]', 5413), ('[捂脸]', 2459), ('[苦涩]', 2062), ('[旺柴]', 944), ('[偷笑]', 231), ('[白眼]', 154), ('[发呆]', 64), ('[奸笑]', 60), ('[666]', 55)]

这样看可能看不出来,复制到微信里,就会显示对应的表情了。

1.3.3 最常发的表情包图片

# 我发送的表情包列表
hhImgList = []
# 女朋友发送的表情包列表
yyImgList = []# 统计数据
for index, msgType, status, createTime, content, imgPath, talkerId  in data.itertuples():if talkerId == TalkerID and msgType == 47:if status == 2:hhImgList.append(imgPath)elif status == 4:yyImgList.append(imgPath)# 统计每个表情包出现次数
hhImg = Counter(hhImgList)
yyImg = Counter(yyImgList)# 打印统计结果
print("鹤鹤共发送了", len(hhImgList), "个表情包")
print("颖颖共发送了", len(yyImgList), "个表情包")
print("---"*10)
print ("鹤鹤表情包前十名:\n", hhImg.most_common(10))
print("---"*10)
print ("颖颖表情包前十名:\n",yyImg.most_common(10))

运行结果

鹤鹤共发送了 4203 个表情包
颖颖共发送了 5024 个表情包
------------------------------
鹤鹤表情包前十名:[('6b5a13890545c9675e6029fbee395560', 319), ('d9f537281429695f9c299049814e3e33', 164), ('8fb0ddeea33701832c86167a141452df', 114), ('25b8abcd5318ded9ade61a6ec1287a95', 91), ('7f69ba3a4ed01d1c16c3b6576c45d24e', 90), ('4ce13465607eb3243d6e80e7a95b838f', 81), ('a9d5dbb4c0fba9a1af0ec2e6e064977b', 80), ('ce58baf1002411bdafd299a689cadfe4', 76), ('c1ed2b89e38cfded0461bc95db1ab522', 75), ('d16c0b43b9ee901d92f9542b1033234a', 70)]
------------------------------
颖颖表情包前十名:[('a9d5dbb4c0fba9a1af0ec2e6e064977b', 712), ('477e31cf6e2a747c96e1248a02605756', 352), ('e976c1e3f56a32db3c2f49de72daa616', 215), ('4d21237942192184a4c8a57ab34fb2fa', 183), ('125d7792a060cece7edef87d71b40837', 168), ('4ce13465607eb3243d6e80e7a95b838f', 151), ('7c04a4df048874f088dc8832c45e3fb6', 146), ('b2f427b22d1e581923837acd7165e882', 137), ('6b5a13890545c9675e6029fbee395560', 137), ('b83d0a5929cdf92aeb05eefaf3612bea', 92)]

:统计得到的 imgPath 值为表情包图片的 MD5 值,对应的表情包可以通过发送时间 createTime,在微信聊天记录中对照着找到。

2. 年度报告

将上面统计好的数据稍加整理,便得到了与女朋友微信聊天的《年度报告》。

image-20220118195253274

鹤鹤年度表情包前十名

颖颖年度表情包前十名

鹤鹤年度聊天词云

图片

颖颖年度聊天词云

图片


欢迎关注公众号【机灵鹤】

我是机灵鹤,一个代码写的不错,还有点小浪漫的程序员。


http://www.ppmy.cn/news/495257.html

相关文章

微信聊天记录同步电脑

相信很多人&#xff0c;遇到过“明明在一个路由器下&#xff0c;却不能同步的情况。” 下面是一个超级简单的解决方案&#xff0c;是我不小心发现的。 &#xff08;WIN10 自带&#xff09; &#xff08;别的系统&#xff0c;试试360随身WiFi&#xff0c;猎豹WiFi——百度一下…

Chat聊天记录聊天记录导出

ChatGPT大家应该都玩过吧&#xff0c;今天我给大家提供一个将聊天记录导出的教学。 第一步&#xff1a;将聊天的页面保存到本地 打开聊天记录界面&#xff0c;调出控制台&#xff08;F12或FnF12&#xff09;点击查看器选项卡右键html标记&#xff0c;选择编辑为html(如下图)全…

【微信篇】PC端微信文件夹里的“微信号“

【微信篇】PC端微信文件夹里的"微信号" 更新记录最敷衍的软件一微信&#xff01;&#xff01;&#xff01;—【蘇小沐】 文章目录 【微信篇】PC端微信文件夹里的"微信号"1.实验环境 PC端微信文件夹里的"微信号"总结 1.实验环境 系统版本Window…

Hadoop综合案例 - 聊天软件数据

目录 1、聊天软件数据分析案例需求2、基于Hive数仓实现需求开发2.1 建库2.2 建表2.3 加载数据2.4 ETL数据清洗2.5 需求指标统计---都很简单 3、FineBI实现可视化报表3.1 FineBI介绍3.2 FineBI配置数据3.3 构建可视化报表 1、聊天软件数据分析案例需求 MR速度慢—引入hive 背景…

手机不用root,一台电脑教你导出微信聊天记录

目录 导语 工具 原理 步骤 步骤截图 首先登录电脑微信&#xff0c;备份聊天记录到电脑上 电脑下载安卓模拟器&#xff08;鄙人用的是夜神&#xff09; 安卓模拟器下载并安装微信 模拟器登录微信 获取微信的uin号 获取手机IMEI码 将IMEI(MEID)uin进行MD5&#xff0c…

导出 Mac 版微信聊天记录

macOS 微信的“备份与恢复”功能只能从手机微信导出到 Mac, 但是微信其实又在本地存了加密的 sqlite3 数据库&#xff1b; 本地数据库的是一系列 *.db 文件&#xff0c;可以用如下命令查看&#xff0c; ls -alh ~/Library/Containers/com.tencent.xinWeChat/Data/Library/Appl…

【微信篇】电脑版微信的照片视频文件位置变化

【微信篇】电脑版微信的照片视频文件位置变化 新版的微信视频图片更新了位置&#xff0c;感觉有好有坏吧&#xff0c;好的方面就是以后查找视频、图片、文档等可能更方便&#xff1b;不好就是越更新占用体积越大&#xff0c;还多很多数据&#xff0c;不懂是否流氓&#xff1f;…

如何导出某人微信聊天记录到电脑

微信导出聊天记录 禁止转载,如若转载请标明出处 想送ta一份一路走过来的的点点滴滴? 想表白时作为一份告白礼物? 想分手时,作为最后的告别? 亦或是想,老迈闲暇时,回顾年轻时候的风风雨雨? 。。。 本篇文章,教你一招,助你实现:导出微信聊天记录至电脑; 全程无需使用…