关闭

爱情大数据 | 你的专属微信聊天记录统计

556人阅读 评论(0) 收藏 举报

微信聊天记录数据分析


或许每个人的微信列表里都有几个不舍删除的聊天记录,经年累月,这些聊天记录越积越多,终将成为你和这个人之间的美好回忆。这些回忆中有许多信息值得挖掘,尤其是情侣之间,将这些信息统计出来做一份“爱情报表”,一定会给自己的另一半带去一份惊喜。


工作内容

  • 获取微信聊天数据库
  • 解密数据库获取聊天数据
  • 使用Python分析数据
  • ECharts(或者pyecharts)做数据可视化

获取聊天数据库

这个教程主要是针对安卓手机用户的,对于IOS系统,不太清楚如何获取聊天数据库,毕竟IOS系统生态非常封闭。安卓用户获取微信聊天数据库的方法很简单:

  • 首先需要获取手机root权限
  • 安装RE文件管理器(Root Explorer)
  • 打开RE文件管理器,在路径/data/data/com.tencent.mm/MicroMsg下找到一个由32位字符串命名的文件夹,比如我的文件夹如下,这个32位字符串是mm+uin码进行md5加密后得到的(uin码后面会说)
    这里写图片描述

  • 进入该文件夹,找到EnMicroMsg.db,即为你的微信聊天数据库,将其复制出来并传到电脑上


解密数据库获取聊天数据

解密微信数据库,在网上有很多的教程,归结起来就是,数据库密码=md5(IMEI+uin)[0:7],意思就是,将你手机的IMEI码和你微信的uin码加起来用md5加密后得到一串32位的字符串,取其前7位即为数据库的密码。但是在操作的过程中会有一些坑。

  • 获取IMEI码,即打开手机的拨号界面,输入* #06#,这时就会自动弹出你的IMEI码,但是对于双卡用户,操作的时候会有些懵,比如我用的小米6,输入* #06#后会出来3个码……其实也不用懵,MEID码直接无视,下面两个IMEI码的话,一般都是取第一个,当然不放心的话可以两个都试试。
    这里写图片描述
  • 获取uin码,再次打开RE文件管理器,在路径/data/data/com.tencent.mm/shared_prefs下找到auth_infokey_prefs.xml文件并打开,找到如下文字,其中value后面跟着的就是你的uin码了,我的是8位,每个人uin码的位数可能不一样。
    这里写图片描述
  • 在获取到IMEI码和uin码之后就可以相加后使用md5加密得到密码了。加密可以使用在线md5工具,密码是小写32位md5值的前7位。
    这里写图片描述
  • 获取到密码后就是解密数据库了。工具是sqlcipher.exe,我在网上找了很多版本,这个是最好用的:https://pan.baidu.com/s/1i7nGgS1(密码:sz4u)。打开后找到message表,这里就是全部的聊天记录了,关键的信息就是createTime、talker以及content这三列了,值得注意的是,数据库中保存的时间数据是时间戳,并且每一个数据后面都多出了三位0,在进行数据分析时需要把这三个0剔除。然后我们依次点击File–>Export–>Table as CSV file,将message表导出,我们就可以开始进行数据分析了。导出的文件默认有.csv和.txt两种,后缀需要手动写上去。此外,如果直接读取这个文件的话可能会存在编码错误的问题,建议在保存csv文件以后,右键使用记事本打开,然后再另存为一个新的文件,编码使用utf-8。
    这里写图片描述
    这里写图片描述

使用Python分析数据

呼……终于进入正题了。聊天记录包含了非常丰富的数据,这里我只做了两个比较简单的例子,一个是针对时间做聊天时间段分布的统计;一个是针对内容做字符匹配,统计一些高频词汇出现的次数,比如“早安”、“晚安”、“想你”、“爱”等等(你懂的)。

读取数据

使用pandas读取csv文件里的数据,我们需要的数据在6、7、8三列:

chat = pd.read_csv('chat.csv', sep=',', usecols=[6,7,8])

然后定义两个list,分别用来存储聊天记录的时间和内容,定义变量myGirl,赋值为想要提取出来的联系人的微信号:

myGirl = 'wxid_xxxxxxxx'
chat_time = []
chat_content = []
for i in range(len(chat)-1):
    content = chat[i:i+1]
    if content['talker'].values[0] == myGirl:
        t = content['createTime'].values[0]//1000#除以1000用以剔除后三位0
        c = content['content'].values[0]
        chat_time.append(t)
        chat_content.append(c)

这时chat_time和chat_content里就存储着你和女(男)朋友所有的聊天数据了。接下来需要定义一个函数to_hour()将时间戳转换为24h进制,然后用列表推导式批量进行转换:

def to_hour(t):
    struct_time = time.localtime(t)#将时间戳转换为struct_time元组
    hour = round((struct_time[3] + struct_time[4] / 60), 2)
    return hour

hour_set = [to_hour(i) for i in chat_time]
绘图

聊天时段的分布可以使用seaborn绘制核密度图,非常简洁,一句话搞定,当然如果想让图片好看些的话还需要做额外的配置:

import seaborn as sns 
from matplotlib.font_manager import *#如果想在图上显示中文,需导入这个包
myfont = FontProperties(fname=r'C:\Windows\Fonts\MSYH.TTC',size=22)#标题字体样式
myfont2 = FontProperties(fname=r'C:\Windows\Fonts\MSYH.TTC',size=18)#横纵坐标字体样式
sns.set_style('darkgrid')#设置图片为深色背景且有网格线
sns.distplot(hour_set, 24, color='lightcoral')
plt.xticks(np.arange(0, 25, 1.0), fontsize=15)
plt.yticks(fontsize=15)
plt.title('聊天时间分布', fontproperties=myfont)
plt.xlabel('时间段', fontproperties=myfont2)
plt.ylabel('聊天时间分布', fontproperties=myfont2)
fig = plt.gcf()
fig.set_size_inches(15,8)
fig.savefig('chat_time.png',dpi=100)
plt.show() 

上面是我经常使用的一些配置方案。通过核密度图可以看出,我和我女朋友属于夜猫子类型的,经常在半夜聊天,23点至24点的峰值特别高。
这里写图片描述
不过虽然“lightcoral”的配色非常少女,但是如果你的女(男)朋友并不了解数据分析和统计学的话,上面的图片还是显得有些过于“专业”了,可能只会得到一个“哦(冷漠脸)”字作为回应。因此,一个合适的数据展示方式就显得尤为重要了。

使用ECharts

ECharts(http://echarts.baidu.com/)是一个开源的js组件,绘制的图表种类繁多而且很好看,使用起来也很方便,当然如果你并没有接触过js甚至对其有些抵触,那么也可以安装pyecharts(https://github.com/pyecharts/pyecharts),可以看做是ECharts的Python版,操作更为简洁。这里我使用的是ECharts。首先我们需要在Python中统计hour_set里不同时间段的聊天记录条数,时间段可以任意划分,然后打开ECharts官网,找到官方实例中的雷达图,将统计出的各时间段聊天数据直接替换进去就可以了:

option = {
    title: {
        text: '聊天时间段',
        textStyle: {
            color: '#000',
            fontSize: 20
        }
    },
    //toolbox配置项可以在网页上直接生成下载图片的按钮而不用截图
    toolbox: {
      show: true,
      feature: {
        saveAsImage: {
            show:true,
            excludeComponents :['toolbox'],
            pixelRatio: 2
        }
      }
    },
    tooltip: {},
    radar: {
        // shape: 'circle',
        name: {
            textStyle: {
                color: '#fff',
                backgroundColor: '#999',
                borderRadius: 3,
                padding: [3, 5]
           }
        },
        indicator: [
           { name: '凌晨2点至6点', max: 400},
           { name: '6点至10点次', max: 400},
           { name: '10点至14点', max: 400},
           { name: '14点至18点', max: 400},
           { name: '18点至22点', max: 400},
           { name: '22点至次日凌晨2点', max: 400}
        ]
    },
    series: [{
        name: '聊天时间段',
        type: 'radar',
        // areaStyle: {normal: {}},
        data : [
            {
                value : [63, 141, 250, 213, 263, 390],
                name : '聊天时段'
            }
        ]
    }]
};

这里写图片描述
雷达图的显示方式比上面的核密度图要友善的多,如果是在网页上浏览的话效果更好,因为是可以动的。

统计特殊数据绘制字符云

对于所有夜猫子类型的人来说,可能都会有深夜聊天的经历,比如上面的雷达图中,凌晨2点至清晨6点之间还存在少量的聊天记录,那些不眠的夜晚你可能已经遗忘,但数据会帮你回忆起一切。我们定义一个deep_night列表,在统计hour_set中的时间时,将位于2-6之间的时间数据和对应的聊天数据存进deep_night中,然后将数据写进Excel表中:

import xlwt
wbk = xlwt.Workbook()
sheet = wbk.add_sheet('late')
for i in range(len(deep_night)):
    sheet.write(i,0,time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(deep_night[i][0])))
    sheet.write(i,1,deep_night[i][1])
wbk.save('聊得很晚.xls')

然后再次祭出ECharts,进入官网,找到字符云实例,将Excel中的深夜聊天内容直接替换上去就可以了。

option = {
    tooltip: {},
    series: [{
        type: 'wordCloud',
        gridSize: 20,
        sizeRange: [12, 50],
        rotationRange: [0, 45],
        shape: 'circle',
        textStyle: {
            normal: {
                color: function() {
                    return 'rgb(' + [
                        Math.round(Math.random() * 200),
                        Math.round(Math.random() * 200),
                        Math.round(Math.random() * 200)
                    ].join(',') + ')';
                }
            },
            emphasis: {
                shadowBlur: 10,
                shadowColor: '#333'
            }
        },
        data: [{
            name: '呵呵',
            value: 800,
            textStyle: {
                normal: {
                    color: 'black'
                },
                emphasis: {
                    color: 'red'
                }
            }
        }, {
            name: '别傻了,这是假数据',
            value: 618
        }, {
            name: 'ECharts好用',
            value: 438
        }, {
            name: '哈哈。。',
            value: 405
        }, {
            name: '点个赞',
            value: 246
        }, {
            name: '世界人民大团结万岁',
            value: 224
        }, {
            name: 'naive',
            value: 189
        }, {
            name: '还得学习一个',
            value: 148
        }, {
            name: '闷声发大财!',
            value: 111
        }, {
            name: '学习使我快乐',
            value: 965
        },  {
            name: '葡萄牙1:0!!!',
            value: 582
        }, {
            name: '+1s',
            value: 555
        }, {
            name: '两点半的夜晚  哈哈哈哈',
            value: 550
        }]
    }]
};

这里写图片描述
这个官方实例很简单,字符云的形状是杂乱、随机的,不过我们可以设置maskImage,即整个字符云可以摆成maskImage的形状,大家可以去社区里找找别人做的方案(想想把你和女(男)朋友的聊天记录用字符云的形式摆成一个心形。。。还要啥自行车啊)。

匹配高频字符

这一部分也不难,说白了就是对所有聊天记录做一个字符的正则匹配。正则表达式在爬虫中经常使用,虽然语法很多很繁杂,但是对于匹配字符来说就很简单了,写法很固定。比如我想匹配一句话中“爱”字出现的次数,定义一个pattern=’. * ?(爱). * ?’,这里.*?代表匹配任意字符,“爱”字一定要打括号,然后调用re模块的findall()方法进行匹配,得到的结果是全由“爱”字组成的list,取其长度就是“爱”字出现的次数了:

import re
pattern = '.*?(爱).*?'
string = '我爱吃西瓜,你爱不爱吃。'
result = re.findall(pattern, string)
result
Out[5]: ['爱', '爱', '爱']
len(result)
Out[6]: 3

接下来我们要写若干个pattern,即你想要匹配哪几个词,然后将这几个pattern放进一个list中:

pattern_love = '.*?(爱).*?'
pattern_morning= '.*?(早安).*?'
pattern_night = '.*?(晚安).*?'
pattern_miss = '.*?(想你).*?'
pattern_set = [pattern_love, pattern_morning, pattern_night, pattern_miss]

最后写一个循环嵌套,外层遍历聊天内容,内层遍历pattern_set:

start = datetime.datetime.now()
statistic = [0,0,0,0]
for i in range(len(chat_content)):
    for j in range(len(pattern_set)):
        length = len(re.findall(pattern_set[j], str(chat_content[i])))
        static[j] += length
result = {
        '爱': static[0],
        '早安': static[1],
        '晚安': static[2],
        '想你': static[3]
        }
print(result)
end = datetime.datetime.now()
print('\n..........\n字符统计结束,用时: {}\n............\n'.format(end-start))

用同样的方法还可以匹配各种字符,字符越多时间越久,我在12万多条记录中匹配15个字符,大概耗时4分钟,CPU为i7-6700K,在真正的做大数据分析的在时候,这一步是最耗时的,基本都需要进行分布式运算了。数据展示方面可以使用字符云,不同字符的value值就是其出现的次数,出现次数较多的字符自然就会大一些。当然也可以学习前段时间网易云音乐展示数据的方式:

这一年
你一共说了999次爱

你热衷聊天
喜欢在午夜倾诉衷肠

11月11日大概是很特别的一天

这一天里

你把“早安”

反复说了11次(早安怪???)
……

呃呃,总之大家可以发挥自己的想象。如果想要写的像网易云音乐那样详细的话,就必须把聊天内容和聊天时间一一对应起来,而不能像上面的例子一样将内容和时间分开讨论。当然操作也很简单,只需要定义一个二维list就可以了,第一维是时间,第二维是内容,不过数据库中存储的数据时间是混乱的,并不是按时间递增的,所以我们还需要自己处理一下,也即以list第一维为对象进行排序带动第二维跟着排序:

from operator import itemgetter
chat_all = []
myGirl = 'wxid_xxxxxxxx'
for i in range(len(chat)-1):
    content = chat[i:i+1]
    if content['talker'].values[0] == myGirl:
        t = content['createTime'].values[0]//1000
        c = content['content'].values[0]
        chat_all.append([t,c])
chat_all = sorted(chat_all, key=itemgetter(0))#以第一维为索引排序

这个时候chat_all里就是按照时间顺序排序好的数据了,剩下的就是按照上面的方法进行字符匹配等等操作,也可以挖掘其他好玩的信息,比如结合机器学习算法进行某些信息的预测,对于时间序列数据使用LSTM网络进行预测再合适不过了,当然聊天行为属于社会活动,想要做出更加准确的预测还需要涉及博弈……总之,对上面的一些数据分析来说,编程的难度并不大,主要是发挥自己的想象力,能够在同样的数据中挖掘出独特且有意义的信息是数据分析很重要的一点,同样重要的还有数据的展示方式,毕竟多数人都是外貌协会,好看的展示方式才更得人心。完整代码如下:

import pandas as pd
import time
import seaborn as sns 
import matplotlib.pyplot as plt
import datetime
import numpy as np
import re
from operator import itemgetter
from matplotlib.font_manager import *#导入这个包,可以添加中文字体
import xlwt

chat_file = '自己的csv文件'
myGirl = '目标联系人的微信号'

''' 读取原数据 '''
chat = pd.read_csv(chat_file, sep=',', usecols=[6,7,8])
chat_time = []
chat_content = []
chat_all = []
for i in range(len(chat)-1):
    content = chat[i:i+1]
    if content['talker'].values[0] == myGirl:
        t = content['createTime'].values[0]//1000
        c = content['content'].values[0]
        chat_time.append(t)
        chat_content.append(c)
        chat_all.append([t,c])
chat_all = sorted(chat_all, key=itemgetter(0))#以第一维为索引排序

''' 转换时间格式 '''        
def to_hour(t):
    struct_time = time.localtime(t)
    hour = round((struct_time[3] + struct_time[4] / 60), 2)
    return hour
hour_set = [to_hour(i) for i in chat_time]

print('\n.......................\n开始画图\n.......................')
from matplotlib.font_manager import *#如果想在图上显示中文,需导入这个包
myfont = FontProperties(fname=r'C:\Windows\Fonts\MSYH.TTC',size=22)#标题字体样式
myfont2 = FontProperties(fname=r'C:\Windows\Fonts\MSYH.TTC',size=18)#横纵坐标字体样式
sns.set_style('darkgrid')#设置图片为深色背景且有网格线
sns.distplot(hour_set, 24, color='lightcoral')
plt.xticks(np.arange(0, 25, 1.0), fontsize=15)
plt.yticks(fontsize=15)
plt.title('聊天时间分布', fontproperties=myfont)
plt.xlabel('时间段', fontproperties=myfont2)
plt.ylabel('聊天时间分布', fontproperties=myfont2)
fig = plt.gcf()
fig.set_size_inches(15,8)
fig.savefig('chat_time.png',dpi=100)
plt.show() 
print('\n.......................\n画图结束\n.......................')

''' 聊天时段分布 '''
print('\n.......................\n开始聊天时段统计\n.......................')
time_slice = [0,0,0,0,0,0]
deep_night = []
for i in range(len(hour_set)):
    if hour_set[i]>=2 and hour_set[i]<6:
        time_slice[0] += 1
        deep_night.append([chat_time[i], chat_content[i]])
    elif hour_set[i]>=6 and hour_set[i]<10:
        time_slice[1] += 1
    elif hour_set[i]>=10 and hour_set[i]<14:
        time_slice[2] += 1
    elif hour_set[i]>=14 and hour_set[i]<18:
        time_slice[3] += 1
    elif hour_set[i]>=18 and hour_set[i]<22:
        time_slice[4] += 1
    else:
        time_slice[5] += 1
labels = ['凌晨2点至6点','6点至10点','10点至14点',
          '14点至18点','18点至22点','22点至次日凌晨2点']
time_distribution = {
        labels[0]: time_slice[0],
        labels[1]: time_slice[1],
        labels[2]: time_slice[2],
        labels[3]: time_slice[3],
        labels[4]: time_slice[4],
        labels[5]: time_slice[5]
        }
print(time_distribution)

''' 深夜聊天记录 '''
wbk = xlwt.Workbook()
sheet = wbk.add_sheet('late')
for i in range(len(deep_night)):
    sheet.write(i,0,time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(deep_night[i][0])))
    sheet.write(i,1,deep_night[i][1])
wbk.save('聊得很晚.xls')
print('\n.......................\n聊天时段统计结束\n.......................')

''' 字符统计 '''
print('\n..........\n开始字符统计\n............\n')
start = datetime.datetime.now()
pattern_love = '.*?(爱).*?'
pattern_morning= '.*?(早安).*?'
pattern_night = '.*?(晚安).*?'
pattern_miss = '.*?(想你).*?'
pattern_set = [pattern_love, pattern_morning, pattern_night, pattern_miss]
statistic = [0,0,0,0]
for i in range(len(chat_content)):
    for j in range(len(pattern_set)):
        length = len(re.findall(pattern_set[j], str(chat_content[i])))
        static[j] += length
result = {
        '爱': static[0],
        '早安': static[1],
        '晚安': static[2],
        '想你': static[3]
        }
print(result)
end = datetime.datetime.now()
print('\n..........\n字符统计结束,用时: {}\n............\n'.format(end-start))
0
0
查看评论

文本分析实例---QQ聊天记录分析

对QQ聊天记录进行分析,因为每天产生的聊天记录比较多,所以选取的是从2月份整月的聊天记录数据,分析要产生的结果有三个,聊天记录中发消息的人前top15,统计24小时时间段那个时间段发贴人最多,还有对消息中的热词进行抽取。   对QQ用户发贴次数进行统计,需要注意QQ导出的聊天记录格式,...
  • vs412237401
  • vs412237401
  • 2016-03-01 11:10
  • 5074

【python 可视化】pyecharts + Django 使用指南

本指南按照 Django 官方教程,通过完成一个 Django 小项目来说明如何在 Django 中使用 pyecharts。如果对 Django 还不太熟悉的开发者,可仔细阅读官方提供的最新文档。 Step 0: 使用新的 virtualenv 环境建议开发者使用 1.11.4 版本的 Djan...
  • u013421629
  • u013421629
  • 2017-10-10 14:35
  • 2229

【Python学习系列二十八】绘图库pyecharts

网址:https://github.com/chenjiandongx/pyecharts 安装:pip install pyecharts 参考代码: # -*- coding: utf-8 -*- import sys defaultencoding = 'utf-8' if s...
  • fjssharpsword
  • fjssharpsword
  • 2017-08-04 14:31
  • 4297

用流读写csv文件

http://www.cnblogs.com/Clin/archive/2013/03/14/2959022.html DataTable dt = new DataTable(); var filePath="@c:/"; F...
  • fangzilixia
  • fangzilixia
  • 2016-05-18 15:40
  • 883

微信QQ聊天记录分析工具-微Q

1.背景         忙了一周,从设计算法到编程,到部署服务器,到最后的UI实现,终于我的微Q诞生了。         用起来非常的简洁,只要把微信或者qq的聊天记录导出来,是个txt文件,导入微...
  • gshengod
  • gshengod
  • 2014-12-11 16:29
  • 4963

Android逆向之旅---静态方式破解微信获取聊天记录和通讯录信息

微信现在是老少皆宜,大街小巷都在使用,已经替代了传统的短信聊天方式了,只要涉及到聊天就肯定有隐私消息,那么本文就来讲解如何获取微信的聊天记录以及通讯录信息
  • jiangwei0910410003
  • jiangwei0910410003
  • 2016-08-22 08:59
  • 26173

教你怎么查微信聊天记录?

百度唯一认证団队QQ: 862539992 《嘿客帝国》成立超过8年,他们查询手机通话记录短信内容 微信记录 qq聊天记录 破解微信QQ密码 开房记录 本部以信誉第一,客户为上,诚信服务! 1 首先,登入微信。...
  • kkk5678
  • kkk5678
  • 2015-06-28 19:42
  • 645

是时候给你的微信公众号请一位专属客服了

1.为什么要写这篇文章? 一是因为经常逛知乎,发现好些知乎大神的签名上都放的自己的微信公众号,但是关注之后就回一句简单的谢谢关注之类的话,缺乏互动性。二来是之前网盘共享了一堆本科生的毕设,为了防止别有用心的人拿去卖,加了密码,想要获取密码的话得加我微信验证。最近好多人都来加微信求密码,实在忙不过来...
  • lgdlxc
  • lgdlxc
  • 2017-03-06 21:11
  • 538

微信聊天记录查看器(程序+源码) - iOS版

本文版权归cxun所有,如有转载请注明出处与本文链接,谢谢! 原文地址:http://www.cnblogs.com/cxun/p/4338643.html   摘要 iPhone中的微信是不是占用了越来越多的空间呢?不想删图片?不舍得删视频?那就转移到电脑硬盘上来吧,...
  • caizi001
  • caizi001
  • 2015-05-18 08:52
  • 2952

你有没有过奋不顾身的爱情,然后痛彻心扉的失去,你有过吗?

你有没有过奋不顾身的爱情,然后痛彻心扉的失去,你有过吗?
  • WASEFADG
  • WASEFADG
  • 2017-12-09 20:33
  • 12107
    个人资料
    • 访问:861次
    • 积分:38
    • 等级:
    • 排名:千里之外
    • 原创:3篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章存档