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

水平優先,比較喜歡這塊,程序不夠精簡,若有改進地方,大佬請指正!函數

相關文章
相關標籤/搜索