python可视化文本分析(2)—snownlp+jieba分析QQ群成员发言状况

公众号文章连接python

第二个情感分析,主要经过python实现qq群消息分析,分析群成员发言总次数,群成员情绪对比,单个群成员的发言词云情况以及单个同窗的发言情感走势。 用到一下库:api

  • re正则,matplotlib,wordcloud,numpy,jieba分词,snownlp情感分析。
  • 上述库的用法很简单,安装也很简单,因此不须要担忧门槛。

最好结合第一篇或者先看第一篇 详细说一下模块的制做流程:数组

  1. 正则匹配文本内容,第一篇只考虑总计文本的展现,并无考虑到群成员的群体。因此要用字典{}讲学生的qq/邮箱和昵称存一下。还有他的发言记录。这里有个比较重要的是他的昵称多是变得,你的群消息里面展现的是那个时候他的群昵称,,可能从大演说家变成啥啥啥的。因此个人思想就是主要按照qq/邮箱这个点肯定惟一,而昵称只用第一次出现的。文本先相加。
value={}
def analyseinformation(lines):
    qqnow=''#qq或者email当前用户
    for line in lines:
        if line != "\n" and line.strip() != "\n" and line != None and not line.__contains__("撤回了"):
           line = line.replace("[表情]", " ").replace("@全体成员", " ").replace("[表情]", " ").\
                replace("[QQ红包]我发了一个“专享红包”,请使用新版手机QQ查收红。", "").replace("\n", " ").replace("[图片]",'')          
           if pattern.search(line):#匹配到正确的对象
               # print(line)
                if pattern3.search(line):
                    qq1=str(pattern3.search(line).group(3))
                    namenow=str(pattern3.search(line).group(1))
                    if  not qq1 in value.keys():
                         value[qq1]={'name':namenow,'qq':qq1,'text':[]}
                    qqnow=qq1#当前用户发言发生了更改
                elif pattern4.search(line):
                    email=str(pattern4.search(line).group(2))
                    namenow=str(pattern4.search(line).group(1))
                    if  not email in value.keys():
                         value[email]={'name':namenow,'qq': email,'text':[]}
                    qqnow=email
               # print(name)
           elif not qqnow.__eq__(''):#初始化的时候的坑,初始化为'',前几行没用文本直接过滤
                value[qqnow]['text'].append(str(line))
复制代码
  1. 上面就说讲全部有用的信息放到字典value中,可是我想用几个小数组分开存储一些信息。能够稍微处理一下:
time=[]#次数
text=[]#文本
name=[]#姓名
qq=[]#qq或者邮箱提取
def getmotion(values):
    for key in values:
        print(values[key])
        time.append(values[key]['text'].__len__())
        usertxt=''
        for txt in values[key]['text']:
            usertxt+=txt+' '
        text.append(usertxt)
        name.append(values[key]['name'])
        qq.append(key)
复制代码
  1. 剩下就能够开始完成本身想要展现的部分了。首先,我想查看这段时间每一个人到底发言多少次。由于matplotlib图形显示不了太多,我显示部分(能够本身更改,只不过是效果问题),你还能够自定义排序完成排序而后再展现:
#展现各个同窗的发言次数
def getspeaktimeall(time,name):
    Xi = np.array(time[20:50])#根据本身展现的须要需改范围,咱们群人数太多
    Yi = np.array(name[20:50])
    x=np.arange(0,30,1)
    width=0.6
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
    plt.figure(figsize=(8, 6))  ##指定图像比例: 8:6
    plt.barh(x , Xi, width, color='SkyBlue',alpha=0.8)
    plt.xlabel("time")
    plt.ylabel("name")
    for a,b,c in zip(Xi,Yi,x):
        print(a,b,c)
        plt.text(a+10,c-0.4,'%d'%int(a),ha='center',va='bottom')
    plt.yticks(x,Yi)
   # plt.legend()
    plt.show()
    plt.close()
复制代码
  1. 我还想看到全部人的发言情感总的比较。那么我就将全部同窗的发言成为一个大的字符串,而后用snownlp去分析,snownlp的api很简单。 s=SnowNLP(text) print(s.sentiments)就出来了,这部分的坑点是标签的展现我之前记录过能够结合着看,就不详述了。这部分详细代码为:
def getemotionall(time,text,name,qq):
    emotion=[]
    for i in range(0,len(qq)):
        print(name[i],text[i])
        s=SnowNLP(text[i])
        emotion.append(s.sentiments*100)
    print(len(name),len(emotion))
    Xi = np.array(emotion[10:40])
    Yi = np.array(name[10:40])
    x = np.arange(0, 30, 1)
    width = 0.6
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
    plt.figure(figsize=(8, 6))  ##指定图像比例: 8:6
    plt.barh(x, Xi, width, color='red',label='同窗发言总情绪', alpha=0.8)
    plt.xlabel("emotion")
    plt.ylabel("name")
    for a, b, c in zip(Xi, Yi, x):
        print(a, b, c)
        plt.text(a + 2, c - 0.4, '%d' % int(a), ha='center', va='bottom')
    plt.yticks(x, Yi)
    # plt.legend()
    plt.show()
    plt.close()
复制代码
  1. 接下来我想分析的是每一个人的发言词云,这部分第一篇也讲过实现的方式,代码就留在完整贴了。你能够查看你讨厌的人,喜欢的人,或者两我的的聊天记录。看看她关心啥。。嘿嘿🤭。
  2. 我还想看的就是每一个人的情感走向,这个也挺有价值的,你能够分析她或他最近的若干条的情感走势,若是整合最小二乘法预测还能画一条情感预测的走势出来,这里就先不画了。我才用的是折线图,1表明积极,0表明消极,0.5表明中性。由于有的人发言太多,不利于图标展现,我只去了他最近200条记录,没用基于时间,若是有兴趣你还能够把时间整合进来。核心代码为:
def getemotionbyqq(value,qq):
    va=value[qq]['text']
    emotion=[]
    for q in va[len(va)-200:len(va)]:
        s = SnowNLP(q)
        emotion.append(s.sentiments)
        #print(s.sentiments)
    x=np.arange(len(emotion))
    y=np.array(emotion)
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
    plt.figure(figsize=(12, 6))  ##指定图像比例: 8:6
    plt.plot(x,y,label='emotion status')
    plt.xlabel("最近200次发言情绪走势")
    plt.ylabel("0-1表示消极-积极")
    plt.legend()
    plt.show()
复制代码

附上代码和展现:app

import re
from snownlp import SnowNLP
import numpy as np
import matplotlib.pyplot as plt  ##绘图库
from wordcloud import WordCloud
import jieba.analyse
time=[]#次数
text=[]#文本
name=[]#姓名
qq=[]#qq或者邮箱提取
value={}
pattern=re.compile(r'(\d*)-(\d*)-(\d*) .* .*')#匹配 2018-05-05 15:55:40 2班某某(1315426911) 有一个坑点就是2018-05-07 13:48:39 2XXX<xxxx@qq.com>这种格式
#pattern2=re.compile(r'(\d+):(\d+):\d+')#匹配 15:55:40
pattern3=re.compile(r'(\S+)(\()(.*?)(\))')#匹配 2班某某(1315426911)相关内容
pattern4=re.compile(r'(\S+)[<](.*)[>]')
def getemotionbyqq(value,qq):
    va=value[qq]['text']
    emotion=[]
    for q in va[len(va)-200:len(va)]:
        s = SnowNLP(q)
        emotion.append(s.sentiments)
        #print(s.sentiments)
    x=np.arange(len(emotion))
    y=np.array(emotion)
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
    plt.figure(figsize=(12, 6))  ##指定图像比例: 8:6
    plt.plot(x,y,label='emotion status')
    plt.xlabel("最近200次发言情绪走势")
    plt.ylabel("0-1表示消极-积极")
    plt.legend()
    plt.show()
def getstudentcloudbyqq(value,qq):
    va=value[qq]['text']
    text=''
    for q in va:
        text+=q+' '
    print(text)
    ags = jieba.analyse.extract_tags(text, topK=40)
    text=' '.join(ags)
    wc = WordCloud(background_color="white",
                   width=1500, height=1000,
                   min_font_size=40,
                   font_path="simhei.ttf",
                   max_font_size=300,  # 设置字体最大值
                   random_state=40,  # 设置有多少种随机生成状态,即有多少种配色方案
                   )  # 字体这里有个坑,必定要设这个参数。不然会显示一堆小方框wc.font_path="simhei.ttf" # 黑体
    # wc.font_path="simhei.ttf"
    my_wordcloud = wc.generate(text)

    plt.imshow(my_wordcloud)
    plt.axis("off")
    plt.show()
    plt.close()
def getemotionall(time,text,name,qq):
    emotion=[]
    for i in range(0,len(qq)):
        print(name[i],text[i])
        s=SnowNLP(text[i])
        emotion.append(s.sentiments*100)
    print(len(name),len(emotion))
    Xi = np.array(emotion[10:40])
    Yi = np.array(name[10:40])
    x = np.arange(0, 30, 1)
    width = 0.6
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
    plt.figure(figsize=(8, 6))  ##指定图像比例: 8:6
    plt.barh(x, Xi, width, color='red',label='同窗发言总情绪', alpha=0.8)
    plt.xlabel("emotion")
    plt.ylabel("name")
    for a, b, c in zip(Xi, Yi, x):
        print(a, b, c)
        plt.text(a + 2, c - 0.4, '%d' % int(a), ha='center', va='bottom')
    plt.yticks(x, Yi)
    # plt.legend()
    plt.show()
    plt.close()
#展现各个同窗的发言次数
def getspeaktimeall(time,name):
    Xi = np.array(time[20:50])#根据本身展现的须要需改范围,咱们群人数太多
    Yi = np.array(name[20:50])
    x=np.arange(0,30,1)
    width=0.6
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
    plt.figure(figsize=(8, 6))  ##指定图像比例: 8:6
    plt.barh(x , Xi, width, color='SkyBlue',alpha=0.8)
    plt.xlabel("time")
    plt.ylabel("name")
    for a,b,c in zip(Xi,Yi,x):
        print(a,b,c)
        plt.text(a+10,c-0.4,'%d'%int(a),ha='center',va='bottom')
    plt.yticks(x,Yi)
   # plt.legend()
    plt.show()
    plt.close()

def getmotion(values):
    for key in values:
        print(values[key])
        time.append(values[key]['text'].__len__())
        usertxt=''
        for txt in values[key]['text']:
            usertxt+=txt+' '
        text.append(usertxt)
        name.append(values[key]['name'])
        qq.append(key)
    #getmatplotlibtime(time,text,name,qq)
   # getmatplotlibemotion(time,text,name,qq)
   # print(time)
def analyseinformation(lines):
    qqnow=''#qq或者email当前用户
    for line in lines:
        if line != "\n" and line.strip() != "\n" and line != None and not line.__contains__("撤回了"):
           line = line.replace("[表情]", " ").replace("@全体成员", " ").replace("[表情]", " ").\
                replace("[QQ红包]我发了一个“专享红包”,请使用新版手机QQ查收红。", "").replace("\n", " ").replace("[图片]",'')
           if pattern.search(line):#匹配到正确的对象
               # print(line)
                if pattern3.search(line):
                    qq1=str(pattern3.search(line).group(3))
                    namenow=str(pattern3.search(line).group(1))
                    if  not qq1 in value.keys():
                         value[qq1]={'name':namenow,'qq':qq1,'text':[]}
                    qqnow=qq1#当前用户发言发生了更改
                elif pattern4.search(line):
                    email=str(pattern4.search(line).group(2))
                    namenow=str(pattern4.search(line).group(1))
                    if  not email in value.keys():
                         value[email]={'name':namenow,'qq': email,'text':[]}
                    qqnow=email
               # print(name)
           elif not qqnow.__eq__(''):#初始化的时候的坑,初始化为'',前几行没用文本直接过滤
                value[qqnow]['text'].append(str(line))
               # print(name)
                #print(value[name])
if __name__ == '__main__':
    f = open('E:/text.txt', 'r', encoding='utf-8')  # 要进行分词处理的文本文件 (通通按照utf8文件去处理,免得麻烦)
    lines = f.readlines()
    #执行这个函数获取分析才能解析value{}
    analyseinformation(lines)
    getmotion(value)#这个函数获取一些name[]数组的值
    #核心分析函数:

    getspeaktimeall(time,name)#选定区间的同窗发言次数
    getemotionall(time,text,name,qq)
    getstudentcloudbyqq(value,'694459644')
    getemotionbyqq(value,'694459644')






复制代码
  • 发言的次数(我专挑小的区间为了展现)
    在这里插入图片描述
  • 情绪总的比较(跑的比较慢由于多)
    在这里插入图片描述
  • 某个同窗的发言词云(我偷偷选了发言较多的班长。。)
    在这里插入图片描述
  • 单我的的情感走势(我又偷偷分析了班长的🤭)
    在这里插入图片描述
    能够看到这小子最近几回发言不太良好呢。

其实仍是有遗憾的,由于snownlp训练的是商品评论正负语料,有的地方不必定很准。但愿有机会本身能作一个情绪分析的包。哎,路还很长。dom

水平优先,比较喜欢这块,程序不够精简,若有改进地方,大佬请指正!函数

相关文章
相关标签/搜索