查看原文
其他

迟到的情人节礼物:做一个与她微信聊天的词云吧

2017-11-20 竹间为简 Python爱好者社区

作者:竹间为简 

经济学科班,爱生活,爱Python,爱macOS/iOS,互联网金融风控。跨界狂魔。

简书专栏:http://www.jianshu.com/u/a508c9751b83


所以这是两个逗比的日常


本文受到《十分钟视频,手把手教你用Python撒情人节狗粮的正确姿势》启发,作者寒小阳,好像是一个机器学习QQ群的群主,但是我在那个群里潜水太久已经被踢了。
原文只是拿了一个大话西游的文本来做成词云,而本文将使用情侣的微信聊天记录作为文本来源,是不是更情深意切,一虐方休。


本文的操作系统环境:iOS 10.2.1,macOS 10.12.3,用到了一个第三方的iOS设备管理工具工具iMazing,官网上是很贵的,淘宝上有团购的正版卖,便宜不少。编程环境为Python 3.6,使用Jupyter Notebook 4.2.1。


提取聊天记录数据


首先打开这个软件,映入眼帘的是如下界面。首先点击左侧的”文件系统“。之后,既可以选择最左边的“应用程序”,也可以选择最右边的“备份”。



第一步


先点击“备份”时



点击“备份”后


此时就要千辛万苦找到存放聊天记录的数据库的位置(这个路径网上都搜不到,有软件直接靠这个位置卖钱的,被我瞎猫碰死耗子找到了)
Apps/AppDomain-com.tencent.xin/Documents/04……015/DB/MM.sqlite
04……015是很长一串数字英文夹杂的文件夹名,可能文件夹因人而异的,可能Documents文件里有多个该类型文件夹,选择时间最新的那个。


先点击“应用程序”时


在其中找到微信,看到“文稿”由于iOS限制是无法访问的,只能点击“备份”。



点击“应用程序”找到微信并点开后


进去之后就会看到文件夹Documents,之后操作与上文一致。


导出数据库


找到上文所说的数据库之后,点击”拷贝至Mac“,保存到电脑某处就可以了。



导出数据库


数据库初窥


从扩展名可知,这是一个sqlite数据库,推荐一个免费软件叫sqlitebrowser,打开数据库后发现里面有好几百张(根据你的聊天记录条数而变化)表啊!每一张表代表着一个聊天对象,可能是群可能是人可能是公众号。到底妹子在哪一张表里呢?



数据库内容


我的SQL能力很差,只好通过python操作数据库,办法笨了点,编程大神不要笑我(笑我也没无妨,我有女票)。


以下开始虐狗


提取聊天记录文 47 32439 47 15232 0 0 3418 0 0:00:09 0:00:04 0:00:05 3418

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一列存放的即是聊天记录。


分词


以下代码我就不做详细解释了,可参见《十分钟视频,手把手教你用Python撒情人节狗粮的正确姿势》。

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是:将聊天里会使用到的高频英文、数字加回分词列表,例如233、666、mac、app之类的。


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") #存成文件

其他


1.背景图片的地址,读者要是觉得不好看可自行搜集素材,反正我的直男审美已经被吐槽过N次了。

2.我这里用的字体是汉仪晴空体W,推荐汉仪的官方网站,个人可注册,之后在它的公众号里获得激活码,就可以非商业用途地免费下载字体了。


最后


郑重提醒:该礼物只能作为锦上添花,使用本教程导致情人节变情人劫的,本人概不负责……


读者也可以拿来做跟基友/闺蜜的词云等,做做文本挖掘,看看你们的日常对话高频的是什么,感觉挺有意思的。


* 此文用时02h27m写就,操作用时02h03m,时长统计via timetrack.io

Python爱好者社区历史文章大合集

Python爱好者社区历史文章列表(每周append更新一次)

福利:文末扫码立刻关注公众号,“Python爱好者社区”,开始学习Python课程:

关注后在公众号内回复“课程”即可获取:

0.小编的Python入门视频课程!!!

1.崔老师爬虫实战案例免费学习视频。

2.丘老师数据科学入门指导免费学习视频。

3.陈老师数据分析报告制作免费学习视频。

4.玩转大数据分析!Spark2.X+Python 精华实战课程免费学习视频。

5.丘老师Python网络爬虫实战免费学习视频。


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存