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

浏览: 2960

作者:竹间为简  

经济学科班,爱生活,爱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操作数据库,办法笨了点,编程大神不要笑我(笑我也没无妨,我有女票)。

以下开始虐狗

提取聊天记录文本

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网络爬虫实战免费学习视频。

image.png

推荐 0
本文由 Python爱好者社区 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册