In [1]:
# -*- coding: utf-8 -*-

import pandas as pd
import re
import numpy as np
import jieba

In [2]:
import pymysql

def get_db_data(query_str):
    conn = pymysql.connect(host='127.0.0.1',port=3306,user='analyzer',password='analyzer@tbs2016',database='dp_relation',charset='utf8mb4',cursorclass=pymysql.cursors.DictCursor)
    cur=conn.cursor()
    doc = pd.read_sql_query(query_str, conn)
    doc = pd.DataFrame(doc)
    cur.close()
    conn.close()
    return doc

In [3]:
'''
微博文本过滤
'''

def re_sub(text_l):
    '替换文本中的超链接和多余的空格'
    if isinstance(text_l, str) and (text_l is not None):
        text_s = re.sub('\s+', ' ', text_l)
        text_s = re.sub(' ', ',', text_s)
        text_s = re.sub('#.+?#|\[.+?]|【.+?】', '', text_s)
        text_s = re.sub('https?:[a-zA-Z\\/\\.0-9_]+', '', text_s)
        text_s = re.sub('@.+?[,,::\ )]|@.+?$', '', text_s)
        text_s = re.sub('我在(\\w){0,2}[::](\\w*)', '', text_s)
        text_s = re.sub('\\[(\\w){1,4}\\]', '', text_s)
        text_s = re.sub('&[a-z]+;', '', text_s)
    else:
        text_s = str(text_l)
        text_s = re_sub(text_s)
    return text_s

re_sub_vec = np.vectorize(re_sub) # 函数向量化

In [4]:
data = get_db_data("SELECT * FROM emotion_analyse WHERE project_id=35 AND keyword_id='35_1'")
data.content = re_sub_vec(data.content)

In [5]:
#data = pd.read_excel('/home/jeffmxh/sentiment_result.xlsx')
#data.content = re_sub_vec(data.content)

#data = data.loc[:,['content']]
#data.loc[1:10:]

In [6]:
'''
把每一条评论分割成单独的句子
'''

def sentence_split(content):
    sentence = str(content)
    sentence = re.sub('\u200b', '', sentence)
    result = re.split('。|?|!|\\.|\\?|\\!', sentence)
    return [ele for ele in result if len(ele)>1]

In [7]:
data['content_list'] = data['content'].map(sentence_split)
data.loc[1:2,:]


Out[7]:
id project_id keyword_id content pa pe pd ph pg pb ... happy praise angry sad fear disagreeable surprise emotion polar content_list
1 31344 35 35_1 此用户没有填写评论! 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 None None [此用户没有填写评论]
2 31345 35 35_1 做活动买的,好便宜 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 None None [做活动买的,好便宜]

2 rows × 35 columns


In [13]:
# 用于分词的类

import os
import re
from os import path
import jieba
class jieba4null():
    """
    docstring for parser_word
    deal处理文本,返回词表、词性及依存关系三个值
    """
    def __init__(self,n_core = 16):
        self.rootdir = os.getcwd()
        #self.STOP_WORDS_LIST = self.load_txt('/home/jeffmxh/stopwords_utf8.txt')
        #self.STOP_WORDS_LIST = set([re.sub('\n', '', item) for item in self.STOP_WORDS_LIST])
        jieba.load_userdict('/home/jeffmxh/emotion_user_dict.txt')
        self.n_CORE=n_core
        jieba.enable_parallel(self.n_CORE-1)
    def filter_stop(self,input_text):
        for token in input_text:
            if token not in self.STOP_WORDS_LIST:
                yield token
    def cut_word(self,sent):
        #words = self.filter_stop(jieba.cut(sent, cut_all=False))
        words = jieba.cut(sent, cut_all=False)
        result = list(words)
        return list(filter(lambda x:x!='\u200b', result))
    def cut_sentence(self, sent_list):
        result = []
        for sent in sent_list:
            result.append(list(self.cut_word(sent)))
        return result
    def load_txt(self,file):
        with open(file,'r',encoding = 'utf-8') as f_h:
            res = [line.encode('utf-8', 'ignore').decode('utf-8', 'ignore') for line in f_h]
            return res

In [14]:
seg_word = jieba4null()
data.loc[:,'seg_words'] = data['content_list'].map(seg_word.cut_sentence)
#data

In [15]:
data.loc[:,['content','seg_words']]


Out[15]:
content seg_words
0 很好 [[很, 好]]
1 此用户没有填写评论! [[此, 用户, 没有, 填写, 评论]]
2 做活动买的,好便宜 [[做, 活动, 买, 的, ,, 好, 便宜]]
3 我扫码了是正品不过有一个地方我不太明白,当时客服告诉我是在香港发货可是物流上面显示的是在深圳发货。 [[我, 扫码, 了, 是, 正品, 不过, 有, 一个, 地方, 我, 不, 太, 明白,...
4 还可以 [[还, 可以]]
5 不知道是不是正品,打开箱子盒子是打开着的 [[不, 知道, 是不是, 正品, ,, 打开, 箱子, 盒子, 是, 打开, 着, 的]]
6 收到了,等待使用效果。 [[收到, 了, ,, 等待, 使用, 效果]]
7 发货和快递好慢哈哈,盒子被打开过,估计是海关开的,扫了扫是正品,挺好 [[发货, 和, 快递, 好慢, 哈哈, ,, 盒子, 被, 打开, 过, ,, 估计, 是...
8 很好用 [[很, 好, 用]]
9 好评 [[好评]]
10 很好,还送了赠品?? [[很, 好, ,, 还, 送, 了, 赠品]]
11 扫了一贴,显示正品 [[扫, 了, 一贴, ,, 显示, 正品]]
12 是正品呢。一打开就能闻到蜂蜜的味道,甜甜的。本人严重敏感肌,普通面膜我用几分钟就会干,吸收不... [[是, 正品, 呢], [一, 打开, 就, 能, 闻到, 蜂蜜, 的, 味道, ,, 甜...
13 以前用过感觉还可以,好评吧,但以后不会再买韩货了。 [[以前, 用过, 感觉, 还, 可以, ,, 好评, 吧, ,, 但, 以后, 不会, 再...
14 很满意,特别湿润,验过是正品。 [[很, 满意, ,, 特别, 湿润, ,, 验过, 是, 正品]]
15 刚回来,还没来得及用了,用了再追评吧! [[刚回来, ,, 还, 没, 来得及, 用, 了, ,, 用, 了, 再, 追评, 吧]]
16 正品,非常喜欢,估计是因为过海关的原因,每盒都被拆开了 [[正品, ,, 非常, 喜欢, ,, 估计, 是因为, 过, 海关, 的, 原因, ,, ...
17 好用,已经是第二次购买了 [[好用, ,, 已经, 是, 第二次, 购买, 了]]
18 很好 [[很, 好]]
19 还不错 [[还, 不错]]
20 和我以前买的不一样,而且用后脸痒痒,都红了,假货 [[和, 我, 以前, 买, 的, 不, 一样, ,, 而且, 用后, 脸, 痒痒, ,, ...
21 还可以,比较补水 [[还, 可以, ,, 比较, 补水]]
22 孕妇都可以用应该不错,待追加 [[孕妇, 都, 可以, 用, 应该, 不错, ,, 待, 追加]]
23 还没有用 [[还, 没有, 用]]
24 很好 [[很, 好]]
25 还可以,就等了好久哦 [[还, 可以, ,, 就, 等, 了, 好久, 哦]]
26 替朋友买的不知道好不好 [[替, 朋友, 买, 的, 不, 知道, 好不好]]
27 还没用过,看着不错 [[还, 没用过, ,, 看着, 不错]]
28 怎么说不是密封的还没用,包装一小小快胶带被撕开了 [[怎么, 说, 不是, 密封, 的, 还, 没用, ,, 包装, 一, 小小, 快, 胶带...
29 很棒,就是为什么包装盒都是开封了的 [[很棒, ,, 就是, 为什么, 包装盒, 都, 是, 开封, 了, 的]]
... ... ...
80 还没鉴别真假,希望是真的 [[还, 没, 鉴别, 真假, ,, 希望, 是, 真的]]
81 香港直邮的,送了一片别的牌子的面膜,拆开包装,面膜是被打开了,也没少 [[香港, 直邮, 的, ,, 送, 了, 一片, 别的, 牌子, 的, 面膜, ,, 拆开...
82 特地下了一个软件,是正品 [[特地, 下, 了, 一个, 软件, ,, 是, 正品]]
83 <b></b>收<b></b>到<b></b>了<b></b> [[<, b, >, <, /, b, >, 收, <, b, >, <, /, b, >,...
84 囤货中 [[囤货, 中]]
85 一直期待着呀,敷完水水的,很不错 [[一直, 期待, 着, 呀, ,, 敷, 完水水, 的, ,, 很, 不错]]
86 还未检验是否是正品,不知道是什么原因盒子是开着的,还有赠品,买家态度好棒 [[还, 未, 检验, 是否是, 正品, ,, 不, 知道, 是, 什么, 原因, 盒子, ...
87 之前用过这个面膜首先味道很好闻用完之后挺水润的挺好用的。会回购。 [[之前, 用过, 这个, 面膜, 首先, 味道, 很, 好闻, 用, 完, 之后, 挺, ...
88 效果没有想象中神奇,补水效果一般,蜂蜜味道挺好闻的,总体还是不错的 [[效果, 没有, 想象, 中, 神奇, ,, 补水, 效果, 一般, ,, 蜂蜜, 味道,...
89 不知道是不是正品,先用用再说吧 [[不, 知道, 是不是, 正品, ,, 先用, 用, 再说, 吧]]
90 第一次用这个面膜效果真的很好,太欣喜了! [[第一次, 用, 这个, 面膜, 效果, 真的, 很, 好, ,, 太, 欣喜, 了]]
91 不错,挺好用的。就是刚买就做活动了。 [[不错, ,, 挺好用, 的], [就是, 刚买, 就, 做, 活动, 了]]
92 打开闻了一下,应该是正品 [[打开, 闻, 了, 一下, ,, 应该, 是, 正品]]
93 用过两片了.味道挺好闻的.里面的汁液多多.贴在脸上很服帖.总之感觉还不错吧 [[用过, 两片, 了], [味道, 挺, 好闻, 的], [里面, 的, 汁液, 多多],...
94 看起来挺好。 [[看起来, 挺, 好]]
95 <b></b>此<b></b>用<b></b>户<b></b>没<b></b>有<b></b... [[<, b, >, <, /, b, >, 此, <, b, >, <, /, b, >,...
96 刚到,今天就用了一片,感觉不错,补水效果很好 [[刚到, ,, 今天, 就, 用, 了, 一片, ,, 感觉, 不错, ,, 补水, 效果...
97 非常好用,扫码了,是正品,heygirl很可爱呦 [[非常, 好用, ,, 扫码, 了, ,, 是, 正品, ,, heygirl, 很, 可...
98 是正品,很舒服,真的很舒服 [[是, 正品, ,, 很, 舒服, ,, 真的, 很, 舒服]]
99 扫了,是正品,支持 [[扫, 了, ,, 是, 正品, ,, 支持]]
100 不错 [[不错]]
101 好用 [[好用]]
102 一般般 [[一般般]]
103 这款面膜简直太棒了,超级水润,绝对正版,用完还会再来的^?_?^ [[这, 款, 面膜, 简直, 太棒了, ,, 超级, 水润, ,, 绝对, 正版, ,, ...
104 精华几乎都在面膜纸上,跟皮肤贴合,做完感觉很好 [[精华, 几乎, 都, 在, 面膜, 纸上, ,, 跟, 皮肤, 贴合, ,, 做, 完,...
105 可以 [[可以]]
106 是正品,用着特别舒服 [[是, 正品, ,, 用, 着, 特别, 舒服]]
107 很好很舒服??? [[很, 好, 很, 舒服]]
108 超级棒,heygirl小姐姐简直太可爱啦,还送了礼物,遇到这么贴心的小姐姐生活感觉都变美好了 [[超级, 棒, ,, heygirl, 小姐姐, 简直, 太, 可爱, 啦, ,, 还, ...
109 扫了一下里边每一片,都是一号店和亚马逊的,不知道是不是真的,在脸上用不是很放心呢,先试试 [[扫, 了, 一下, 里边, 每, 一片, ,, 都, 是, 一号, 店, 和, 亚马逊,...

110 rows × 2 columns


In [10]:
import pandas as pd

class polar_classifier():
    '''
    用于对句子列表进行极性分析的类
    '''
    def __init__(self):
        self.pos_list = self.load_txt('/home/jeffmxh/full_pos_dict_sougou.txt')
        self.neg_list = self.load_txt('/home/jeffmxh/full_neg_dict_sougou.txt')
        self.degree_dict = pd.read_excel('/home/jeffmxh/py_sentiment_analyse/degree_dict.xlsx')
        self.deny_dict = ['不', '不是', '没有']
    def load_txt(self,file):
        with open(file,'r',encoding = 'utf-8') as f_h:
            res = [line.encode('utf-8', 'ignore').decode('utf-8', 'ignore') for line in f_h]
            result = [re.sub('\n', '', item) for item in res]
            return result
        
    # 鉴定词汇的情感极性,输入词汇以及正负列表

    def word_polar_classify(self, word, pos_list, neg_list):
        if word in pos_list:
            return 1
        elif word in neg_list:
            return -1
        else:
            return 0

    # 鉴定程度副词,degree:1~6
    
    def word_strength_classify(self, word, degree_dict):
        sub_dict = degree_dict.loc[degree_dict.word==word,:]
        if sub_dict.shape[0]==0:
            return 0
        else:
            return sub_dict.iloc[0,1]

    # 鉴定否定词

    def word_deny_classify(self, word, deny_dict):
        if word in deny_dict:
            return -1
        else:
            return 1
        
    # 分析单个列表词汇
    
    def single_list_classify(self, seg_list):
        sign = 1
        k = 1
        result_list = []
        for i,word in enumerate(seg_list):
            polar_temp = self.word_polar_classify(word, self.pos_list, self.neg_list)
            if polar_temp!=0:
                result_temp = polar_temp * sign * k
                result_list.append(result_temp)
            else:
                sign *= self.word_deny_classify(word, self.deny_dict)
                k += self.word_strength_classify(word, self.degree_dict)
        if len(result_list)==0:
            return 'None'
        else:
            return sum(result_list)
        
    # 分析多个列表词汇
    
    def multi_list_classify(self, big_seg_list):
        res = []
        for seg_list in big_seg_list:
            res.append(self.single_list_classify(seg_list))
        senti_list = [x for x in res if x!='None']
        if len(senti_list)==0:
            return 'None'
        else:
            return sum(senti_list)

In [11]:
worker = polar_classifier()
#worker.multi_list_classify(data.seg_words[40])
data['polar'] = data['seg_words'].map(worker.multi_list_classify)

In [12]:
data = data.drop(['content_list','seg_words'], axis = 1)
data.loc[0:2,:]


Out[12]:
id project_id keyword_id content pa pe pd ph pg pb ... pc happy praise angry sad fear disagreeable surprise emotion polar
0 31216 35 35_1 很好 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 None None
1 31217 35 35_1 此用户没有填写评论! 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 None None
2 31218 35 35_1 做活动买的,好便宜 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 None None

3 rows × 34 columns


In [13]:
data.columns


Out[13]:
Index(['id', 'project_id', 'keyword_id', 'content', 'pa', 'pe', 'pd', 'ph',
       'pg', 'pb', 'pk', 'nz', 'nb', 'nj', 'nh', 'pf', 'ni', 'nc', 'ng', 'ne',
       'nd', 'nn', 'nk', 'nl', 'pc', 'happy', 'praise', 'angry', 'sad', 'fear',
       'disagreeable', 'surprise', 'emotion', 'polar'],
      dtype='object')

In [14]:
data.loc[1:2,:]


Out[14]:
id project_id keyword_id content pa pe pd ph pg pb ... pc happy praise angry sad fear disagreeable surprise emotion polar
1 31217 35 35_1 此用户没有填写评论! 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 None None
2 31218 35 35_1 做活动买的,好便宜 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 None None

2 rows × 34 columns


In [25]:
def update_sql_polar(emotion_result):
    conn = pymysql.connect(host='127.0.0.1',
                            port=3306,
                            user='analyzer',
                            password='analyzer@tbs2016',
                            database='dp_relation',
                            charset='utf8mb4',
                            cursorclass=pymysql.cursors.DictCursor)
    for i in range(emotion_result.shape[0]):
        sql_update = ("UPDATE emotion_analyse SET polar='%s' where id=%d"
                    % (str(emotion_result.polar[i]), emotion_result.id[i]))
        cur = conn.cursor()
        bool_resu = cur.execute(sql_update)
    conn.commit()
    conn.close()

In [12]:
writer = pd.ExcelWriter('emotion_result.xlsx')
data.to_excel(writer, sheet_name='sheet1', encoding='utf-8', index=False)#写入excel
writer.save()