您现在的位置是:首页 > 技术教程 正文

【情感提取+情感计算+词频统计】python情感分析

admin 阅读: 2024-03-23
后台-插件-广告管理-内容页头部广告(手机)

目录

1、情感分析介绍

2、基于大连理工情感词汇方法

2.1加载大连理工情感词典,程度副词典,否定词典,停用词典

2.2译文断章切句

2.3提取情感词并计算情感值

2.4统计词频

2.5调用实现



1、情感分析介绍

情感分析是一种自然语言处理技术,旨在识别文本中的情感并将其分类为积极、消极或中性。它通过使用机器学习算法和自然语言处理技术来自动分析文本中的情感,从而帮助人们更好地理解文本的情感含义。

本文以某译本new_deepl_translated.txt为分析对象,通过对译文断章切句,进而对每一个句子情感词提取、情感值计算,以及词频统计,最后保存为excel文件。

new_deepl_translated.txt部分内容如下:

情感值计算结果:

词频统计结果:

2、基于大连理工情感词汇方法

2.1加载大连理工情感词典,程度副词典,否定词典,停用词典

各词典大家可以从网上进行下载,顶部我放了一个资源包可以直接拿来用。

定义一个类sa,用于加载情感词典、程度副词典、否定词典、停用词典,以及分词和去除停用词。针对大连理工情感词典,我只需要加载词语、情感分类、强度、极性这4列内容。

  1. class sa:
  2. # 加载情感词典、程度副词典、否定词典、停用词典
  3. def __init__(self, senti_dict_path, degree_dict_path, not_dict_path, stopword_path):
  4. self.senti_dict = self.load_dict(senti_dict_path)
  5. self.degree_dict = self.load_degree_dict(degree_dict_path)
  6. self.not_dict = self.load_not_dict(not_dict_path)
  7. self.stopwords = self.load_stopwords(stopword_path)
  8. # 加载情感词典
  9. def load_dict(self, path):
  10. with open(path, 'r', encoding='utf-8') as f:
  11. lines = f.readlines()
  12. word_dict = {}
  13. for line in lines:
  14. items = line.strip().split('\t')
  15. if len(items) >= 7:
  16. word = items[0] #情词
  17. emotion = items[4] #情词类别
  18. strength = int(items[5]) #情词强度
  19. polarity = int(items[6]) #情词极性
  20. word_dict[word] = {'emotion': emotion, 'strength': strength, 'polarity': polarity}
  21. return word_dict
  22. # 加载程度副词词典
  23. def load_degree_dict(self, path):
  24. with open(path, 'r', encoding='utf-8') as f:
  25. lines = f.readlines()
  26. degree_dict = {}
  27. for line in lines:
  28. items = line.strip().split('\t')
  29. if len(items) >= 2:
  30. degree_word = items[0] #副词
  31. degree_value = float(items[1]) #副词权值
  32. degree_dict[degree_word] = degree_value
  33. return degree_dict
  34. # 加载否定词词典
  35. def load_not_dict(self, path):
  36. with open(path, 'r', encoding='utf-8') as f:
  37. lines = f.readlines()
  38. not_dict = {}
  39. for line in lines:
  40. items = line.strip().split('\t')
  41. if len(items) >= 1:
  42. not_word = items[0] #否定词
  43. not_dict[not_word] = True
  44. return not_dict
  45. # 加载停用词表
  46. def load_stopwords(self, path):
  47. with open(path, 'r', encoding='utf-8') as f:
  48. stopwords = [line.strip() for line in f.readlines()]
  49. return stopwords
  50. # 分词
  51. def cut_words(self, text):
  52. words = jieba.cut(text)
  53. return [word for word in words]
  54. # 去除停用词
  55. def remove_stopword(self, words):
  56. return [word for word in words if word not in self.stopwords]

2.2译文断章切句

定义一个SplitFile方法对译文进行分章,然后定义normal_cut_sentence方法对译文进行分句。

  1. # 断章 将一个txt文件的内容,按照第几章进行分割 section
  2. def SplitFile(filename):
  3. f=open(filename, 'r', encoding="utf-8")
  4. # 获取文件每一行
  5. lines = f.readlines()
  6. zhang = ""
  7. zhangji = []
  8. i = 0
  9. for line in lines:
  10. strh = line[0:6] # 取一行前5个字
  11. if ("第" in strh and "章" in strh):
  12. #print (strh)
  13. if (i>0):
  14. zhangji.append([zhang])
  15. zhang = ""
  16. zhang += line
  17. i += 1
  18. zhangji.append([zhang]) #最后一章
  19. #print (章集)
  20. print (filename,"章节数 = ",len(zhangji))
  21. return zhangji
  22. #切句 将文本切句,换回句列表
  23. def normal_cut_sentence(text):
  24. text = re.sub('([。!?\?])([^’”")])',r'\1\n\2',text)#普通断句符号且后面没有引号
  25. #text = re.sub('(\.{6})([^’”])',r'\1\n\2',text)#英文省略号且后面没有引号
  26. text = re.sub('(\…{2})([^’”])',r'\1\n\2',text)#中文省略号且后面没有引号
  27. text = re.sub('([.。!?\?\.{6}\…{2}][’”"])([^’”"])',r'\1\n\2',text)#断句号+引号且后面没有引号
  28. text = re.sub(r"\n\n",r'\n',text) #删除多余空行
  29. text = re.sub(r"\n\n",r'\n',text) #删除多余空行
  30. text = re.sub(r"\n\n",r'\n',text) #删除多余空行
  31. text = re.sub(r"\n\n",r'\n',text) #删除多余空行
  32. text = text.rstrip("\r\n") # 去掉段尾的\n,然后
  33. return text.split("\n")

2.3提取情感词并计算情感值

利用jieba包进行分词后,去除停用词,然后在大连理工情感词汇中查找每一个词汇,依次判断词语是否是情感词,提取情感种类与分值。

情感值计算公式:

其中,大连理工情感词典各情感分类规则如下:

  1. #提取情感词和计算情感值
  2. class ScoreAnalysis:
  3. # 初始化
  4. def __init__(self, senti_dict_path, degree_dict_path, not_dict_path, stopword_path):
  5. self.sa = sa(senti_dict_path, degree_dict_path, not_dict_path, stopword_path)
  6. self.score_class = {'好': 0, '乐': 1, '怒': 2, '哀': 3, '惧': 4, '恶': 5, '惊': 6, '思': 7} #将情感分为8大类
  7. # 查找情感词
  8. def findword(self, text):
  9. Eword_list = []
  10. word_loc = []
  11. for i in range(0, len(text)):
  12. if text[i] in self.sa.senti_dict.keys():
  13. word = Word(text[i], self.sa.senti_dict[text[i]])
  14. Eword_list.append(word)
  15. word_loc.append(i)
  16. return Eword_list, word_loc
  17. #计算情感得分
  18. def get8score(self, text):
  19. Eword_list, word_loc = self.findword(text) ##查找文本中包含哪些情感词
  20. # 8大类找对应感情大类的词语,分别统计分数= 词极性*词权重
  21. result = []
  22. for key in self.score_class.keys(): #区分8大类
  23. not_word = []
  24. degree_word = []
  25. score = 0
  26. intensity = 1
  27. score_words = []
  28. degree_word_pos = -1
  29. not_word_pos = -1
  30. for j in range(0,len(Eword_list)): #遍历text每个词
  31. word = Eword_list[j]
  32. word_score = 0
  33. if (key == word.class_value): #判断情感词属于哪个大类
  34. score_words.append(word.word)
  35. #扫描情感词前面4个词内的程度副词和否定词
  36. not_v = 1
  37. degree = 1
  38. not_word = []
  39. degree_word = []
  40. degree_word_pos = -1
  41. not_word_pos = -1
  42. star = word_loc[j]-4
  43. if star < 0:
  44. star = 0
  45. for i in range(star, word_loc[j]-1):
  46. if text[i] in self.sa.degree_dict.keys(): #扫描程度副词
  47. degree_word.append(text[i])
  48. degree *= self.sa.degree_dict[text[i]]
  49. degree_word_pos = i
  50. for i in range(star, word_loc[j]-1):
  51. if text[i] in self.sa.not_dict.keys(): #扫描否定词
  52. not_word.append(text[i])
  53. not_v *= -1
  54. not_word_pos = i
  55. if not_word_pos > -1 and degree_word_pos > -1:
  56. if not_word_pos < degree_word_pos: #否定词在前: "不太高兴"
  57. degree *= 0.5
  58. else: #否定词在后 "太不高兴"
  59. degree *= 2
  60. word_score = word.value['polarity'] * not_v * degree
  61. word_score = float(word_score)
  62. #print(word_score)
  63. if word_score > score and word_score > 0:
  64. score = word_score
  65. if word_score < score and word_score < 0:
  66. score = word_score
  67. # 限定取值范围
  68. if score > 9 :
  69. score = 9
  70. if score < -9 :
  71. score = -9
  72. result.append([key, score, score_words, not_word, degree_word])
  73. return result
  74. #对22小类合并为8大类
  75. class Word:
  76. # 初始化
  77. def __init__(self, word, value):
  78. self.word = word
  79. self.value = value
  80. self.class_value = self.get_class_value()
  81. # 获取情感词的大类
  82. def get_class_value(self):
  83. emotion = self.value['emotion']
  84. if emotion in ['PD', 'PH', 'PG', 'PB', 'PK']:
  85. return '好'
  86. elif emotion in ['PA', 'PE']:
  87. return '乐'
  88. elif emotion == 'NA':
  89. return '怒'
  90. elif emotion in ['NB', 'NJ', 'NH','PF']:
  91. return '哀'
  92. elif emotion in ['NI', 'NC', 'NG']:
  93. return '惧'
  94. elif emotion in ['NE', 'ND', 'NN', 'NK', 'NL']:
  95. return '恶'
  96. elif emotion == 'PC':
  97. return '惊'
  98. elif emotion == 'NF':
  99. return '思'
  100. else:
  101. return 'none'

2.4统计词频

定义"添加词频"方法,向词频列表中添加词汇,如果词汇已存在,则将其频次加1,否则将其添加到列表末尾。

  1. def 添加词频(word, freq_list):
  2. """
  3. 参数:
  4. word -- 待添加的词汇
  5. freq_list -- 词频列表
  6. 返回值:
  7. """
  8. word_str = ','.join(map(str.strip, word)).strip('[]\'\"') # 将词汇转换为字符串并去除引号和方括号
  9. # 将逗号分隔的字符串转换为词汇列表
  10. word_list = word_str.split(',')
  11. for w in word_list:
  12. added = False
  13. for i in range(len(freq_list)):
  14. if freq_list[i][0] == w:
  15. freq_list[i][1] += 1
  16. added = True
  17. break
  18. if not added:
  19. freq_list.append([w, 1])

2.5调用实现

  1. #导入相关包
  2. import re
  3. import os
  4. import time
  5. import pandas as pd
  6. import jieba
  7. #传入词典
  8. senti_dict_path = 'D:/emotion_project/origin/tici/大连理工情感词汇.txt'
  9. degree_dict_path = 'D:/emotion_project/origin/tici/副词赋值.txt'
  10. not_dict_path = 'D:/emotion_project/origin/tici/否定词.txt'
  11. stopword_path = 'D:/emotion_project/origin/tici/cn_stopwords.txt'
  12. #加载词典实例化对象sa类
  13. sa_obj = sa(senti_dict_path, degree_dict_path, not_dict_path, stopword_path)
  14. #计算情值实例化对象ScoreAnalysis类
  15. sa = ScoreAnalysis(senti_dict_path, degree_dict_path, not_dict_path, stopword_path)
  16. #**************************************************************************
  17. #分析deepl机器翻译译本每句8种情感值,生成情感表格、词频表格
  18. machine_trans = [ "deepl"]
  19. f_deepl = "new_deepl_translated.txt" #文本路径
  20. files = [f_deepl]
  21. 情类 = ['好','乐','怒','哀','惧','恶','惊','思']
  22. 表头 = ["原句","正面","负面","好","好词","乐","乐词","怒","怒词","哀","哀词","惧","惧词","恶","恶词","惊", "惊词","思","思词"]
  23. 情感乐 = [[0]*5]*64
  24. 篇号 = 0
  25. 章号 = 0
  26. 行号 = 0
  27. #**************************************************************************
  28. 开始时间 = time.time()
  29. forin files[0:]:#不含后边界 共5
  30. #情感值统计表结果路径
  31. writer = pd.ExcelWriter("D:/emotion_project/" + machine_trans[篇号]+'.xlsx')
  32. #词频统计表结果路径
  33. 词频表格 = pd.ExcelWriter("D:/emotion_project/" + machine_trans[篇号]+'词频表.xlsx')
  34. 正面词频 = []
  35. 负面词频 = []
  36. 八情词频 = [[] for i in range(8)]
  37. 章号 = 0
  38. 章集 = SplitFile(篇) #调用-断章-方法
  39. forin 章集[0:]: #共64
  40. 章情词频 = []
  41. 章情词集 = ""
  42. 句集 = normal_cut_sentence( 章[0] ) # 调用-分句-方法
  43. 章分析 = []
  44. forin 句集:
  45. words = sa_obj.cut_words(句) # 分词
  46. words_ = sa_obj.remove_stopword(words) #去除停用词
  47. 八情 = sa.get8score(words_) #提取情感词和计算情感值
  48. #数据处理
  49. 正面 = 0
  50. 负面 = 0
  51. forin 八情:
  52. if 情[1] > 0 :
  53. 正面 += 情[1]
  54. else:
  55. 负面 += 情[1]
  56. #添加表格行数据
  57. = []
  58. 行.append(句)
  59. 行.append(正面)
  60. 行.append(负面)
  61. forin 八情:
  62. 行.append(情[1]) #情感值
  63. 行.append(情[2]) #情感词
  64. print(行)
  65. 章分析.append(行)
  66. #*******************************词频统计*************************************
  67. forin 八情[0:2]: #0,1
  68. 添加词频( 情[2], 正面词频 )
  69. forin 八情[6:8]: #6,7
  70. 添加词频( 情[2], 正面词频 )
  71. forin 八情[2:6]: #2,3,4,5
  72. 添加词频( 情[2], 负面词频 )
  73. i = 0
  74. forin 八情:
  75. if len(情[2]) > 0:
  76. 添加词频(情[2], 章情词频 )
  77. 添加词频(情[2], 八情词频[i] )
  78. i +=1
  79. #print(章情词频)
  80. 第几章 = '第'+str(章号+1) +'章'
  81. df = pd.DataFrame(章情词频, columns = ['章情词','频'] )
  82. df.sort_values(by="频",ascending = False, inplace = True) #按词频降序排列
  83. df.to_excel( 词频表格, 第几章 ,index=False )
  84. #**************************************************************************
  85. df = pd.DataFrame(章分析, columns = 表头 )
  86. df.to_excel( writer, 第几章 ,index=False )
  87. 章号 += 1
  88. df = pd.DataFrame(正面词频, columns = ['正面词','频'] )
  89. df.sort_values(by="频",ascending = False, inplace = True) #按词频降序排列
  90. df.to_excel( 词频表格, '正面词频' ,index=False )
  91. df = pd.DataFrame(负面词频, columns = ['负面词','频'] )
  92. df.sort_values(by="频",ascending = False, inplace = True) #按词频降序排列
  93. df.to_excel( 词频表格, '负面词频' ,index=False )
  94. for i in range(8):
  95. df = pd.DataFrame(八情词频[i], columns = [情类[i]+'词','频'] )
  96. df.sort_values(by="频",ascending = False, inplace = True) #按词频降序排列
  97. df.to_excel( 词频表格, 情类[i]+'词频' ,index=False )
  98. 词频表格.save()
  99. writer.save()
  100. 篇号 += 1
  101. 结束时间 = time.time()
  102. print("耗时",结束时间-开始时间,"秒")

运行结果:

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索