微信聊天记录提取及分析(wordcloud+pyecharts)
0. 前言
之所以想要提取微信的聊天记录并分析是因为也开始再学习python,但是单纯看看语法什么的又很无趣,无意间看到python可以进行微信聊天记录的分析,就自己尝试做了一下,感觉还是挺有意思的。
1.提取聊天记录数据库
我所用的是小米手机,所以提取聊天记录是主要是通过本地备份功能,其余手机也可参考下述博客,具体流程可参考:
微信聊天记录导出(2020新版)
安卓\电脑微信聊天记录导出表格
微信聊天记录数据提取并分析
利用python做微信聊天记录词云分析
提取微信数据库的主体流程都差不多,基本都是先进行备份,然后将备份文件复制到电脑进行解压,解压完成之后根据得到的数据库密码访问数据库。提取数据库的过程基本上都不会有什么问题,主要会出现的问题在于获取微信数据库密码。我开始使用的是手机IMEI + uin拼接取其32位MD5码前7位的方式,但是因为我手机上有两个IMEI码,尝试了各种组合获得的密码始终是错误的,所以就放弃采用这种方式,但是根据其他博客中的内容,这种方式也可以获取数据库密码。
我最终采用的是反序列化的方式获取数据库密码,即将微信com.tencent.mm\r\MicroMsg\systemInfo.cfg和com.tencent.mm\r\MicroMsg\CompatibleInfo.cfg这两个文件复制出来,通过参考代码获取数据库密码。开始直接在命令行通过javac编译并运行,如下所示
javac IMEI.java
java IMEI systemInfo.cfg CompatibleInfo.cfg
但是直接在命令行中运行会报 “错误: 找不到或无法加载主类 IMEI 原因: java.lang.ClassNotFoundException: IMEI”,但是将代码放在IDEA中可以运行并得到最终数据库密码,代码如下:
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.security.MessageDigest;
import java.util.HashMap;public class IMEI {public static void main(String[] args) {// systemInfo.cfg存储路径,修改为电脑中存储位置String systemInfo_path = "D:\\wechet-anayze\\systemInfo.cfg";// compatibleInfo.cfg存储路径,修改为电脑中存储位置String compatibleInfo_path1 = "D:\\wechet-anayze\\CompatibleInfo.cfg";try {ObjectInputStream in = new ObjectInputStream(new FileInputStream(path));Object DL = in.readObject();HashMap hashWithOutFormat = (HashMap) DL;ObjectInputStream in1 = new ObjectInputStream(new FileInputStream(path1));Object DJ = in1.readObject();HashMap hashWithOutFormat1 = (HashMap) DJ;String s = String.valueOf(hashWithOutFormat1.get(Integer.valueOf(258))); // 取手机的IMEIs = s + hashWithOutFormat.get(Integer.valueOf(1)); //合并到一个字符串s = encode(s); // hashSystem.out.println("The Key is : " + s.substring(0, 7));in.close();in1.close();} catch (Exception e) {e.printStackTrace();}}public static String encode(String content) {try {MessageDigest digest = MessageDigest.getInstance("MD5");digest.update(content.getBytes());return getEncode32(digest);} catch (Exception e) {e.printStackTrace();}return null;}private static String getEncode32(MessageDigest digest) {StringBuilder builder = new StringBuilder();for (byte b : digest.digest()) {builder.append(Integer.toHexString((b >> 4) & 0xf));builder.append(Integer.toHexString(b & 0xf));}return builder.toString();}
}
微信数据库及数据库密码获取完成之后就可以通过sqlcipher(官方下载地址)软件访问数据库中内容,查看具体的聊天信息等,我在后续处理中主要用到了message和contact表,message表中记录了所发送的所有消息信息,contact表中记录了所有的联系人信息,message表中主要使用到的内容如下:
message表主要内容
列名 | 内容 |
---|---|
msgId | 按所有消息时间顺序的唯一编号 |
type | 聊天内容类型 |
isSend | 标识消息是自己发送还是对方发送,1表示自己,0表示对方 |
createTime | 聊天时间 |
talker | 单聊的wxid或群聊编号"XXXX@chatroom" |
content | 聊天内容,单聊直接显示内容,群聊格式为“wxid:\n”内容 |
因为也挺想知道和其他人的聊天类型,所以就也根据message表中的type值结合createTime查找具体的聊天信息,从而对type类型做了如下分类,
type类型信息
type值 | 表示内容 |
---|---|
1 | 文本内容 |
2 | 位置信息 |
3 | 图片及视频 |
34 | 语音消息 |
42 | 名片(公众号名片) |
43 | 图片及视频 |
47 | 表情包 |
48 | 定位信息 |
49 | 小程序链接 |
10000 | 撤回消息提醒(XXXX撤回了一条消息) |
1048625 | 照片 |
16777265 | 链接 |
285212721 | 文件 |
419430449 | 微信转账 |
436207665 | 微信红包 |
469762097 | 微信红包 |
·11879048186 | 位置共享 |
… | (还有未知type信息,待补充) |
contact表主要内容
列名 | 含义 |
---|---|
username | 微信id,格式是"wxid_xxxxxxxx"或者一看就是自己设置的 |
alias | 自己设置的那个可以通过查找加好友的微信名(和上面那个有的有区别有的为空) |
conRemark | 联系人备注名 |
nickname | 微信名片上的名字,公众号的名字 |
contactLabelIds | 联系人标签号 |
2.数据预处理
2.1 message表和contact表获取
获取到微信数据库及数据库密码后,可通过sqlciper软件查看数据库中内容,同时也可将所需的数据导出,可通过file/Export/Table as CSV file选项,选择需要导出的数据表,将之存储为CSV文件。
这里需要注意一下:
如果在python中直接读取导出的csv文件夹,python中会报错,大致是因为编码错误。其余博客中有提到使用excel打开导出的csv文件,然后以utf-8格式另存,最后读取另存后的文件,通过试验这种方法可以进行读取,但是因为csv文件用excel打开时超过16位的数字将会被强制使用科学计数法表示,所以message表中的createTime会被使用科学计数法表示,另存后的文件中creatTime时间精度会损失,所以我最终采用了一个简单粗暴的方法:用记事本打开csv文件,然后以utf-8的形式另存,在python中就可以正常读取了。(话说用记事本打开要比用excel打开快好多倍)
2.2 message表预处理
因为message表中和contact表中含有大量数据分析时不用的数据列,所以在数据预处理阶段中,只需要提取message表和contact表中我们所关注的一些数据。对于message表而言,我们只关注talker,createTime,type, isSend, content所表示的内容,也即聊天对象,聊天时间,消息类型,消息由谁发送,聊天内容。更近一步,对于聊天内容而言,我们只关注文本消息(文本消息可用于后续制作词云),对于其他类型的消息我们只需要统计出现的次数,而不必关注具体内容。所以在预处理过程中,同时需要将非文本类型消息内容置0,这样做的另一个好处是可以大大减少message表的数据量,就个人而言,将非文本消息置零后,message文件大小由134MB缩小到29M。
提取talker,createTime,type, isSend, content内容
"""
Create on 2020-11-21
@author: muxiaohe
"""
# 对message表中内容进行处理,只留下所需的type, isSend, createTime, talker, content内容,并将之存储于新的文件中
def get_needed_data(file_path, save_file_path):message = read_file(file_path)message = message[['type', 'isSend', 'createTime', 'talker', 'content']]message.to_csv(save_file_path, encoding='utf_8_sig',header=True, index=False)
将非文本消息置零
"""
Create on 2020-11-21
@author: muxiaohe
"""
# 对message表中数据进行处理,,删除content中的无用数据,将type中非1值对应的content数据统统置为零
def data_clean(file_path, save_path):message = pd.read_csv(file_path, sep=',', encoding='utf-8', low_memory=False)print("源文件大小: ", message.shape)message.loc[message.type != 1, 'content'] = 0print("处理后文件大小: ", message.shape)message.to_csv(save_path, encoding='utf_8_sig', header=True, index=False)
2.3 contact表预处理
与message表类似,contact表也需去除无关数据,contact表中我们只提取 usename, alias, conRemark, nickname信息,同时在处理时只保留了有备注的联系人,没有备注的联系人也没必要分析聊天记录。
"""
Create on 2020-11-21
@author: muxiaohe
"""
# 对contact表中数据进行预处理,获取所需数据,清除其余数据
def contact_pre_treatment(file_path, save_path):contact_path = r"D:\wechet-anayze\recontact.txt"contact_save_path = r"D:\wechet-anayze\pre-recontact.csv"contact = pd.read_csv(contact_path, sep=',', encoding="utf-8", low_memory=False)print("处理前文件大小: ", contact.shape)contact = contact[['username', 'alias', 'conRemark', 'nickname']]# 删除无用记录,只保留有备注的联系人contact1 = contact.drop(contact[pd.isna(contact.conRemark)].index)print("处理后文件大小: ", contact.shape)contact1.to_csv(contact_save_path, encoding='utf_8_sig', header=True, index=False)
3.聊天记录分析
3.1 获取常用联系人聊天次数
在预处理的基础之上,获取每个联系人的聊天次数,并据此使用pyecharts绘制柱状图,使用pyecharts绘制时需特别注意:pyecharts传入数据时需要int数据,而从文件中读取赋值到list中的数值类型为int64,需要先使用int()函数进行转换,否则绘制出来的图形中data数据域将都为NaN。
"""
Create on 2020-11-21
@author: muxiaohe
"""
# 获取常用联系人聊天次数
def get_chat_nums(message_path, contact_path):""":param message_path: 预处理完成后的message表存储路径:param contact_path: 预处理完成后的contact表存储路径:return:"""# message_path = r'D:\wechet-anayze\pre-message-2.txt'# contact_path = r'D:\wechet-anayze\pre-recontact.csv'message = pd.read_csv(message_path, sep=',', encoding='utf-8', low_memory=False)contact = pd.read_csv(contact_path, sep=',', encoding='utf-8', low_memory=False)# 提取出联系人列表中用户名和备注名称contact = contact[['username', 'conRemark']]# 将用户名提取出来username = contact['username'].tolist()print(type(username))# 将用户名及备注名提取为一个字典contact_dict = dict(zip(contact['username'], contact['conRemark']))# 联系人及其聊天次数集合contact_sum_message = {}# 全部联系人聊天次数集合sum_message = 0# 联系人列表uname_list = []# 联系人列表对应的聊天次数列表chat_num_list = []# 遍历联系人列表,并逐一统计聊天次数for uname in username:# 根据微信id获取真实姓名,key为真实姓名key = contact_dict.get(uname)# 根据微信id统计聊天次数,value:聊天次数value = (message['talker'] == uname).sum()# 过滤聊天次数为0的联系人,只保留聊天次数不为0的联系人if value != 0:contact_sum_message[key] = valuesum_message += valueuname_list.append(key)# 这里需特别注意:value值也即聊天的次数格式是int64,但是pyecharts中如果传入的是int64时,最终渲染出的html文件中会数据会丢失,# 所以需转为int值(血泪教训)chat_num_list.append(int(value))# print(contact_sum_message)print("总聊天次数: ", sum_message)# 使用pyecharts绘制柱状图c = (Bar(init_opts=opts.InitOpts(width="1600px", height="600px", page_title="聊天次数统计")).add_xaxis(uname_list).add_yaxis(series_name="聊天次数", y_axis=chat_num_list, color='#FF6666').set_global_opts(# 标题配置title_opts=opts.TitleOpts(title="聊天次数统计"),# X轴区域缩放配置项,可使用list同时配置多个配置项datazoom_opts=[opts.DataZoomOpts(range_start=20, range_end=40), opts.DataZoomOpts(type_="inside")],# 区域选择组件brush_opts=opts.BrushOpts(),# X坐标轴旋转xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),# 工具箱组件toolbox_opts=opts.ToolboxOpts(),# 图例配置legend_opts=opts.LegendOpts(is_show=False),).set_series_opts(label_opts=opts.LabelOpts(is_show=False),# 配置最大值最小值刻度线markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(type_="min", name="最小值"),opts.MarkLineItem(type_="max", name="最大值"),opts.MarkLineItem(type_="average", name="平均值"),]),).render("chat_num_count.html"))
3.2 获取聊天消息中不同类型消息占比
"""
Create on 2020-11-21
@author: muxiaohe
"""
import pandas as pd
from pyecharts import options as opts
from pyecharts.charts import Pie
# 获取各个消息聊天记录数量,并使用pycharts绘图
def get_message_type_frequency(file_path, wxid):""":param file_path: 经过预处理后的message表存储位置:param wxid: 待查询人的微信id:return:"""# file_path = r'D:\wechet-anayze\pre-message-2.txt'message = pd.read_csv(file_path, sep=',', encoding='utf-8', low_memory=False)# wxid = ''# 进行数据筛选,选择message表中与所需微信id一致的数据message = message[message['talker'] == wxid]# 根据消息类型统计每种类型的频次(索引为数字编码)chat_type_count = message['type'].groupby(message['type']).size()# 消息类型对应关系message_type = {'1': '文本内容', "3": "图片及视频", "34": "语音消息", "42": "名片信息", "43": "图片及视频","47": "表情包", "48": "定位信息", "49": "小程序链接", "10000": "消息撤回提醒", "1048625": "网络照片","16777265": "链接信息", "419430449": "微信转账", "436207665": "红包", "469762097": "红包","-1879048186": "位置共享"}# 集合对象,功能与chat_type_count相同,存储(聊天类型:频次)信息(索引为对应中文类型)chat_type_count_dict = {}# 根据消息类型代码for key in chat_type_count.index:if str(key) in message_type.keys():print(message_type.get(str(key)))chat_type_count_dict[message_type.get(str(key))] = chat_type_count[key]else:chat_type_count_dict[key] = chat_type_count[key]print("结果集类型: ", type(chat_type_count_dict))print(chat_type_count_dict)x_data = []y_data = []for key in chat_type_count_dict:temp = [str(key), chat_type_count_dict.get(key)]x_data.append(str(key))y_data.append(int(chat_type_count_dict.get(key)))a1 = []for z in zip(x_data, y_data):a1.append(z)pie = Pie(init_opts=opts.InitOpts(width="1600px", height="600px", page_title="消息类型统计"))pie.add("",data_pair=a1,center=["35%", "60%"],)pie.set_global_opts(title_opts=opts.TitleOpts(title="Pie-调整位置"),legend_opts=opts.LegendOpts(pos_left="15%"),)pie.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}"))pie.render("message_type_count.html")
3.3 聊天记录词云
可选择具体的聊天对象,获取全部的聊天内容,代码中可以chinese_slice选择是否进行分词,如果不进行分词则将全部聊天内容拼接到一起,通过wordcloud模块生成词云,如果选择分词则会调用jiebe模块先进行分词,然后再通过wordcloud模块生成词云。
"""
Create on 2020-11-21
@author: muxiaohe
"""
import imageio
import jieba
import pandas as pd
import matplotlib.pyplot as plt
import wordcloud
# 根据聊天记录生成词云
def get_wordcloud(file_path, stopword_path, wxid, image_path):""":param file_path: 预处理完成后的message表存储位置:param stopword_path: 停用词文件存储位置:param wxid: 待查询人微信id:return:"""# 分词及词云处理# message_path = r'D:/wechet-anayze/pre-message-2.txt'# stopword_path = r'D:/wechet-anayze/stopword.txt'# 文件读取message = pd.read_csv(file_path, sep=',', encoding='utf-8', low_memory=False)# 数据筛选,选择对应微信id的信息message = message[message['talker'] == wxid]# 提取聊天内容信息content = message['content']# 中文字型存储路径font_path = r'C:\Windows\Fonts\MSYH.TTC'# 是否选用分词wordcut_flag = True# 词云图片输出路径image_out_name = 'word-heart.png'# 读取停用词表stopwords = [line.strip() for line in open(stopword_path, encoding='UTF-8').readlines()]if image_out_name is None:image_out_name = 'word-heart.png'if wordcut_flag:print("进行中文分词")outstr = ""text = ",".join(content)text_list = jieba.lcut(text, cut_all=False)for word in text_list:if word not in stopwords:if word != '\t' and '\n':outstr += wordoutstr += " "# 如果想存储分词后结果,可取消下方注释# savepath = r'D:/wechet-anayze/textlist.txt'# fp = open(savepath, 'w', encoding='utf8', errors='ignore')# fp.write(outstr)# fp.close()text = outstrelse:print("不进行中文分词")text = " ".join(content)# 词云形状图片位置mk = imageio.imread(image_path)# 构建并配置词云对象w,注意要加scale参数,提高清晰度w = wordcloud.WordCloud(width=1000,height=700,background_color='white',font_path=font_path,mask=mk,scale=2,stopwords=None,contour_width=1,contour_color='red')# 将string变量传入w的generate()方法,给词云输入文字w.generate(text)# 展示图片# 根据原始背景图片的色调进行上色image_colors = wordcloud.ImageColorGenerator(mk)plt.imshow(w.recolor(color_func=image_colors))# 根据原始黑白色调进行上色# plt.imshow(wc.recolor(color_func=grey_color_func, random_state=3), interpolation='bilinear') #生成黑白词云图# 根据函数原始设置进行上色# plt.imshow(wc)# 隐藏图像坐标轴plt.axis("off")plt.show()# 将词云图片导出到当前文件夹w.to_file(image_out_name)
有兴趣的话可以参考我的GitHub地址,里边有所需的全部文件及代码,有帮到的请给star呀~
微信聊天记录提取及分析
微信聊天记录提取及分析(wordcloud+pyecharts)相关推荐
- 利用python做微信聊天记录词云分析——记录美好回忆
目录 1 概述 2 数据准备 2.1 安卓设备 2.1.1 Root手机,安装Root Explorer 2.1.2 用Root Explorer将聊天记录的数据文件导出并存入电脑 2.1.3 对En ...
- 微信聊天记录词云分析
步骤 - 获取对象聊天记录加密数据 - 解码 - 对csv数据进行筛选 -词云分析 获取微信聊天记录加密数据 安卓手机获取微信导出微信聊天记录需要先获取root权限,这个风险比较大,而且我这个手机比较 ...
- 微信聊天记录数据提取并分析
项目背景: 公司有一部手机,这个手机专门用微信群拉客户的.手机里微信群聊天记录很多,想把这些聊天记录提取出来分析一下有用的信息. 查找一下 首先看一下有没有人之前做个这个项目,如果有的话就不用浪费时间 ...
- 微信聊天记录的词云制作
微信聊天记录的词云制作 需求 导出微信聊天记录 提取文字聊天记录 生成词云 需求 想把跟朋友的微信聊天记录做个词云 导出微信聊天记录 我的手机是iphone,用旧版的itunes备份手机全部信息 it ...
- 520小玩意之Python词云:导出与女票的微信聊天记录并分析
用python看看自己和女票都聊了些什么事 最终效果图: 一.导出微信聊天文件 写2种导出聊天记录的方法:一种是Mac版微信,另一种是iOS版微信. 1.导出Mac版微信聊天记录 Mac版微信在本地存 ...
- python通过微信聊天记录分析_Python利用itchat对微信中好友数据实现简单分析的方法...
前言 最近在一个微信公众号上看到一个调用微信 API 可以对微信好友进行简单数据分析的一个包 itchat 感觉挺好用的,就简单尝试了一下. 库文档说明链接在这: itchat 安装 在终端中输入以下 ...
- WX Backup - 免费微信聊天记录备份导出与查看工具 (可提取图片/视频/语音)
微信绝对是一个让人爱恨交织的 APP,它在国内几乎完全占据了人们的社交以及生活的方方面面,但腾讯却并没有为微信提供好用的「聊天记录」备份导出和查看的功能. WX Backup 是一款完全免费的微信聊天 ...
- 微信聊天记录深度分析,看看这一年你和谁最亲密
原文链接: https://zhuanlan.zhihu.com/p/100084316 2019年就要过去了,想知道你平时用的最多的词是什么吗?想知道你一天中哪个时间段聊天最多吗?想知道这一年谁和你 ...
- chatgpt赋能python:Python微信聊天记录:如何导出并分析聊天记录
Python 微信聊天记录:如何导出并分析聊天记录 微信是目前最受欢迎的聊天工具之一,但是它的聊天记录并不方便导出和分析.本文将介绍如何使用 Python 导出微信聊天记录,并进行分析. 导出微信聊天 ...
最新文章
- C#解析XML各种方法特点比较(转载)
- 公子龙:我读研期间通过实习和比赛收入五十万
- ksql 数量大于2_A股史上唯一能暴涨200%的买卖铁则:内盘大于外盘股价必跌,外盘大于内盘股价必涨,堪称绝技...
- 【全记录】2017云栖大会·北京峰会——企业云上业务优化专场
- 变压器 5g_T5:文本到文本传输变压器
- 【英语学习】【Level 07】U01 Making friends L2 A new friend from the past
- Intel 64/x86_64/IA-32/x86处理器 - SIMD指令集 - SSE扩展(6) - 逻辑指令 比较指令
- FusionCharts参数说明——3D饼图属性(Pie3D.swf )
- unity 是厘米还是米_做工扎实,可玩性强,类乐高产品的好选择,米兔积木工程吊车...
- 记录一下免费域名和空间
- 转:神奇的Fastcgi_Finish_Request
- 用于语音识别的数据增强
- 【Leetcode 795】Number of Subarrays with Bounded Maximum
- 论文笔记_S2D.31_2015-CVPR_对单张图像进行统一的深度和语义预测
- 计算机考试九九乘法表,多种办法用EXCEL软件生成99乘法表
- php pager,fleaphp常用方法分页之Pager使用方法
- BCD码与十进制转换
- 串口连接BBB(三)
- Php区分自然量跟aso量,ASO优化——判断下载量与评论的比例关系
- C++ uint8_t