基于情感词典的python情感分析
近期⽼师给我们安排了⼀个⼤作业,要求根据情感词典对微博语料进⾏情感分析。于是在⽹上狂资料,看相关书籍,终于搞出了这个任务。现在做做笔记,总结⼀下本次的任务,同时也给遇到有同样需求的⼈,提供⼀点帮助。
1、情感分析含义
情感分析指的是对新闻报道、商品评论、电影影评等⽂本信息进⾏观点提取、主题分析、情感挖掘。情感分析常⽤于对某⼀篇新闻报道积极消极分析、淘宝商品评论情感打分、股评情感分析、电影评论情感挖掘。情感分析的内容包括:情感的持有者分析、态度持有者分析、态度类型分析(⼀系列类型如喜欢(like),讨厌(hate),珍视(value),渴望(desire)等;或着简单的加权极性如积极(positive),消极(negative)和中性(neutral)并可⽤具体的权重修饰)、态度的范围分析(包含每句话,某⼀段、或者全⽂)。因此,情感分析的⽬的可以分为:初级:⽂章的整体感情是积极/消极的;进阶:对⽂章的态度从1-5打分;⾼级:检测态度的⽬标,持有者和类型。
总的来说,情感分析就是对⽂本信息进⾏情感倾向挖掘。
2、情感挖掘⽅法
情感挖掘⽬前主要使⽤的⽅法是使⽤情感词典,对⽂本进⾏情感词匹配,汇总情感词进⾏评分,最后得到⽂本的情感倾向。本次我主要使⽤了两种⽅法进⾏情感分析。第⼀种:基于BosonNLP情感词典。该情感词典是由波森⾃然语⾔处理公司推出的⼀款已经做好标注的情感词典。词典中对每个情感词进⾏情感值评分,bosanNLP情感词典如下图所⽰:
第⼆种,采⽤的是知⽹推出的情感词典,以及极性表进⾏情感分析。知⽹提供的情感词典共⽤12个⽂件,分为英⽂和中⽂。其中中⽂情感词典包括:评价、情感、主张、程度(正⾯、负⾯)的情感⽂本。本⽂将评价和情感词整合作为情感词典使⽤,程度词表中含有的程度词,按照等级区分,分为:most(最⾼)-very(很、⾮常)-more(更多、更)-ish(稍、⼀点点)-insufficiently(⽋、不)-over(过多、多分、多)六个情感程度词典。
知⽹情感词典下载地址:-
3、原理介绍
3.1 基于BosonNLP情感分析原理
基于BosonNLP情感词典的情感分析较为简单。⾸先,需要对⽂本进⾏分句、分词,本⽂选择的分词⼯具为哈⼯⼤的pyltp。其次,将分词好的列表数据对应BosonNLp词典进⾏逐个匹配,并记录匹配到的情感词分值。最后,统计计算分值总和,如果分值⼤于0,表⽰情感倾向为积极的;如果⼩于0,则表⽰情
感倾向为消极的。原理框图如下:
3.2 基于BosonNLP情感分析代码:
# -*- coding:utf-8 -*-
import pandas as pd
import jieba
#基于波森情感词典计算情感值
def getscore(text):
df = pd.read_table(r"BosonNLP_dict\BosonNLP_", sep="", names=['key', 'score'])
key = df['key'].list()
score = df['score'].list()
# jieba分词
segs = jieba.lcut(text,cut_all = False) #返回list
# 计算得分
score_list = [score[key.index(x)] for x in segs if(x in key)]
return sum(score_list)
#读取⽂件
def read_txt(filename):
with open(filename,'r',encoding='utf-8')as f:
txt = f.read()
return txt
#写⼊⽂件
def write_data(filename,data):
with open(filename,'a',encoding='utf-8')as f:
f.write(data)
if__name__=='__main__':
text = read_txt('test_data\微博.txt')
lists  = text.split('\n')
# al_senti = ['⽆','积极','消极','消极','中性','消极','积极','消极','积极','积极','积极',
#            '⽆','积极','积极','中性','积极','消极','积极','消极','积极','消极','积极',
#            '⽆','中性','消极','中性','消极','积极','消极','消极','消极','消极','积极'
#            ]
al_senti = read_txt(r'test_data\⼈⼯情感标注.txt').split('\n')
i = 0
for list in lists:
if list  != '':
# print(list)
sentiments = round(getscore(list),2)
#情感值为正数,表⽰积极;为负数表⽰消极
print(list)
print("情感值:",sentiments)
print('⼈⼯标注情感倾向:'+al_senti[i])
if sentiments > 0:
print("机器标注情感倾向:积极\n")
s = "机器判断情感倾向:积极\n"
else:
print('机器标注情感倾向:消极\n')
s = "机器判断情感倾向:消极"+'\n'
sentiment = '情感值:'+str(sentiments)+'\n'
al_sentiment= '⼈⼯标注情感倾向:'+al_senti[i]+'\n'
#⽂件写⼊
filename = 'result_data\BosonNLP情感分析结果.txt'
write_data(filename,'情感分析⽂本:')
write_data(filename,list+'\n') #写⼊待处理⽂本
write_data(filename,sentiment) #写⼊情感值
write_data(filename,al_sentiment) #写⼊机器判断情感倾向
write_data(filename,s+'\n') #写⼊⼈⼯标注情感
i = i+1
相关⽂件:
BosonNLp情感词典下载地址:
微博语料:链接:pan.baidu/s/1Pskzw7bg9qTnXD_QKF-4sg  提取码:15bu
输出结果:
3.3 基于知⽹情感词典的情感挖掘原理
基于知⽹情感词典的情感分析原理分为以下⼏步:
1、⾸先,需要对⽂本分句,分句,得到分词分句后的⽂本语料,并将结果与哈⼯⼤的停⽤词表⽐对,去除停⽤词;
2、其次,对每⼀句话进⾏情感分析,分析的⽅法主要为:判断这段话中的情感词数⽬,含有积极词,则积极词数⽬加1,含有消极词,则消极词数⽬加1。并且再统计的过程中还需要判断该情感词前⾯是否存在程度副词,如果存在,则需要根据程度副词的种类赋予不同的权重,乘以情感词数。如果句尾存在?!等符号,则情感词数⽬增加⼀定值,因为!与?这类的标点往往表⽰情感情绪的加强,因此需要进⾏⼀定处理。
3、接着统计计算整段话的情感值(积极词值-消极词值),得到该段⽂本的情感倾向。
4、最后,统计每⼀段的情感值,相加得到⽂章的情感值。
整体流程框图如下:
3.4 基于知⽹情感词典的情感分析代码:
import pyltp
from pyltp import Segmentor
from pyltp import SentenceSplitter
from pyltp import Postagger
import numpy as np
#读取⽂件,⽂件读取函数
def read_file(filename):
with  open(filename, 'r',encoding='utf-8')as f:
text = f.read()
#返回list类型数据
text = text.split('\n')
return text
#将数据写⼊⽂件中python round函数怎么使用
def write_data(filename,data):
with open(filename,'a',encoding='utf-8')as f:
f.write(str(data))
#⽂本分句
def cut_sentence(text):
sentences = SentenceSplitter.split(text)
sentence_list = [ w for w in sentences]
return sentence_list
#⽂本分词
def tokenize(sentence):
#加载模型
segmentor = Segmentor()  # 初始化实例
# 加载模型
segmentor.load(r'E:\tool\python\Lib\site-packages\pyltp-0.2.1.dist-info\ltp_del') # 产⽣分词,segment分词函数
words = segmentor.segment(sentence)
words = list(words)
# 释放模型
return words
#词性标注
def postagger(words):
# 初始化实例
postagger = Postagger()
# 加载模型
postagger.load(r'E:\tool\python\Lib\site-packages\pyltp-0.2.1.dist-info\ltp_del') # 词性标注
postags = postagger.postag(words)
# 释放模型
#返回list
postags = [i for i in postags]
return postags
# 分词,词性标注,词和词性构成⼀个元组
def intergrad_word(words,postags):
#拉链算法,两两匹配
pos_list = zip(words,postags)
pos_list = [ w for w in pos_list]
return pos_list
#去停⽤词函数
def del_stopwords(words):
# 读取停⽤词表
stopwords = read_file(r"test_")
# 去除停⽤词后的句⼦
new_words = []
for word in words:
if word not in stopwords:
new_words.append(word)
return new_words
# 获取六种权值的词,根据要求返回list,这个函数是为了配合Django的views下的函数使⽤
def weighted_value(request):
result_dict = []
if request == "one":
result_dict = read_file(r"E:\学习笔记\NLP学习\NLP code\情感分析3\degree_")
elif request == "two":
result_dict = read_file(r"E:\学习笔记\NLP学习\NLP code\情感分析3\degree_")
elif request == "three":
result_dict = read_file(r"E:\学习笔记\NLP学习\NLP code\情感分析3\degree_")
elif request == "four":
result_dict = read_file(r"E:\学习笔记\NLP学习\NLP code\情感分析3\degree_")
elif request == "five":
result_dict = read_file(r"E:\学习笔记\NLP学习\NLP code\情感分析3\degree_") elif request == "six":
result_dict = read_file(r"E:\学习笔记\NLP学习\NLP code\情感分析3\degree_")
elif request == 'posdict':
result_dict = read_file(r"E:\学习笔记\NLP学习\NLP code\情感分析3\emotion_dict\pos_") elif request == 'negdict':
result_dict = read_file(r"E:\学习笔记\NLP学习\NLP code\情感分析3\emotion_dict\neg_") else:
pass
return result_dict
print("reading sentiment dict .......")
#读取情感词典
posdict = weighted_value('posdict')
negdict = weighted_value('negdict')
# 读取程度副词词典
# 权值为2
mostdict = weighted_value('one')
# 权值为1.75
verydict = weighted_value('two')
# 权值为1.50
moredict = weighted_value('three')
# 权值为1.25
ishdict = weighted_value('four')
# 权值为0.25
insufficientdict = weighted_value('five')
# 权值为-1
inversedict = weighted_value('six')
#程度副词处理,对不同的程度副词给予不同的权重
def match_adverb(word,sentiment_value):
#最⾼级权重为
if word in mostdict:
sentiment_value *= 8
#⽐较级权重
elif word in verydict:
sentiment_value *= 6
#⽐较级权重
elif word in moredict:
sentiment_value *= 4
#轻微程度词权重
elif word in ishdict:
sentiment_value *= 2
#相对程度词权重
elif word in insufficientdict:
sentiment_value *= 0.5
#否定词权重
elif word in inversedict:
sentiment_value *= -1
else:
sentiment_value *= 1
return sentiment_value
#对每⼀条微博打分
def single_sentiment_score(text_sent):
sentiment_scores = []
#对单条微博分句
sentences = cut_sentence(text_sent)
for sent in sentences:
#查看分句结果
# print('分句:',sent)
#分词
words = tokenize(sent)
seg_words = del_stopwords(words)
#i,s 记录情感词和程度词出现的位置
i = 0  #记录扫描到的词位⼦
s = 0  #记录情感词的位置
poscount = 0 #记录积极情感词数⽬
negcount = 0 #记录消极情感词数⽬