河南南阳收割机被堵事件:官员缺德,祸患无穷

极目新闻领导公开“记者毕节采访被打”细节:他们打人后擦去指纹

突发!员工跳楼!只拿低保工资!央企设计院集体罢工!

退休后的温家宝

突发!北京某院集体罢工!

生成图片,分享到微信朋友圈

自由微信安卓APP发布,立即下载! | 提交文章网址
查看原文

“王牌冤家”:评论爬虫及情感分析(SnowNLP)

胡萝卜酱 DataGo数据狗 2022-07-01

李荣浩上周发的《耳朵》专辑,你萌听了吗?小编真的超级喜欢“王牌冤家”这首歌,在新说唱听了李老师的那几句就一直念念不忘,这一周可是一直单曲循环中。恰好前两天看了SnowNLP的一点东西,所以,这一次基于这首歌的评论,来做个非常easy的情感分析。文本信息是选取的网易云音乐下的评论,所以本文是爬虫+分析。

爬虫

网易云音乐上万首hiphop歌曲解析rapper们的最爱(爬虫篇)一文中,我们基于selenium爬取了歌单,歌曲和歌词的信息,本来在评论的爬取也可以选择selenium的方式,但是,小编上网一搜,就找到评论的API,这可就非常简单了。

Step 1:在网页打开需要爬取歌曲的界面:

这个歌曲ID非常重要,而,目前,我们仅需要这一个信息就OK了。

Step 2:上API:

http://music.163.com/api/v1/resource/comments/R_SO_4_862129612?limit=20&offset=0

API其实是

http://music.163.com/api/v1/resource/comments/R_SO_4_歌曲ID?limit=每页展示评论数量&offset=(页数-1)*20.

是不是对于API下的代码有点看不懂,没关系,你可以把这些代码粘贴到一个json解码网站,比如说

这么是不是自己想要爬取的信息更直观了。

Step 3:上代码

1import requests
2import json
3import time
4import random
5import pandas as pd
6
7#下载第一页数据
8def get_one_page(url):
9    headers = {
10    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36'
11    }
12    response = requests.get(url,headers=headers)
13    if response.status_code == 200:  #页面正常响应
14        return response.text # 返回页面源代码
15    return None
16
17
18commentId=[]
19nickname=[]
20userId=[]
21content=[]
22likedCount=[]
23
24#解析第一页数据
25def parse_ono_page(html):
26    data = json.loads(html)['comments'#评论以json形式存储,故以json形式截取
27    for item in data:
28        commentId.append(item['commentId']),#评论id
29        nickname.append(item['user']['nickname']),#评论用户的昵称
30        userId.append(item['user']['userId']),#评论用户的id
31        content.append(item['content']),#评论内容
32        likedCount.append(item['likedCount'])#点赞数
33
34
35#保存数据到文本文档
36def save_to_txt():
37    for i in range(1755):
38        url='http://music.163.com/api/v1/resource/comments/R_SO_4_862129612?limit=20&offset=' + str(20*(i-1))
39        html = get_one_page(url)
40        print('正在保存第%d页.'% i)
41        parse_ono_page(html)
42        time.sleep(5 + float(random.randint(1,100)) /20)             
43if __name__ =='__main__':
44    save_to_txt()
45wangpai = {'commentId': commentId, 'nickname': nickname, 'userId': userId, 'content': content, 'likedCount':likedCount}
46wangpai = pd.DataFrame(wangpai, columns=['commentId''nickname''userId''content','likedCount'])
47wangpai.to_csv("wangpaiyuanjia.csv",encoding="utf_8_sig",index = False

爬虫部分,done!

分析

这里小编用到了SnowNLP,官方介绍是:SnowNLP是一个python写的类库,可以方便的处理中文文本内容,是受到了TextBlob的启发而写的,由于现在大部分的自然语言处理库基本都是针对英文的,于是写了一个方便处理中文的类库,并且和TextBlob不同的是,这里没有用NLTK,所有的算法都是自己实现的,并且自带了一些训练好的字典。注意本程序都是处理的unicode编码,所以使用时请自行decode成unicode。简单的说,SnowNLP就是可以中文自然语言处理库,可以完成中文分析,词性标注,情感分析,等等功能。

在本文,我们仅借助其对评论进行情感分析,举一个简单的例子:

1s1 = '我喜欢,作曲作词我都好喜欢'
2s2 = '一般般'
3s3 = '感觉水平下降了好多,不好听'
4print('s1: ',SnowNLP(s1).sentiments)
5print('s2: ',SnowNLP(s2).sentiments)
6print('s3: ',SnowNLP(s3).sentiments)
7#s1:  0.9574420076803888
8#s2:  0.5033557046979866
9#s3:  0.183861270052044 

给出的情感评分在[0,1]之间,越接近1,情感表现越积极,越接近0,情感表现越消极。所以,我们将所有的评论都计算了情感得分,并将大于0.5的归于正向情感,反之则为负向情感。代码如下:

1from snownlp import SnowNLP
2data = pd.read_csv("wangpaiyuanjia.csv",lineterminator='\n')
3data["semiscore"] = data['content'].apply(lambda x: SnowNLP(x).sentiments)
4data['semilabel'] = data["semiscore"].apply(lambda x: 1 if x>0.5 else -1)
5
6import numpy as np
7import matplotlib.pyplot as plt
8plt.hist(data["semiscore"], bins = np.arange(01.010.01),label="semisocre", color="#ff9999")
9plt.xlabel("semiscore")
10plt.ylabel("number")
11plt.title("The semi-score of comment")
12plt.show()
13
14
15semilabel = data["semilabel"].value_counts()
16plt.bar(semilabel.index,semilabel.values,tick_label=semilabel.index,color='#90EE90')
17plt.xlabel("semislabel")
18plt.ylabel("number")
19plt.title("The semi-label of comment")
20plt.show()

基于情感的得分,我们得到下图:

非常直观,大家对“王牌冤家”这首歌喜欢的人居多,和我一样,非常喜欢的人数也是相当可观的。那么以0.5为界限进行划分后呢:

正向情感的人数是负向情感人数的两倍多。作为粉丝,非常欣慰啊。

这里,再对这些评论做一个简单的词云图吧,词云图主要是jieba分词,因为SnowNLP分词的效果不如jieba。如下:

1import jieba
2comment=''.join(data['content'])
3wordlist = jieba.cut(comment, cut_all=False)
4stopwords_chinese = [line.strip() for line in open('stopwords_chinese.txt',encoding='UTF-8').readlines()]
5#过滤点单个字
6word_list=[]
7for seg in wordlist:
8    if seg not in stopwords_chinese:
9        word_list.append(seg)
10
11word_list=pd.DataFrame({'comment':word_list})
12word_rank = word_list["comment"].value_counts()
13
14
15from pyecharts import WordCloud
16wordcloud_chinese = WordCloud(width=1500, height=820)
17wordcloud_chinese.add("", word_rank.index[0:100], word_rank.values[0:100], word_size_range=[20200], is_more_utils=True)
18wordcloud_chinese.render("comment.html")


关于停用词,可以参考网易云音乐上万首hiphop歌曲解析rapper们的最爱(可视化篇)

结语

结合之前写的关于rap歌词的三篇文章,好像胡萝卜酱把网易云音乐相关能爬的信息都爬了,。网页爬虫,胡萝卜酱写了很多了,之后,胡萝卜酱给大家带来一些不一样的爬虫吧。

文章有问题?点此查看未经处理的缓存