本文将使用情侣的微信聊天记录作为文本来源, 是不是更情深意切, 一虐方休
本文的操作系统环境: iOS 10.2.1,macOS 10.12.3, 用到了一个第三方的 iOS 设备管理工具工具 iMazing, 官网上是很贵的, 淘宝上有团购的正版卖, 便宜不少编程环境为 Python 3.6, 使用 Jupyter Notebook 4.2.1
提取聊天记录数据
首先打开这个软件, 映入眼帘的是如下界面首先点击左侧的文件系统之后, 既可以选择最左边的应用程序, 也可以选择最右边的备份
第一步
先点击备份时
点击备份后
此时就要千辛万苦找到存放聊天记录的数据库的位置 (这个路径网上都搜不到, 有软件直接靠这个位置卖钱的, 被我瞎猫碰死耗子找到了)
Apps/AppDomain-com.tencent.xin/Documents/04015/DB/MM.sqlite
04015 是很长一串数字英文夹杂的文件夹名, 可能文件夹因人而异的, 可能 Documents 文件里有多个该类型文件夹, 选择时间最新的那个
先点击应用程序时
在其中找到微信, 看到文稿由于 iOS 限制是无法访问的, 只能点击备份
点击应用程序找到微信并点开后
进去之后就会看到文件夹 Documents, 之后操作与上文一致
导出数据库
找到上文所说的数据库之后, 点击拷贝至 Mac, 保存到电脑某处就可以了
数据库初窥
从扩展名可知, 这是一个 sqlite 数据库, 推荐一个免费软件叫 sqlitebrowser, 打开数据库后发现里面有好几百张 (根据你的聊天记录条数而变化) 表啊! 每一张表代表着一个聊天对象, 可能是群可能是人可能是公众号到底妹子在哪一张表里呢?
数据库内容
我的 SQL 能力很差, 只好通过 python 操作数据库, 办法笨了点, 编程大神不要笑我 (笑我也无妨, 我有女票)
以下开始虐狗
提取聊天记录文本
import sqlite3
import pandas as pd
conn=sqlite3.connect('%s' %'.../MM.sqlite') #连接数据库
cur=conn.cursor()
query = "SELECT name FROM sqlite_master WHERE type='table'order by name" #查询所有表名
a = pd.read_sql(query, conn)
result = []
for i in a.name: #开始遍历所有表查找女票 (的聊天记录) 藏身之处
query3 = "SELECT * FROM %s" %(i)
r = pd.read_sql(query3, conn)
if 'Message' in r.columns:
for j in r.Message:
if 'xxxxxx' in j: #注 1, 关键的一步
result.append(i)
query4 = "SELECT * FROM %s" %(result[0]) #注 1 那步完成得好, result 就会只有一个元素
text = pd.read_sql(query4, conn)
text = list(text.Message) #注 2
full_text = '\n'.join(text) #将 text 这个列表合并成字符串, 以回车符分隔
f = open('.../ 聊天记录. txt', 'w')
f.write(full_text)
f.close()
注 1: 选择你跟你女朋友的独特一句对话, 用来查找如果你发现你用么么哒我爱你亲爱的 (微信会把官方表情以表情名称形式文本化存储, 所以用这种词查找的效率不高) 等搜出了好几个人的话, 劝你还是先好好反省自己喔想到这里简直是给程序媛查岗男票的福利啊!
注 2: 经过我之前取特例观察, 存放聊天记录的表名均为 Chat_xxx, 而其中的 Message 一列存放的即是聊天记录
分词
以下代码我就不做详细解释了
import codecs
import jieba
file=codecs.open('.../ 聊天记录. txt','r')
content=file.read()
file.close()
segment=[]
segs=jieba.cut(content) #分词
for seg in segs:
if len(seg)>1 and seg!='\r\n':
segment.append(seg)
words_df=pd.DataFrame({'segment':segment})
del segment #将 segment 转换成 DataFrame 后删掉, 释放内存
我的结果是: 文本共有 17w + 行, 分出了 100w 个词汇 (重复计数) 因此用 Spyder 处理时候已经卡到不行了, 换用 Jupyter IPython Notebook 反而十分流畅, 难怪好多大神也是用 Notebook 做的
停用词库
文本挖掘的第一步分词之后的重要步骤是排除无用词语, 业内称作停用词我设定的停用词分为两个来源:
1. 由于微信中分享的网页会以地址的形式以文本存在聊天记录里, 被分词分开, 因此需要排除, 为了方便, 直接在分词结果中的所有非中文词汇放入停用词库这里一个 trick 是: 将聊天里会使用到的高频英文数字加回分词列表, 例如 233666macapp 之类的
2. 通用的停用词库, 这个库里包含了大量的连词副词等, 可见中文停用词词表所做的工作, 我直接拿来用了
3. 其他无用词语例如微信中的 xx 撤回了一条消息也会在记录里不过如果你发现你的记录里撤回的频率特别高你们真的不是在玩 Snapchat?
exclusive = [] #建立一个停用词列表
for i in words_stat.segment:
if re.findall(r'[A-Za-z0-9]*', i)[0] != '': #通过正则式表达排除英文数字 findall 返回的是一个列表
exclusive.append(i)
for j in ['666', '233', '2333', 'App', 'app', 'Mac', 'mac']: #我的举例, 读者可自行添加
exclusive.remove(j) #从排除列表中删去这些需要保留的词汇
ex = ['撤回'] #举例
for e in ex:
exclusive.append(e)
stop = '\n'.join(exclusive)
f = open('.../stopwords.txt', 'w')
f.write(stop)
f.close()
stopwords1=pd.read_csv(".../stopwords.txt", index_col=False,quoting=3,sep="\t",names=['stopword'],encoding="utf8")
stopwords2=pd.read_csv(".../ 停用词库. txt", index_col=False,quoting=3,sep="\t",names=['stopword'],encoding="utf8") #第三方停用词库
stopwords = stopwords1.append(stopwords2)
words_df=words_df[~words_df.segment.isin(stopwords.stopword)] #用停用词库更新分词列表
words_stat=words_df.groupby(by=['segment'])['segment'].agg({"计数":np.size}) #计算频率
words_stat=words_stat.reset_index().sort(columns="计数",ascending=False)
大功告成
import matplotlib.pyplot as plt
from wordcloud import WordCloud
from scipy.misc import imread
import matplotlib.pyplot as plt
from wordcloud import WordCloud,ImageColorGenerator
from scipy.misc import imread
bimg=imread('.../love.png') #背景图片
wordcloud=WordCloud(font_path="simhei.ttf",background_color="white",mask = bimg,max_font_size=600,random_state=100) #背景设成白的比较合适, 我感觉; max_font_size 和 random_state 自己调咯
wordcloud=wordcloud.fit_words(words_stat.head(4000).itertuples(index=False)) #词频排名前多少的放到图里
bimgColors=ImageColorGenerator(bimg)
plt.figure()
plt.imshow(wordcloud.recolor(color_func=bimgColors))
plt.axis("off")
plt.show()
wordcloud.to_file("结果. png") #存成文件
来源: http://geek.csdn.net/news/detail/253755