当前位置:   article > 正文

Chapter 15 电商产品评论数据情感分析

Chapter 15 电商产品评论数据情感分析

一、背景和目标

本文对电商平台上的热水器评论进行文本挖掘分析,本次数据挖掘的建模目标如下:

  1. 分析某一品牌热水器的用户情感倾向。
  2. 从评论文本中挖掘出该品牌热水器的优点和不足。
  3. 提炼不同品牌热水器的卖点。

二、方法步骤

  1. 利用爬虫工具——八爪鱼采集器,对京东商城进行热水器评论的数据采集。
  2. 对获取的数据进行基本的处理操作,包括数据预处理、中文分词、停用词过滤等。
  3. 文本评论数据经过处理后,运用多种手段对评论数据进行多方面的分析。
  4. 从对应结果的分析中获取文本评论数据中有价值的内容。

三、过程

3.1 评论数据采集

要分析电商平台热水器的评论数据,需要先对评论数据进行采集,对比多种网络爬虫工具后,发现八爪鱼采集器属于“易用型”,它主要通过模仿用户的网页操作进行数据采集,只需指定数据采集逻辑和可视化采集的数据,即可完成采集规则的制定。因此在此,选择八爪鱼采集器作为网页数据的抓取工具。

3.2 评论预处理

3.21 对象评论抽取

将评论为“美的”的“评论一列抽取”,编码每UTF-8格式。

 

  1. #-*- coding: utf-8 -*-
  2. import pandas as pd
  3. inputfile = '.../data/huizong.csv' #评论汇总文件
  4. outputfile = '.../data/meidi_jd.txt' #评论提取后保存路径
  5. data = pd.read_csv(inputfile, encoding = 'utf-8')
  6. data = data[[u'评论']][data[u'品牌'] == u'美的']
  7. data.to_csv(outputfile, index = False, header = False, encoding = 'utf-8')

 3.22 文本去重

  1. #-*- coding: utf-8 -*-
  2. import pandas as pd
  3. inputfile = '.../data/meidi_jd.txt' #评论文件
  4. outputfile = '.../data/meidi_jd_process_1.txt' #评论处理后保存路径
  5. data = pd.read_csv(inputfile, encoding = 'utf-8', header = None)
  6. l1 = len(data)
  7. data = pd.DataFrame(data[0].unique())
  8. l2 = len(data)
  9. data.to_csv(outputfile, index = False, header = False, encoding = 'utf-8')
  10. print(u'删除了%s条评论。' %(l1 - l2))

3.23 机械压缩去词语

例如:

好用,好用,好用,好用!

变为:好用!

3.24 短句删除 

字数越少,表达的意思越少,要表达相关的意思就必须有相应量的字数,过少字数的评论是没有什么意义的,如“很不错”等,为此将过短的评论文本数据删除,以除去没有意义的评论。

显然,短句删除最重要的环节是保留评论的字数下限的确定,这个没有精确的标准,一般4~8个国际字符都是比较合理的,这里设置下限度为4,即语料小于4个国际字符的则删去。

3.3 文本评论的分词

分词结果的准确性对后续文本挖掘算法有着不可忽视的影响。本文采用python中的中文分词包“jieba”(结巴分词),对TXT文档进行分词。“结巴分词”提供分词、词性标注、未登录词识别,支持用户词典等功能。经相关测试,此系统的分词精度高达97%以上。

3.4 模型构建

3.41 情感倾向性模型介绍

  1. 训练生成词向量
  2. 评论集子集的仍标注与映射
  3. 训练栈式自编码网络

3.42 基于语义网络的评论分析

步骤:

  1. 数据预处理,分词以及对停用词的过滤。
  2. 进行情感倾向性分析,并将评论数据分割成正面(好评)、负面(差评)、中性(中评)3大组。(可用武汉大学开发的免费系统:ROSTCM6 来完成)
  3. 抽取正面(好评)、负面(差评)两组,以进行语义网格的构建与分析。(可用武汉大学开发的免费系统:ROSTCM6 来完成)

3.43 基于LDA模型的主题分析

由于COSTCM6 得到的结果还有评分前缀,所以对开头的评分前缀和空格进行删除。

删除前缀评分代码:

  1. #-*- coding: utf-8 -*-
  2. import pandas as pd
  3. #参数初始化
  4. inputfile1 = '.../data/meidi_jd_process_end_负面情感结果.txt'
  5. inputfile2 = '.../data/meidi_jd_process_end_正面情感结果.txt'
  6. outputfile1 = '.../data/meidi_jd_neg.txt'
  7. outputfile2 = '.../data/meidi_jd_pos.txt'
  8. data1 = pd.read_csv(inputfile1, encoding = 'utf-8', header = None) #读入数据
  9. data2 = pd.read_csv(inputfile2, encoding = 'utf-8', header = None)
  10. data1 = pd.DataFrame(data1[0].str.replace('.*?\d+?\\t ', '')) #用正则表达式修改数据
  11. data2 = pd.DataFrame(data2[0].str.replace('.*?\d+?\\t ', ''))
  12. data1.to_csv(outputfile1, index = False, header = False, encoding = 'utf-8') #保存结果
  13. data2.to_csv(outputfile2, index = False, header = False, encoding = 'utf-8')

分词代码:

  1. #-*- coding: utf-8 -*-
  2. import pandas as pd
  3. import jieba #导入结巴分词,需要自行下载安装
  4. #参数初始化
  5. inputfile1 = '.../data/meidi_jd_neg.txt'
  6. inputfile2 = '.../data/meidi_jd_pos.txt'
  7. outputfile1 = '.../data/meidi_jd_neg_cut.txt'
  8. outputfile2 = '.../data/meidi_jd_pos_cut.txt'
  9. data1 = pd.read_csv(inputfile1, encoding = 'utf-8', header = None) #读入数据
  10. data2 = pd.read_csv(inputfile2, encoding = 'utf-8', header = None)
  11. mycut = lambda s: ' '.join(jieba.cut(s)) #自定义简单分词函数
  12. data1 = data1[0].apply(mycut) #通过“广播”形式分词,加快速度。
  13. data2 = data2[0].apply(mycut)
  14. data1.to_csv(outputfile1, index = False, header = False, encoding = 'utf-8') #保存结果
  15. data2.to_csv(outputfile2, index = False, header = False, encoding = 'utf-8')

LDA代码:

  1. #-*- coding: utf-8 -*-
  2. import pandas as pd
  3. # 修改当前工作路径
  4. import os
  5. print(os.getcwd()) # 查看当前工作路径
  6. os.chdir('D:/demo') # 修改路径
  7. print(os.getcwd()) # 查看当前工作路径
  8. # 修改默认编码
  9. import sys
  10. sys.getdefaultencoding() # 查看当前编码格式
  11. # 报错时(AttributeError: 'module' object has no attribute 'setdefaultencoding')
  12. reload(sys) # 报上面的错时,执行此命令
  13. sys.setdefaultencoding('utf8') # 修改编码格式
  14. #参数初始化
  15. negfile = '.../data/meidi_jd_neg_cut.txt'
  16. posfile = '.../data/meidi_jd_pos_cut.txt'
  17. stoplist = '.../data/stoplist.txt'
  18. neg = pd.read_csv(negfile, encoding = 'utf-8', header = None) #读入数据
  19. pos = pd.read_csv(posfile, encoding = 'utf-8', header = None)
  20. stop = pd.read_csv(stoplist, encoding = 'utf-8', header = None, sep = 'tipdm')
  21. #sep设置分割词,由于csv默认以半角逗号为分割词,而该词恰好在停用词表中,因此会导致读取出错
  22. #所以解决办法是手动设置一个不存在的分割词,如tipdm。
  23. stop = [' ', ''] + list(stop[0]) #Pandas自动过滤了空格符,这里手动添加
  24. neg[1] = neg[0].apply(lambda s: s.split(' ')) #定义一个分割函数,然后用apply广播
  25. neg[2] = neg[1].apply(lambda x: [i for i in x if i not in stop]) #逐词判断是否停用词,思路同上
  26. pos[1] = pos[0].apply(lambda s: s.split(' '))
  27. pos[2] = pos[1].apply(lambda x: [i for i in x if i not in stop])
  28. from gensim import corpora, models
  29. #负面主题分析
  30. neg_dict = corpora.Dictionary(neg[2]) #建立词典
  31. neg_corpus = [neg_dict.doc2bow(i) for i in neg[2]] #建立语料库
  32. neg_lda = models.LdaModel(neg_corpus, num_topics = 3, id2word = neg_dict) #LDA模型训练
  33. for i in range(3):
  34. neg_lda.show_topics()#展示主题
  35. #正面主题分析
  36. pos_dict = corpora.Dictionary(pos[2])
  37. pos_corpus = [pos_dict.doc2bow(i) for i in pos[2]]
  38. pos_lda = models.LdaModel(pos_corpus, num_topics = 3, id2word = pos_dict)
  39. for i in range(3):
  40. pos_lda.show_topics()#展示主题

结果展示:

  1. neg_lda.show_topics()#展示正面主题
  2. Out[48]:
  3. [(0,
  4. '0.029*"加热" + 0.029*"不错" + 0.021*"热水器" + 0.013*"速度" + 0.011*"京东" + 0.010*"好" + 0.010*"买" + 0.007*"慢" + 0.006*"安装" + 0.006*"有点"'),
  5. (1,
  6. '0.057*"安装" + 0.020*"热水器" + 0.016*"师傅" + 0.015*"不错" + 0.015*"美的" + 0.013*"好" + 0.011*"买" + 0.011*"问题" + 0.010*"东西" + 0.008*"京东"'),
  7. (2,
  8. '0.040*"安装" + 0.028*"买" + 0.022*"知道" + 0.015*"好" + 0.010*"师傅" + 0.009*"有点" + 0.008*"热水器" + 0.008*"安装费" + 0.008*"一个" + 0.008*"n"')]
  9. pos_lda.show_topics()#展示负面主题
  10. Out[49]:
  11. [(0,
  12. '0.038*"好" + 0.035*"加热" + 0.020*"方便" + 0.017*"很快" + 0.017*"不错" + 0.016*"有点" + 0.016*"好用" + 0.014*"保温" + 0.011*"热水" + 0.011*"使用"'),
  13. (1,
  14. '0.057*"安装" + 0.022*"买" + 0.017*"师傅" + 0.016*"美的" + 0.014*"热水器" + 0.014*"一个" + 0.011*"安装费" + 0.008*"n" + 0.008*"材料" + 0.008*"售后"'),
  15. (2,
  16. '0.098*"不错" + 0.090*"好" + 0.042*"安装" + 0.023*"送货" + 0.022*"东西" + 0.021*"买" + 0.018*"热水器" + 0.017*"挺" + 0.017*"京东" + 0.015*"服务"')]

 经过LDA主题分析后,评论文本被聚成3个主题,每个主题下生成10个最有可能出现的词语及相应的概率。

 

心得体会:

1、爬取数据的工具还有其他,经检验,“后裔采集器”个人完全免费,且速度相对较快(据说八爪鱼1分钟10条),且还比较好用,建议使用。

2、ROSTCM6 中,以下文件均需要(不能删除,都是软件的一部分):

3、jieba 分词的3种:

1) 精确模式:试图将语句最精确的切分,不存在冗余数据,适合做文本分析

  1. seg_list = jieba.cut("我来到北京清华大学", cut_all=False)
  2. print("【精确模式】: " + "/ ".join(seg_list))
  3. 或者:
  4. seg_list = jieba.cut("我来到北京清华大学") # 默认是精确模式
  5. print("【精确模式】: " + "/ ".join(seg_list))
  6. 输出:
  7. 【精确模式】: 我/ 来到/ 北京/ 清华大学

 

2) 全模式:将语句中所有可能是词的词语都切分出来,速度很快,但是存在冗余数据

  1. seg_list = jieba.cut("我来到北京清华大学", cut_all=True) # 全模式
  2. 输出:
  3. 【全模式】: 我/ 来到/ 北京/ 清华/ 清华大学/ 华大/ 大学

 

3) 搜索引擎模式:在精确模式的基础上,对长词再次进行切分

  1. seg_list = jieba.cut_for_search("小明硕士毕业于中国科学院计算所") # 搜索引擎模式
  2. 输出:
  3. 【搜索引擎模式】: 小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 计算所

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/819310
推荐阅读
相关标签
  

闽ICP备14008679号