项目地址 https://github.com/Adydio/DataAnalysis_CloudMusic

网易云音乐评论数据分析

1.背景与目标

今年四月底,各大网友“册封”华语乐坛“新四大天王”。这四位分别是华晨宇,王琳凯,Capper和姜云升。值得注意的是,这一次“新四大天王”的评选是具有一定审丑性质的。以本文即将分析的Capper的作品《雪distance》为例,这首歌歌词质量低、审美价值低,却在近期爆火。我认为这些作品的爆火,与歌手在场下的“迷惑言论”和近期对于这些歌手或者这些作品的负面爆料有关,并且我拟用自己获取的数据更好地说明这一点。

网易云音乐是一款火爆的听歌软件,聚集了大量年轻受众。值得一提的是,相比于QQ音乐等一流听歌软件,网易云音乐的评论数往往是前者的好几倍,我认为这其中的原因是微妙而复杂的。作为一位“村龄”五年的网易云音乐深度用户,我认为网易云爆火原因之一就是它善于营造“氛围”。如今的年轻人物质丰富但也面临着前所未有的压力。情感的压抑,生活的不顺让他们诉诸歌曲,寻求慰藉。而网易云音乐创造的“云村”,“抱一抱”等小功能,还有简约不简单的页面设计,小众但精华的曲库,精准的每日推送以及走心的听歌报告给了年轻人最好的答案。而我此次作业的目标,就是结合时事分析华语乐坛“新四大天王”爆火的原因,发掘数据背后的一些规律并且给出自己的评价和解释,再通过自己收集的数据,结合网易云音乐软件本身的特点,探究网易云音乐评论的特点并且探讨网易云音乐大环境的变化。

2.获取数据

运用python,调用网易云音乐评论的API,整理数据得到Excel文件。

《雪Distance》的处理是在pre-processing.ipynb中完成的。这是调用API后再用自己编写的函数整合复杂的嵌套json文件得到的结果,代码是经过高度简化的,原理上利用我的这些代码可以获取网易云音乐任何一首歌曲的所有评论。

部分来源于课程群的数据如stopwords.txt,comments.txt,hot_comments.txt。我只选用stopwords.txt并且基于实际情况进行了大量改动。原因在于这些数据大多过于老旧,评论几乎都是2019年之前的数据,而且部分歌曲如周杰伦的歌曲早就下架。对于分析“热评”性质有较大的干扰。为了得到更精准的数据,我还是使用自己爬取的数据。具体爬取过程见AcquireComments.ipynb,里面有详细的API信息和自己编写的函数,原理上可以用这些方法获取任意一个歌单的所有歌曲详细信息。

3.数据分析

3.1 《雪Distance》歌曲评论全面分析

3.1.0 数据读取与预处理

我们读取歌手Capper的新作《雪Distance》的评论。

xd <- read.table(file = "xue_distance_final.csv",header = TRUE,encoding = 'UTF-8',sep = ",",comment.char = "",quote = "",fill = TRUE, allowEscapes = TRUE) # 读入数据
xd <- xd[,-11]
xd <- xd[,-1]
xd <- xd[,-1]
xd <- xd[,-1]# 删除前三列和最后一列,这是在调用api之后再处理多出来的
summary(xd)
##     userid           commentid           username           content         
##  Length:85502       Length:85502       Length:85502       Length:85502      
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##    timeStr           likedcount             ip           
##  Length:85502       Length:85502       Length:85502      
##  Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character
变量解释
变量名 含义
userid 发表评论者的id
commentid 留言的编号
username 发表评论者的昵称
content 评论内容
timeStr 发表评论的日期
likedcount 点赞次数
ip ip属地

变量的类型有的不正确,需要修改:

xd[,"timeStr"] <- as.Date(xd[,"timeStr"])
xd[,"userid"] <- as.numeric(xd[,"userid"])
xd[,"likedcount"] <- as.numeric(xd[,"likedcount"])
xd[,"commentid"] <- as.numeric(xd[,"commentid"])
cat("去除NA前的评论数",nrow(xd))
## 去除NA前的评论数 85502
xd <- na.omit(xd)
cat("\n去除NA后的评论数",nrow(xd))
## 
## 去除NA后的评论数 84941

因为爬数据过程中,userid难免会带上奇怪的符号,而样本量足够大,我们索性直接去掉含有NA的行,对结果影响不大。

3.1.1 评论个数随时间的分布

为了研究歌词的性质,我们先从个例开始研究。《雪Distance》是时下讨论度非常高的一首rap歌曲,这首歌于2023年3月1日在网易云音乐上发布,而在接下来的两个月中,这首歌先是被曝有重大抄袭嫌疑,再就是在4月9日歌手Capper在沈阳巡演时发表攻击性极强的言论引发网民不满,这在另一种程度上促进了该歌曲进一步“出圈”爆火,因此,我们先来看看评论数量随时间的分布情况。

library(ggplot2)
comment_distribution_time <- ggplot(data = xd, aes(x=timeStr)) + geom_histogram(aes(y=..density..), color = "black", fill="white", binwidth = 1) + 
 geom_density(alpha=0.2, fill="green") + labs(x = "时间", y = "评论数") + ggtitle("评论数量随时间的分布") + theme(plot.title = element_text(hjust = 0.5))
comment_distribution_time

这个结果能反映一些事实。首先,歌曲在前20天的表现足以说明歌手Capper的热度之高。在新歌发布的前四天就有上万条评论的迅速累积,以及在3月4日单日评论近万,这是非常少见的,可见歌手本身是具有大量的粉丝群体的。在前四天热度短暂高潮后,随着越来越多的人涌入歌曲,外加歌曲已经积累了两万条评论的基础,该歌曲涉嫌抄袭也引发讨论,这一切导致在20天左右歌曲热度再次上升,最后热度渐渐饱和,每天的评论数稳定增长,而每日的增长数有明显下行趋势。这仿佛是每一首流行歌曲的归宿,除非有特殊的事件发生,才能再一次将歌曲的热度唤醒。而我们看到,在四月中旬,歌曲的热度奇迹般回升,歌曲迎来了又一次热度的小高潮。我们观察到歌曲每日评论数的“鞍点”就在4月10日左右,正好对应歌手Capper极具争议的演唱会时间4月9日。为了进一步展现此次事件与歌曲热度的相关性,我将继续分析歌曲评论的群体变化以及评论内容的情感变化。

3.1.2 初见端倪,揭秘“狂热粉丝”

我们开始着眼于观察评论群体的分布。众所周知,在各大音乐软件都存在着多多少少的“饭圈”现象。死忠粉刷评论这件事情也是喜闻乐见了。在数以万计的评论中,必然会出现狂热的粉丝刷评论的现象。我们来观察狂热粉丝的数量以及他们活跃时间的分布,即寻找发表多次评论的用户。

xd_user <- table(xd$userid) # 将所有的评论按userid统计频数
xd_user <- sort(xd_user, decreasing = TRUE)
xd_user[1:35]
## 
## 8455015649 3963628262 8430449562 5114176147 1930671410 7890401962  566213081 
##        129        114        100         95         93         93         84 
##  541063310 1366699586  622107542 1923260533 4945096989 5111163569 3327610983 
##         79         79         75         75         71         71         70 
##  625745696 1681335566 8473380483 1956659800 2131321920 8460446466 1419626544 
##         67         66         66         60         56         53         52 
##  430208557 3255555684 8471492830 1557313181 1922260450 8469828249 1983875970 
##         51         51         51         48         48         48         47 
## 8132241849 8537369422  541975316 1507307204 1750245473 7923187383 1854718965 
##         47         47         46         46         46         46         45

我们发现死忠粉数量惊人之多!如果将发10条评论以上的评论者定义为“狂热粉丝”,我们来计算一下狂热粉丝的评论有多少:

fans <- xd_user[xd_user[]>=10]
ans <- 0
for (i in 1:length(fans)) {
  ans <- ans + fans[i]
}
cat("狂热粉丝贡献的评论数:",ans)
## 狂热粉丝贡献的评论数: 11328

这是一个很大的数!要知道绝大多数流行歌曲的评论数不过寥寥数百上千,这个数目无疑是惊人的。此外我们再看看这些死忠粉都发了些什么:

for (i in 1:5) {
  print(xd[xd[,"userid"]==as.numeric(labels(xd_user)[[1]][i]),"content"][1:10])
}
##  [1] "见一面好不好 我站远点"                 
##  [2] "有无数个瞬间我还是很想你"              
##  [3] "后来我们的关系不删除 不打扰 熟悉且陌生"
##  [4] "晚安之后 你在睡觉 我在想你"            
##  [5] "我理解 她比我漂亮"                     
##  [6] "起雾了 看不清你"                       
##  [7] "很少想起你了 挚爱"                     
##  [8] "因为相信你不会离开我 所以我是小闹 小作"
##  [9] "睡不着的凌晨回不去的我们"              
## [10] "来日方长我们带着诚意慢慢来"            
##  [1] "那些委屈难过像耳光一样抽得我哑口无言."        
##  [2] "你要站在我的位置你就知道我的感受."            
##  [3] "等到我们终于懂得站在彼此的角度看待问题时."    
##  [4] "或许你会遇到更好的人可我除了你看谁都差点意思."
##  [5] "我无法回答那些尖锐的话除了眼泪就是沉默."      
##  [6] "你说我不懂于是我心千斤重."                    
##  [7] "见一面吧我站远点看一眼就好."                  
##  [8] "不想揭穿不代表我看不透."                      
##  [9] "好像大家都不太珍惜对自己好的人."              
## [10] "2023忘掉关于你的所有."                        
##  [1] "盆儿爱你?"                                                                                                                                                                                             
##  [2] "capper不是我对象我真的#恶心#头晕#面色苍白#出汗#腹痛#血压下降#休克#昏迷#体温增高#浑身无力发冷#全身酸痛#没有食欲#昏昏欲睡#腹泻#呕吐#眼睛酸胀#痛关节疼痛#咳嗽#咳痰#胸痛#恶寒#头痛[快哭了][快哭了][快哭了]"
##  [3] "capper一定要快乐!!!听见了吗!"                                                                                                                                                                      
##  [4] "capper不是我对象我真的#恶心#头晕#面色苍白#出汗#腹痛#血压下降#休克#昏迷#体温增高#浑身无力发冷#全身酸痛#没有食欲#昏昏欲睡#腹泻#呕吐#眼睛酸胀#痛关节疼痛#咳嗽#咳痰#胸痛#恶寒#头痛[快哭了][快哭了][快哭了]"
##  [5] "capper是我对象我就#舒坦#头不昏了#眼不花了#千里眼#一秒逃离#胸口无不适#精神振奋#顺风耳#食欲大增#好奇心#发疯#不再克制#脚步轻盈#温柔#暖心#宁静#热爱生活#清风徐来#来去之间[舔屏][舔屏][舔屏][流泪]"         
##  [6] "capper是我对象我就#舒坦#头不昏了#眼不花了#千里眼#一秒逃离#胸口无不适#精神振奋#顺风耳#食欲大增#好奇心#发疯#不再克制#脚步轻盈#温柔#暖心#宁静#热爱生活#清风徐来#来去之间[舔屏][舔屏][舔屏][流泪]"         
##  [7] "capper一定要快乐!!!听见了吗!"                                                                                                                                                                      
##  [8] "capper是我对象我就#舒坦#头不昏了#眼不花了#千里眼#一秒逃离#胸口无不适#精神振奋#顺风耳#食欲大增#好奇心#发疯#不再克制#脚步轻盈#温柔#暖心#宁静#热爱生活#清风徐来#来去之间[舔屏][舔屏][舔屏][流泪]"         
##  [9] "capper不是我对象我真的#恶心#头晕#面色苍白#出汗#腹痛#血压下降#休克#昏迷#体温增高#浑身无力发冷#全身酸痛#没有食欲#昏昏欲睡#腹泻#呕吐#眼睛酸胀#痛关节疼痛#咳嗽#咳痰#胸痛#恶寒#头痛[快哭了][快哭了][快哭了]"
## [10] "capper不是我对象我真的#恶心#头晕#面色苍白#出汗#腹痛#血压下降#休克#昏迷#体温增高#浑身无力发冷#全身酸痛#没有食欲#昏昏欲睡#腹泻#呕吐#眼睛酸胀#痛关节疼痛#咳嗽#咳痰#胸痛#恶寒#头痛[快哭了][快哭了][快哭了]"
##  [1] "哥是你力气大还是大象力气大啊" "哥是你力气大还是大象力气大啊"
##  [3] "哥是你力气大还是大象力气大啊" "哥是你力气大还是大象力气大啊"
##  [5] "哥是你力气大还是大象力气大啊" "哥是你力气大还是大象力气大啊"
##  [7] "哥是你力气大还是大象力气大啊" "哥是你力气大还是大象力气大啊"
##  [9] "哥是你力气大还是大象力气大啊" "哥是你力气大还是大象力气大啊"
##  [1] "你不会偷偷下班了吧"                  "不要偷偷自己下班 要记得给大家说再见"
##  [3] "不要偷偷自己下班 要记得给大家说再见" "不要偷偷自己下班 要记得给大家说再见"
##  [5] "不要偷偷自己下班 要记得给大家说再见" "不要偷偷自己下班 要记得给大家说再见"
##  [7] "下班了要说一声呀"                    "能不能给发个颜文字"                 
##  [9] "能不能给发个颜文字"                  "能不能给发个颜文字"

评论里有大量意义不明并且重复的言论。狂热粉丝贡献了数以万计的评论,可见歌曲评论区的水分之多。我们知道,在网易云音乐里面,对于所谓“网红歌曲”,评论过万的歌曲是一个分水岭,短时间内过万就表示这首歌彻彻底底的“红了”,从而能够吸引更多的听众,形成正反馈效应,在短时间内还可以继续收割一部分听众。而一些真正有内涵的歌曲,“去饭圈化”的好歌曲,评论数增长往往不是快餐式的急剧增长,而是随着口碑的积累缓慢爬升。

评论数排名前五的狂热粉丝们给我们展示了评论区“水评论”的众生相。既有疯狂输出情绪的,又有脑残支援歌手的饭圈文案,还有一些无意义的灌水评论。从这里就可以看出,在狂热粉丝的加持下,这首《雪Distance》的热度一定程度上是被“炒起来的”,也侧面说明了这首歌的“网红“性质早已逾越了歌曲本身的性质。

接下来,我们感兴趣的是,这些狂热粉丝都活跃在什么时候?这些评论一般在何时出现呢?这或许能反映一些问题。

fans_id <- as.numeric(labels(fans)[[1]]) #狂热粉丝的id
fans_comments <- xd[xd[,"userid"] %in% fans_id,] #狂热评论的切片
fanscomments_distribution_time <- ggplot(data = fans_comments, aes(x=timeStr)) + geom_histogram(aes(y=..density..), color = "black", fill="white", binwidth = 1) + 
 geom_density(alpha=0.2, fill="red") + labs(x = "时间", y = "评论数") + ggtitle("狂热粉丝评论数量随时间的分布") + theme(plot.title = element_text(hjust = 0.5))
fanscomments_distribution_time

结果令人惊讶!灌水评论几乎集中于3月5日,几乎可以断定在这一天有系统的“水军”刷评论的行为,而后面的大量的“狂热粉丝”更有可能是路人性质的,并不是以刷评论为动机的。我们回顾一下先前打印的狂热粉丝的评论内容,除了第一位粉丝发的内容与情感有关,其余粉丝的内容评论毫无价值可言,甚至有大量重复。考察一下他们发布的日期,

xd[xd[,"userid"]==as.numeric(labels(xd_user)[[1]][1]),"timeStr"][10]

[1] “2023-05-02”

xd[xd[,"userid"]==as.numeric(labels(xd_user)[[1]][2]),"timeStr"][10]

[1] “2023-05-06”

xd[xd[,"userid"]==as.numeric(labels(xd_user)[[1]][3]),"timeStr"][10]

[1] “2023-03-05”

xd[xd[,"userid"]==as.numeric(labels(xd_user)[[1]][4]),"timeStr"][10]

[1] “2023-03-05”

xd[xd[,"userid"]==as.numeric(labels(xd_user)[[1]][5]),"timeStr"][10]

[1] “2023-03-05”

march5th_comments <- table(xd$timeStr)["2023-03-05"]
march5th_fans_comments <- table(fans_comments$timeStr)["2023-03-05"]
cat("3月5日评论总数为",march5th_comments,",3月5日水军评论总数为",march5th_fans_comments)

3月5日评论总数为 8405 ,3月5日水军评论总数为 5349 发现无意义评论更多聚集在3月5日。可以断定,这一天的评论绝大多数是“水军出击”给刷出来的。这对于歌曲热度提升有着推波助澜的作用,但这种现象对于“饭圈化”尚不严重的网易云音乐来说,无疑是相当可悲的。

3.1.3 歌曲风评研究之评论情感变化

我们将目光转向歌曲的“风评”变化。换言之,接下来我们即将研究评论的关键词和情感的变化。一个无法反驳的事实是,这首《雪Distance》的风评如今是非常烂的,我们在意的是导致此般现象的转折点在哪里,导致这种变化的原因是什么。首先,我们研究评论的情感变化。

在研究以下问题之前,我们先删除掉这些重复的灌水评论。

我们使用百度的paddlepaddle预训练模型,用模型判断用户评论信息的情感态度,分析消极和积极的占比。在EmotionAnalysis.ipynb中,我们得到了含有用户情感态度标签的文件xue_emotion.csv。值得说明的是,该模型对于一串字符会给出相应的正向、负向情感概率。由于评论里含有大量如“丁真”“泰裤辣”“依托答辩”等负面感情倾向的网络用语或影响判断,这里我采用的方法是,当且仅当正向概率大于一个不小于0.5的参数\(p\)时,才认定这是一个正向情绪的评论。

我们接下来读取xue_emotion.csv,该文件是取\(p=0.6\)运行得到的,并且严谨起见,如果一个用户评论数不少于10条,他的评论将被移除。

xd1 <- read.table(file = "xue_emotion.csv",header = TRUE,encoding = 'UTF-8',sep = ",",comment.char = "",quote = "",fill = TRUE, allowEscapes = TRUE)
xd1 <- xd1[-which(xd1[,'userid'] %in% fans_id),]
xd1 <- xd1[,-1]
xd1[,"timeStr"] <- as.Date(xd1[,"timeStr"])
xd1[,"userid"] <- as.numeric(xd1[,"userid"])
xd1[,"new_sentiment_label"] <- as.numeric(xd1[,"new_sentiment_label"])
xd1 <- na.omit(xd1)
emotion_distribution <- aggregate(xd1[,"new_sentiment_label"], by = xd1["timeStr"], mean)
summary(emotion_distribution)
##     timeStr                 x         
##  Min.   :2023-03-01   Min.   :0.3997  
##  1st Qu.:2023-03-18   1st Qu.:0.4574  
##  Median :2023-04-04   Median :0.4919  
##  Mean   :2023-04-04   Mean   :0.4912  
##  3rd Qu.:2023-04-21   3rd Qu.:0.5223  
##  Max.   :2023-05-09   Max.   :0.5737
emotion_distribution_figure <- ggplot(data = emotion_distribution, aes(x = timeStr, y = x)) + geom_point(colour = "#FF4500") + geom_smooth(colour = "#6495ED") + labs(x = "时间", y = "正向情感指标") + ggtitle("正向情感指标数量随时间的分布(p=0.6)") + theme(plot.title = element_text(hjust = 0.5)) + ylim(0.38,0.6)
emotion_distribution_figure

从图中我们看出,评论在歌曲发布初期好评如潮,可是后面的负面评论越来越多。同样地,我们再分别命参数\(p=0.5,0.55,0.65,0.7\)做同样的操作,得到数据框df50,df55,df65,df70。由于同样操作过多,洗数据代码略去不显示。

xd_ <- rbind(xd50,xd55,xd65,xd70)
xd_ <- aggregate(xd_[,"new_sentiment_label"], by = c(xd_["timeStr"], xd_["p"]), mean)
summary(xd_)
##     timeStr                 p                x         
##  Min.   :2023-03-01   Min.   :0.5000   Min.   :0.2747  
##  1st Qu.:2023-03-18   1st Qu.:0.5375   1st Qu.:0.4331  
##  Median :2023-04-04   Median :0.6000   Median :0.4836  
##  Mean   :2023-04-04   Mean   :0.6000   Mean   :0.4801  
##  3rd Qu.:2023-04-22   3rd Qu.:0.6625   3rd Qu.:0.5360  
##  Max.   :2023-05-09   Max.   :0.7000   Max.   :0.6458
ggplot(data = xd_,aes(x = timeStr, y = x, colour = factor(p))) + geom_point() + coord_cartesian() + facet_wrap(~ p) + theme_bw() + geom_smooth(colour = "#6495ED") + labs(x = "时间", y = "正向情感指标") + ggtitle("正向情感指标数量随时间的分布") + theme(plot.title = element_text(hjust = 0.5)) + ylim(0.28,0.6) 

图表的意义是十分清晰的。无论参数\(p\)如何选择,评论的感情分布都是现在三周之内上涨,再逐日降低。这样的原因有两点,首先,随着这首歌发布时间的推移,越来越多的网友发现这首《雪Distance》有着抄袭的嫌疑,在歌曲本身热度的加持下,涉嫌抄袭这件事情会引来各路网友前来留下评论;第二点就是歌手Capper在4月9日极具争议的巡演,他的引战言论吸引了更多的路人,为歌曲带来了更多的(负面的)热度。从图中也看到,四月中旬之后,歌曲的风评不但没有达到饱和,还有雪上加霜之势。

下面,我们继续从评论本身的特点,来探究歌曲的风评转变。

3.1.4 歌曲风评研究之关键词

我们首先关注评论的词云,了解大致有哪些关键词。在这里我们再次利用百度开发的基于Python的LAC分词模型。生成云图的文件参见WordCloud.ipynb,其中LAC起分词作用,而wordcloud库负责生成云图。为了贴合网易云音乐的样式,背景被设定为其logo的形状:

这张词云图可谓是包罗万象了。我们看到还是有很多正面评价如“喜欢”“好听”,可见这首歌曲旋律本身还是有可圈可点之处的。我们还观察到很多与歌词相关的内容,如“雪”“冷”“桥牌”等,这一类评论时常出现,说明听众沉浸其中,与歌词产生了共鸣。还有一类关键词引人注目,便是各种负面词汇,有结合时事的,如“抄袭”“泰裤辣”(时下热梗);也有拿热门负面词汇含沙射影的,如“电子烟”“丁真”“答辩(大便)”等词竟然有着很高的出场频率,这说明这首歌也引来了不少骂声,而这种批判既是隐晦的,又是随波逐流的。换言之,这首歌招来外界的骂声,这些骂声仿佛都是一致的,发表负面评论的人(也称作“黑子”)他们骂这首歌的“骂法”近乎都是一致的,无非是“抄袭”“丁真”“答辩”此类词汇,而我们却鲜见对这首歌客观、冷静的批判,如“歌词写的不好”“唱腔矫揉造作”等等。这种现象我认为不是好的现象,当这首歌成为热点,越来越多的路人关注这件事情,他们做的竟然是“跟风黑”“无脑喷”,而不是认真听完、客观地发表他们的见解,这很大程度证实了网易云音乐的很多用户,很容易被外界“带节奏”,很喜欢去评论区“冲塔”“看乐子”。

当然,暖心的是,词云背后还有一些网易云音乐“特有的”词汇,如“想你”“幸福”“想你”“希望”等。这些词汇脱离了歌曲本身,生动地诠释了网易云音乐的评论区独有的“树洞”属性。随着评论的累积,对于评论区,其内容往往会脱离歌曲本身,反而化身年轻人释放情感、互相交流、抚慰的场所。评论区的这种特色让网易云音乐无法被任何其他的网站取代,我们也可以看到,在网易云音乐的评论区,每一个角落都有正能量的存在。

在这之外,我们还可以观察三月份和四月份的评论关键词,可以看出听众明显的情绪变化:

接下来,我们来统计一下词频。从原评论文件中切片处理得到了word_freq_march.csv,word_freq_april.csv。分别读取并且绘制热度最高的词如下:

xd_march <- read.table(file = "word_freq_march.csv",header = TRUE,encoding = 'UTF-8',sep = ",",comment.char = "",quote = "",fill = TRUE, allowEscapes = TRUE)
xd_march <- xd_march[order(xd_march$value, decreasing = TRUE)[1:10],c(2,3)]
plot_march <- ggplot(data = xd_march,aes(x=reorder(key,-value),y=value,fill=key,colour=key,group=factor(1))) + geom_bar(stat = "identity",alpha=0.5) + labs(x = "", y = "出现次数") + ggtitle("三月评论高频词") + theme_classic() + theme(plot.title = element_text(hjust = 0.5))
plot_march

我们看到,三月份是歌曲刚出的一个月,这个时候风评尚好,反对的声音还没来袭。词频前十名的热词没有贬义词,基本上都是好评,或者是诸如“冷”“雪”“远”“一点”这样的歌词原句。我们再来看四月份的热词:

xd_april <- read.table(file = "word_freq_april.csv",header = TRUE,encoding = 'UTF-8',sep = ",",comment.char = "",quote = "",fill = TRUE, allowEscapes = TRUE)
xd_april <- xd_april[order(xd_april$value, decreasing = TRUE)[1:10],c(2,3)]
plot_april <- ggplot(data = xd_april,aes(x=reorder(key,-value),y=value,fill=key,colour=key,group=factor(1))) + geom_bar(stat = "identity",alpha=0.5) + labs(x = "", y = "出现次数") + ggtitle("四月评论高频词") + theme_classic() + theme(plot.title = element_text(hjust = 0.5))
plot_april

我们看到,四月份的评论就充斥着负面情绪了,因为诸如“泰裤辣”“丁真”“答辩”“电子烟”这样阴阳怪气的贬义词汇频出。而且,由于分词器的限制,“喜欢”可能是从“不喜欢”一词里面拆分开来的,因此这张图背后的负面词汇是比展现出来的要多的。

3.1.5 歌曲受众的地域分布

API返回的诸多参数中还包含用户的ip属地,一个自然的想法就是去探究,这些评论者都来自哪里,会不会来自某个特定区域的人会特别多?接下来我们来探究此事。

首先按照用户id,提取他们的ip。

foo <- function(x){
  return(length(x))
}
user_ip <- aggregate(xd[,"userid"], by = xd["ip"],foo)
write.csv(user_ip, file = "ip.csv")
user_ip <- user_ip[order(user_ip$x,decreasing = TRUE),]

由于python的pyecharts库中有中国地图相关的函数,下面转入IpDistribution.ipynb生成地图的分布。这张图在html上会有更佳的交互式体验,点击地图区域可以显示该地区发表评论的人数,在这里还是以图片的形式展示。网页交互版点击 http://home.ustc.edu.cn/~dyk2021/ip.html

从图中看出来,歌曲在江浙、山东、河南和四川有着较高的热度,而在广东省热度异常的高。其余省份评论数分布较为均匀。我们进一步观察热度较高的省份:

head(user_ip)
##      ip    x
## 25 广东 9663
## 32 河南 5609
## 61 山东 5539
## 41 江苏 5508
## 81 浙江 5066
## 65 四川 4530

很自然的一个怀疑就是前文提及的3月4日的“水军”会不会造成广东省热度异常高?我们考察一下“狂热粉丝”群体(这里我们放宽松,评论数不小于3记为狂热粉丝)。重复上述操作,我们得到:

fans1 <- xd_user[xd_user[]>=3]
fans1_id <- as.numeric(labels(fans1)[[1]])
fans1_comments <- xd[xd[,"userid"] %in% fans1_id,]
fans_ip <- aggregate(fans1_comments[,"userid"], by = fans1_comments["ip"],foo)
fans_ip <- fans_ip[order(fans_ip$x,decreasing = TRUE),]
head(fans_ip)
##      ip    x
## 8  广东 2136
## 13 河南 1688
## 30 山东 1433
## 43 浙江 1397
## 20 江苏 1167
## 34 四川 1146

可见大量灌水、重复评论并不是系统性从单一地点刷取的,哪怕评论是”刷出来的“,其来源也大致符合我国人口分布,因为广东省、山东省、河南省、江苏省和四川省分别为我国人口前五名的大省。从地图中也可以看出来,歌曲的热度分布大致就是我国的人口分布,并没有特殊的地域倾向。这不让人意外,因为互联网、短视频的兴起给了这种歌曲爆火的渠道,让全国网民几乎无差别的了解这个世界的信息。

3.2 我要上热门:网易云评论二三事

3.2.0 数据读取与预处理

在经过数据的爬取和处理之后(见AcquireComments.ipynb),我们得到了来自2213首华语热门歌曲的排名前五热评的数据。这些歌曲的来源很广泛,既有少许九十年代金曲,又涵盖了大量华语乐坛经典曲目以及时下热门流行单曲,并且他们每一首歌都有10000+的评论,足以证明这些热评都是“热评中的热评”。我们首先读取数据。

hc <- read.table(file = "2.csv",header = TRUE,encoding = 'UTF-8',sep = ",",fill = TRUE,quote = "")
hc <- na.omit(hc)
hc <- hc[,-c(1,10)]
hc[,"timeStr"] <- as.Date(hc[,"timeStr"])
hc[,"userid"] <- as.numeric(hc[,"userid"])
hc[,"likedcount"] <- as.numeric(hc[,"likedcount"])
hc[,"commentid"] <- as.numeric(hc[,"commentid"])
hc[,"replycount"] <- as.numeric(hc[,"replycount"])
hc <- na.omit(hc)
summary(hc)
##      userid            commentid           username           content         
##  Min.   :1.000e+00   Min.   :3.272e+05   Length:10969       Length:10969      
##  1st Qu.:4.811e+07   1st Qu.:4.856e+07   Class :character   Class :character  
##  Median :1.240e+08   Median :3.881e+08   Mode  :character   Mode  :character  
##  Mean   :3.421e+08   Mean   :8.338e+08                                        
##  3rd Qu.:3.935e+08   3rd Qu.:1.278e+09                                        
##  Max.   :8.135e+09   Max.   :5.823e+09                                        
##     timeStr             likedcount        replycount           auth       
##  Min.   :2013-05-09   Min.   :    170   Min.   :    0.0   Min.   :0.0000  
##  1st Qu.:2015-11-22   1st Qu.:  14968   1st Qu.:   53.0   1st Qu.:0.0000  
##  Median :2017-05-20   Median :  29740   Median :  166.0   Median :0.0000  
##  Mean   :2017-05-29   Mean   :  53547   Mean   :  484.7   Mean   :0.1396  
##  3rd Qu.:2018-10-20   3rd Qu.:  61009   3rd Qu.:  464.0   3rd Qu.:0.0000  
##  Max.   :2022-12-31   Max.   :1713923   Max.   :32252.0   Max.   :1.0000
新增变量解释
变量名 含义
replycount 回复数
auth 评论的发布者是否为音乐人

处理完了热评数据,我们接着处理普通评论的数据。原先我处理的是课程群里的comments.txt,发现这里面的数据太离谱了,竟然还有评论上万的“普通评论”,可见数据的选取不合理。一个直观的解释是,有的歌曲本身评论一万出头,后一万条很有可能就接近热评了。所以我还是决定自己爬取,文件同上。这一次爬取的是上述2213首华语热歌每首歌的最新15条评论。下面开始洗数据:

rc <- read.table(file = "new_comments.csv",header = TRUE,encoding = 'UTF-8',sep = ",",fill = TRUE,quote = "")
rc <- rc[,-c(1,6,8)]
rc[,"userid"] <- as.numeric(rc[,"userid"])
rc[,"likedcount"] <- as.numeric(rc[,"likedcount"])
rc[,"commentid"] <- as.numeric(rc[,"commentid"])
rc[,"replycount"] <- as.numeric(rc[,"replycount"])
rc <- na.omit(rc)
summary(rc)

发现还是有少数歌曲赞数竟然上万,这必定是已经下架的歌曲。所以要排除掉。

rc <- rc[-which(rc[,"likedcount"]>=50),]
summary(rc)

可以看到,按时间排序的评论一般无人问津。如果你想拿到热评,一定要早发评论!

3.2.1 数据初探:有趣的小细节

  • “热评收割机”,寻找热评专业户

我们来找一找有没有同一个人占领多个热评?这里就涉及到给热评划分类别的问题。网易云用户分音乐人和非音乐人两种,音乐人天然是具有热度的。所以考虑这件事情必须把用户分成两类来看。

hc1 <- tapply(hc[,"userid"],hc[,"auth"],table)
hc_regular <- data.frame(hc1[1])
hc_auth <- data.frame(hc1[2])
colnames(hc_regular) <- c("userid", "count")
colnames(hc_auth) <- c("userid", "count")
cat("汇总非音乐人上热评的次数:\n")
## 汇总非音乐人上热评的次数:
summary(hc_regular$count)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   1.000   1.000   1.000   1.106   1.000  14.000
cat("汇总音乐人上热评的次数:\n")
## 汇总音乐人上热评的次数:
summary(hc_auth$count)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   1.000   1.000   1.000   1.681   2.000  27.000

可见,音乐人是更容易上热评的。如果他是这首歌的作者,他自己在评论区下面留言一定会得到大量的点赞。如果他是音乐人跑去别的歌曲下面留言,同样会被粉丝识别并且得到追捧。所以,如果你的账号在网易云音乐上有一定粉丝积累,你的言论当然会更容易被注意到了!在发评论上热评方面,音乐人徐秉龙算是这方面的专家:

xbl <- hc[hc[,"username"]=="徐秉龙",c(4,6)]
xbl[10:15,c("content","likedcount")]
##                                                       content likedcount
## 3035                                   感情要拉长战线才珍贵。      45960
## 3520                                   像战士冲锋一样去见你。      84041
## 3900 嘉哥真的是一个可以尽自己所有努力去温暖这世上所有人的人。      52877
## 4025               你窥探过我最不安的手,在青春最寒冷的时候。      59273
## 4475                         “不要害怕自己,长成生活的模样。”     138416
## 5015                       “我经过你的凛冽,也最懂你的密切。”     181286

他的评论堪称“非主流”典范,寥寥数语就能挠到当下小年轻们的痒痒肉,他是真的有一套。我们看到这点赞数目在热评中也算是极为之高的了。

当然了,还有非音乐人霸榜评论区高达14次!可见还是有少数掌握了“热评密码”的人,凭借着精辟的言论赢得听众们的青睐。我们看看这个人是何方神圣呢?

hc[hc[,"userid"]==(hc_regular[hc_regular[,"count"]==14,]$userid),3][1]
## [1] "YouTube热门日推"

难怪!原来是官方号。官方号凭借品牌优势本来就有粉丝的积累,网易的CEO丁磊也时不时来评论区做客,当然能吸引大批点赞回复,点赞数动辄十万二十万。譬如说:

hc[hc[,"username"]=="网易CEO丁磊",c(3,4,5,6)]
##          username
## 521   网易CEO丁磊
## 522   网易CEO丁磊
## 10759 网易CEO丁磊
##                                                                                                                                                                content
## 521   在搞了在搞了。正好和云村的同学说下,版权的事情我现在亲自抓,只要独家版权放开,我们就敞开买。最近回来的摩登、英皇、中唱等,大家先听起来,别辜负村长我的一片辛劳。
## 522                                                                                                           “三千里,偶然见过你”。漠河舞厅深深的打动了我!久听不厌。
## 10759                                                                                                                                         能让人想起往事的一首歌。
##          timeStr likedcount
## 521   2021-11-16     201178
## 522   2021-11-13     128035
## 10759 2015-01-09      98614

当然,肯定有那种言论惊人,获赞无数的“评论达人”,比如下面的用户“长夜看海”:

hc[hc[,"userid"]==(hc_regular[hc_regular[,"count"]==10,]$userid),c(4,6)]
##                                                                                         content
## 601                          总有人懂你的欲言又止,也有人懂你的言外之意。时隔多年或是忽然之间。
## 937                                  原来有些放手是必然,原来离开也是种祝福,原来我们没有未来。
## 1539 她教会我分清了爱和新鲜感。所以我才明白为什么有些人一爱就是一生,而有些人连两三天都嫌太长。
## 1566                                             “十成温柔配合七分演技换来五封情书及一种原谅。”
## 1852                                                 “你被我安稳的爱着,应该有做任何事的勇气。”
## 1880                                                                     胡同的名字叫百花深处。
## 1896                                                            要不是我腰不允许,我也做跳跳糖!
## 1900                                                     “别回来了,我已经过了重蹈覆辙的年纪。”
## 2364                                                                   我不想再有微笑抑郁症了。
## 2399                                     我们崇尚孤独,尊敬孤独,对孤独俯首称臣。可是孤独配吗?
##      likedcount
## 601        7495
## 937       15125
## 1539      10813
## 1566      10651
## 1852      63794
## 1880      18970
## 1896      33730
## 1900      79192
## 2364      34377
## 2399      10982

这些评论就“有那味了”,它们一般比较简短,但是却有着深意,还带一点非主流的文艺气息,这种评论是网易云的绝对特色,也是现在文艺小青年最喜欢的表达形式之一。可见这位“长夜看海”可是深谙流量密码啊!

可以用一张图表总结音乐人和非音乐人的“上榜”频率:

hc_regular[,'用户类型'] <- "普通用户"
hc_auth[,'用户类型'] <- "音乐人"
hc_all <- merge(hc_auth, hc_regular, all = TRUE)
hot_comment_freq <- ggplot(data = hc_all, aes(x=count, fill=用户类型, color=用户类型)) + geom_histogram(binwidth = 1,alpha=0.5) + labs(x = "上榜次数", y = "人数") + ggtitle("人数随上榜次数的分布") + theme(plot.title = element_text(hjust = 0.5)) + xlim(0,6)
hot_comment_freq

由此,我们看到,热评往往都是”昙花一现“,一个人很难上榜两次或更多次;注册为音乐人的用户虽然基数少,但是他们更容易上热评。

  • 不为人知的故事:账号已注销

我们知道,网易云音乐之所以能吸引那么多评论,和评论的“故事性”是密不可分的。而那些顶着默认头像,名称为“账号已注销”的用户,他们的背后往往隐藏着一段不为人知的故事,这也是评论区往往最引人入胜的地方。我们来查找一下评论区有多少人已经注销了自己的账号,并且把这一数据写入文件。

hc_del <- hc[hc[,"username"]=="帐号已注销",]
cat("一共有", nrow(hc_del), "位热评用户注销了自己的账号")
## 一共有 465 位热评用户注销了自己的账号
hc_del <- hc_del["content"]
write.csv(hc_del, file = "zhyzx.csv")

我们感兴趣的是,这些注销了账号的用户,他们都在谈论些什么?他们谈论的内容是积极还是消极?我们把得到的字符数据交给python继续处理这一问题,其文件与前文生成词云、判断情感的文件相同。

这张图真是令人震撼!“喜欢”和“爱”是当今年轻人绕不开的话题。哪个男孩子,在年轻的时候没有轰轰烈烈地喜欢过一个人,哪怕已经离开了青葱的校园时光,哪怕已经长大成人步入社会,心里最隐秘的角落还住着一个女孩?“不知道”,有的人迷茫着;“分手”“眼泪”“一个人”,有的人痛并孤独着;“努力”“希望”“高考”,有的人在默默奋斗着……这些注销了账号的云村过客,都不是简单的人;都是有故事的人,都是立体而生动的人。而这,便是网易云音乐最吸引人的地方——你进出了一次评论区,仿佛经历了一场也许很圆满,又也许没有结局的恋爱。

当然有人也会关心,这些注销了帐号的用户,他们的评论有无明显的感情倾向?我们放在后面来一起讨论。

  • 沉没的宝藏功能,关于“抱一抱”

“抱一抱”是网易云音乐独有的小功能。当用户发表了可能与伤心、失落或者抑郁有关的评论时,正在看评论的你可以两只手指往评论区中间划一划,发评论的人就会收到一个“抱抱”,以示安慰。

最让我感到遗憾的是,在我爬取的最新评论和和最热评论中,没有任何用户收到“抱一抱”,因此抱一抱相关数据在预处理过程中就被我删去。这样的原因我认为是多方面的。首先是,抱一抱这个功能过于小众,只有像我这样的深度用户才了解它的使用方法。此外,网易云音乐并没有引导我们去到处“抱一抱”,我觉得这是对的,因为当抱一抱功能泛滥了,它就失去了原有的价值。最大的原因就是我的样本都是华语流行音乐,而抱一抱更容易出现在纯音乐尤其是小众、非主流的流派如lofi-hiphop,蒸汽波里面。

在我看来近两年抱一抱功能有下行趋势,并没有2020年左右见得多,或许是这个功能过于小众了,所以我才称其为”沉没的宝藏功能“。很不幸我的API调用抱一抱评论所需要的参数过于复杂,短时间内写不出来爬取抱一抱数据的脚本,因此我对于抱一抱功能的分析就到这为止了。

3.2.2 热评密码:评论的文本特征

  • 热评字数一般多少?

混迹评论区多年的我见过各种各样的热评。有的热评真情流露、客观流畅,也有的热评短小精悍、直击内心。我们当然要去看一看,至少字面上,热评评论的长短有何种分布。作为比较,我们同时观察普通评论的字数分布。

rc[,"评论类型"] <- "普通评论"
hc[,"评论类型"] <- "热评"
rc[,"评论字数"] <- nchar(rc[,"content"])
hc[,"评论字数"] <- nchar(hc[,"content"])
rc_length <- rc[,c("评论字数", "评论类型")]
hc_length <- hc[,c("评论字数", "评论类型")]
all_length <- merge(rc_length, hc_length, all = TRUE)
length_freq <- ggplot(data = all_length, aes(x=评论字数, fill=评论类型, color=评论类型)) + geom_histogram(aes(y=..density..),binwidth = 5,alpha=0.5) + labs(x = "评论字数", y = "频率") + ggtitle("评论的字数出现频率") + theme(plot.title = element_text(hjust = 0.5)) + xlim(0,150) + scale_fill_brewer(palette = "Pastel1")
length_freq

我们从图表中观察到,普通评论普遍字数较少,大多在70字以内,但也不乏少量文字多于100字的较长评论,不幸沉没在了评论的海洋中。而热评方面也具有类似的双峰分布,但是热评很明显地有一个大约5个字的字数门槛。我们同时看到,热评有较多字数限制在了60字以内,属于短小精悍型;然而字数稍多,或许略显冗长,上榜的概率就没那么大;越到后面可能是字数多于120字的干货评论或者故事性评论,它们也能收获较高的热度。

短的评论在热评中占比大并不意味着短的评论更容易上热评。我们看到短评论的基数也是相当之大的。相比之下,长的评论相应的在热评中的比例就更高。如果单纯考虑“上热评”这件事,用户更应该尝试写长的评论。

据我的不断观察,网易云的评论风格是在逐年改变的。尤其是19、20年左右和现在的环境大不一样了,现在网易云音乐涌入了大量饭圈粉丝,尤其是说唱文化兴起,网易云音乐的大环境也在发生变迁。自然地,我们可以考察不同时间的热评的特征。我们以年份为单位,看看热评的字数有何变化。

hc[,"评论年份"] <- as.character(as.POSIXlt(hc[,"timeStr"])$year + 1900)
hc_length_year <- hc[,c("评论字数", "评论年份")]
table(hc_length_year$评论年份)
## 
## 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 
##    4 1037 1892 1910 1854 1896 1480  650  223   23
hc_length_year <- hc_length_year[-which(hc_length_year[,2]=="2013"|hc_length_year[,2]=="2022"),]

观察到2022年和2013年样本量太少,遂在下面的研究中剔除。

length_freq_year <- ggplot(data = hc_length_year, aes(x=评论字数,fill=评论年份,colour=评论年份)) + geom_density(alpha=0.2) + labs(x = "评论字数", y = "频率") + ggtitle("2014-2021热评的字数出现频率") + theme(plot.title = element_text(hjust = 0.5)) + xlim(0,150)
length_freq_year

这一张图的现象其实是有点反直观的。我们看到,“短热评”数量从2021年到2016年逐年递减,到了2015,2014年反而有增长趋势。一个不可否认的事实是,中等长度的评论(约70-110字)在热评区不太受待见,这是每一年都一样的。而对于字数多于120的“长热评”,起初在2014年较少,中间阶段2015-2019年变得较多,而从2020年开始,长热评的比例越来越少了。

为了看的更清楚些,分块绘制如下:

ggplot(data = hc_length_year, aes(x=评论字数,fill=评论年份,colour=评论年份)) + geom_histogram(aes(y=..density..),binwidth = 5,alpha = 0.1) + facet_wrap(~ 评论年份) + theme_bw() + geom_density(alpha=0.5) + labs(x = "评论字数", y = "频率") + ggtitle("2014-2021热评的字数出现频率") + theme(plot.title = element_text(hjust = 0.5)) + xlim(0,150)

这张图很能说明问题。首先一个事实是,现在的热评越来越倾向于“抖机灵”,高度凝练的文字文字背后往往有大量信息,这种“信息密度”的剧增是这些热评获得青睐的原因。可以看到,尤其是2021年,字数在30以内的热评史无前例的多。如今短视频普及,人们仿佛越来越追求高的信息密度,字数多的长评论甚至都看不进去,我认为这个趋势是有问题的,这也是我认为网易云音乐评论区的氛围在走下坡路的原因。那些动人的故事、细腻的情绪越来越少,取而代之的净是一些短小的,在短期内能引起短暂而廉价的情绪共鸣的评论,我对此表达严厉的批判。

前面我还提到,“短热评”数量到了2015,2014年反而有增长趋势,这多少有些反直觉。然而我们更需要注意的是,在2014年左右,相隔现在已经近9年。那个时期的用户没有什么“热评”的概念,在评论区更多是朴素的评价和情感的流露。换言之,那段时间长的评论本身就不多;更何况,如今的听众打开评论区,看到了远在8、9年前的人们在这里留下的足迹——时间本身就赋予了这些评论更高的价值。比方说包括我在内的很多年轻人很喜欢听陶喆,而陶喆的歌发行的时候甚至还没有我们,因此我们看一下陶喆的评论区,热评往往是14-16年发布的,而且普遍很短。

我所认为网易云音乐评论区最高光的时段是在17-19年。那个时段饭圈现象尚不严重,一些糟糕的势力并没有涌入网易云,在这段时间中、长热评百花齐放,周杰伦的版权还在,评论区的饭圈现象也不严重。如今,反观前文《雪Distance》的评论区,更多的是没营养的、乌烟瘴气的抽象文学,还有比比皆是的“饭圈互撕”“你行你上”,这样的网易云与多年之前,已经有了一道鸿沟。

  • 热评有哪些关键词?

我们还是用之前的python文件来生成词云这是热门评论的关键词:

下面是普通评论的关键词:

定性来看,热评对于“情感”的描述会更多,诸如“喜欢”和“爱”,以及“希望”和“感情”,人对于美好的向往永远是热评的底色;普通的评论涵盖的面便更广了,对于歌曲本身的评价也相对多一些,比如“好听”“前奏”等;一般的评论还倾向于描述评论者此刻的感受,这是热评里面比较少见的,如“想你”“晚安”“难过”等。

为了看得更清楚一些,下面我们展示热门评论和普通评论的热词排行:

hot_words <- read.table(file = "word_freq_hot.csv",header = TRUE,encoding = 'UTF-8',sep = ",",comment.char = "",quote = "",fill = TRUE, allowEscapes = TRUE)
hot_words <- hot_words[order(hot_words$value, decreasing = TRUE)[1:5],c(2,3)]
plot_hot <- ggplot(data = hot_words,aes(x=reorder(key,-value),y=value,fill=key,colour=key)) + geom_bar(stat = "identity",width=0.8,alpha=0.5) + labs(x = "", y = "出现次数") + ggtitle("热评高频词") + theme_classic() + theme(plot.title = element_text(hjust = 0.5))
plot_hot

这与网易云的特色和当代年轻人的心里状况完全符合。“喜欢”和“爱”是贯穿我们一生的话题,也是我们永恒的追求,但是还是“一个人”的你,曾因为感情而“大哭”,但是在生活中仍能看到“希望”。

我们再看看一般的评论都有哪些高频词:

new_words <- read.table(file = "word_freq_new.csv",header = TRUE,encoding = 'UTF-8',sep = ",",comment.char = "",quote = "",fill = TRUE, allowEscapes = TRUE)
new_words <- new_words[order(new_words$value, decreasing = TRUE)[1:5],c(2,3)]
plot_new <- ggplot(data = new_words,aes(x=reorder(key,-value),y=value,fill=key,colour=key)) + geom_bar(stat = "identity",width=0.8,alpha=0.5) + labs(x = "", y = "出现次数") + ggtitle("普通评论高频词") + theme_classic() + theme(plot.title = element_text(hjust = 0.5))
plot_new

这是个颇为有趣的结果,“喜欢”和”爱“热度不减,后面的词汇”流泪“跟情绪有关,而且是负面的。说明网易云音乐的很多用户倾向于把情绪释放在评论区里,让眼泪在现实里暂时憋着,转而倾泻于歌里。“好听”则很常见了,但是这类词汇在热评里面不算多见。”男朋友“一词或许能反映,那些经常在网易云评论区发表于感情相关的评论人更有可能是女生,所以我建议这些女生报考中国科学技术大学。

  • 评论的感情分布如何?

评论区对于一些人来说更多是交流情感的场所,而我们从关键词的频率里面看到,这些情感更有可能是负面的,难道热评、普通评论情感基调都是负面的吗?这显然不太可能。我们进一步用数据说明这一点。我们继续沿用百度的paddlepaddle预训练模型,虽然模型时常误判,但是大体上的判断还是有参考价值的。

我们先讲必要信息写入文件,转入python处理。

hc_emo <- hc[,c("username","content","评论类型")]
rc_emo <- rc[,c("username","content","评论类型")]
xd[,"评论类型"] <- "雪Distance"
xd_emo <- xd[,c("username","content","评论类型")]
all_emo <- rbind(hc_emo, rc_emo, xd_emo)
all_emo[which(all_emo[,"username"]=="帐号已注销"),"评论类型"] <- "账号已注销"
all_emo <- all_emo[,c("content","评论类型")]
write.csv(all_emo, file = "all_emo.csv")

在另一边,所有的评论附带上其正向反馈概率值回到all_emotion_probs.csv,读取并作图如下:

emo_probs <- read.table(file = "all_emotion_probs.csv",header = TRUE,encoding = 'UTF-8',sep = ",",comment.char = "",quote = "",fill = TRUE, allowEscapes = TRUE)
emo_plot <- ggplot(emo_probs, aes(x=评论类型,y=positive_probs,fill=评论类型,colour=评论类型)) + geom_boxplot(alpha=0.5) + stat_summary(fun.y = mean, geom = "point", size = 2, shape = 3) + ylab("正向情感概率") + ggtitle("不同类型评论的正向情感概率分布") + theme_classic() + theme(plot.title = element_text(hjust = 0.5))
emo_plot

这表明了,不论是哪种评论,评论区里面正向的感情均值在0.70以上,可见评论区里面消极评论并不多。这是合理的,因为一个人在评论区里留言,大概率他还是愿意听这首歌的,因此他不大会留下对这首歌消极的评论,除非是单纯地抒发自己的一些负面情绪。账号已注销这一类情绪比热评或者普通评论均值略低,波动略高,差距非常小。相比其他三者,第一部分分析的《雪Distance》这首歌的风评之差尽览无遗。值得注意的是这个正向概率肯定是不准确的,但是在大样本下相对是准确的,比如说可以明显反映第二部分的样本和《雪Distance》评论样本感情的差距。

3.2.3 更进一步:热评的点赞和回复

热评一定赞数很高吗?其实热评是相对于每一首歌而言的。所以在热评中赞数也有高低之分的。先定性查看热评和普通评论的赞数分布:

library("gridExtra")
library(RColorBrewer)
hc_likes <- hc[,c("likedcount", "replycount","评论类型")]
rc_likes <- rc[,c("likedcount", "replycount","评论类型")]
p1 <- ggplot(data = hc_likes, aes(x=likedcount),color=brewer.pal(2,"Pastel1")[1]) + geom_histogram(aes(y=..density..),alpha=0.5,fill=brewer.pal(2,"Pastel1")[1]) + labs(x = "赞数", y = "频率") + ggtitle("热评赞数") + theme(plot.title = element_text(hjust = 0.5)) + xlim(0,100000) + geom_vline(aes(xintercept=median(likedcount)))
p2 <- ggplot(data = rc_likes, aes(x=likedcount),color=brewer.pal(2,"Pastel1")[1]) + geom_histogram(aes(y=..density..),alpha=0.5,fill=brewer.pal(2,"Pastel1")[2]) + labs(x = "赞数", y = "频率") + ggtitle("普通评论赞数") + theme(plot.title = element_text(hjust = 0.5)) + xlim(0,30) + geom_vline(aes(xintercept=mean(likedcount)))
grid.arrange(p1,p2,nrow=1)

概括地说,热评的赞数一般在25000上下;而普通评论获赞平均不超过两个。我们再关注一下10万以上特别高赞的评论:

high_likes <- hc_likes[hc_likes[,"likedcount"]>100000,]
high_likes <- hc[which(hc[,"likedcount"] %in% high_likes$likedcount),]
summary(high_likes$timeStr)
##         Min.      1st Qu.       Median         Mean      3rd Qu.         Max. 
## "2014-04-06" "2016-02-06" "2017-07-12" "2017-06-28" "2018-11-13" "2021-11-16"

我们可以看出来,在这些赞数破10万的超高赞评论中,最晚的出现在近两年前,平均出现在6年之前。因此,现在发布的评论,在现今网易云音乐的大环境下,很难在一年之内赞数破10万。超高赞的产生既需要契机,更需要时间的沉淀。

热度高的评价,不仅会有很多人留下他们的“赞”,还会有一定的话题性,吸引大量用户回复这个热评。高的点赞量,说明很多人赞同这条评论,或者觉得这条评论说得好;高的回复量说明这条评论的话题性很强。我们开始猜想,“字数”会不会是影响回复量和点赞量的一个重要指标呢?

library(plotly)
hc_likes <- hc[,c("likedcount", "replycount", "评论字数", "评论年份")]
for (i in 1:nrow(hc_likes)) {
  if(hc_likes[i,"评论年份"]<2017){
    hc_likes[i,"评论时段"] <- "早期"
  }else if(hc_likes[i,"评论年份"]<2020){
    hc_likes[i,"评论时段"] <- "2017-2019"
  }else{
    hc_likes[i,"评论时段"] <- "2020及以后"
  }
}
hc_likes_1 <- hc_likes[hc_likes[,"评论时段"]=="早期",]
plot_ly(hc_likes,x=~评论字数,y=~likedcount,z=~replycount,color=~评论时段)

(移动鼠标可以交互查看此图)

这个图可以定性反映一些事实:

  • 1.超高赞或超高回复量的评论几乎都在2020年以前。在这之后,“云村”像这样的现象几乎绝迹。

  • 2.考察replycount-评论字数平面,总体分布相对均匀,跟帖量较高的评论要么字数很少(30字以内),要么字数很多(120-150字),字数过多的热评获赞或者跟帖数普遍较少,而且到了2020年,热评的字数没有多于150字。

  • 3.考察likedcount-评论字数平面,总体密度函数定性来看单调递减,点赞数最高的评论往往字数较少

为了放大这些这些定性结论,我们分别观察点赞数、回复数与评论字数的关系。

ggplot(data = hc_likes, aes(x=评论字数,y=likedcount,fill=评论时段,colour=评论时段)) + geom_point(alpha=0.5) + facet_wrap(~ 评论时段) + theme_bw() + labs(x = "评论字数", y = "赞数") + ggtitle("不同时段热评的赞数和字数的关系") + theme(plot.title = element_text(hjust = 0.5)) + geom_rug(position = 'jitter', size = 0.1)

我们看到,对于早期的热评,简短的也好,长篇的故事也好,都能收获较高的赞数。到了17-19年,点赞数量相比上一阶段全面提升,这也对应了我之前提到,这段时间是网易云最为纯粹的一段时期。在这段时期里,什么样的评论无论字数,都可以获得可观点赞数,当然了,高赞评论还是更多地出现在30字以内短评和140字左右长评中。到了20年以后,热评整体字数缩水,标志着网易云社区氛围走下坡路的开始。这段时期评论总体赞数较低,相对赞数较高的评论仍然偏向于出现在30字以内短评和140字左右长评中。

评论的赞数为何有这种双峰分布的倾向?首先,我认为,现在的人点赞的频率越来越低。就我而言我自己也很少给评论点赞除非它说的真的特别好。简单的句子往往在一瞬间击中心灵,这种短时间内的刺激很容易促使用户给出他手中的赞;而长评往往故事性较强,读完之后回味悠长,而且人们总是有种倾向,认为字数多的评论”一般不会太差“,所以这种评论也很有可能拿到高赞。

我们继续考察回复数和字数的关系:

ggplot(data = hc_likes, aes(x=评论字数,y=replycount,fill=评论时段,colour=评论时段)) + geom_point(alpha=0.5) + facet_wrap(~ 评论时段 ) + theme_bw() + labs(x = "评论字数", y = "回复数") + ggtitle("不同时段跟帖数和字数的关系") + theme(plot.title = element_text(hjust = 0.5)) + geom_rug(position = 'jitter', size = 0.1) + scale_fill_brewer(palette = "Pastel1")

首先我们能发现的是,在2020年之后,几乎没有先前那样10000+跟帖数的现象级热评。2017-2019是现象级热评的高产时期。每个时期的跟帖量都有亲短评和长评的性质,与点赞方面的情况一致;2020年中等长度评论(约60-110字)的回复量降到历史最低,同期相比于短评论和长评论也在跟帖数目上被碾压。

我们大致可以认为,任何时期,高赞、高回复的热评的字数出现频率是50字以内>120-150字左右>>60~110字。如今热评更多地出现在短评论中是一个趋势,这种趋势是令人惋惜的,但也是无法阻挡的。不过好在,这个样本是一个多样性下的平均。在网易云的一些亚文化小圈子,评论的氛围仍然很好,你仍然可以看到很多有营养的、让人回味的评论,譬如说纯音乐区的评论就是一股清流。当年让我印象深刻的是《城南花已开》的评论区,里面讲述了一个令人遗憾又让人心生暖意的故事。最高赞的评论超过了170万,回复数近3万,堪称网易云音乐镇站级别的现象级评论。如今,五年前的老用户已经老了5岁,可能当时还还在上学的他现在已经忙于生活,为了生计而奔波。网易云的用户在不断更新,但是其鼎盛时期上演的诸多“现象”,或许会在每个老用户心里留下难以抹别的印记,最终化作时代的眼泪吧。

评论质量的下降、热评字数和内涵的缩水几乎成了必然,你几乎不能指望现在的环境能造就新的现象了。不过我仍然希望“云村”里面的一些小圈子能维持住本身的质量和活力,为网易云音乐多保留一些纯粹的东西。

3.2.4 云村发展:透过关键词看变化

前文用过评论的字数、点赞数以及跟帖数随时间的变化,阐释了网易云这几年来大环境一直在不断变化的事实以及导致这种现象的可能原因。作为全文分析部分的收束,这里展示网易云音乐三个阶段的热评词云:

all_comments <- hc[,c("content","timeStr","评论年份")]
for (i in 1:nrow(all_comments)) {
  if(all_comments[i,"评论年份"]<2017){
    all_comments[i,"评论时段"] <- "早期"
  }else if(all_comments[i,"评论年份"]<2020){
    all_comments[i,"评论时段"] <- "2017-2019"
  }else{
    all_comments[i,"评论时段"] <- "2020及以后"
  }
}
all_comments <- all_comments[,c("content","评论时段")]
all_comments_1 <- all_comments[all_comments[,"评论时段"]=="早期",]
all_comments_2 <- all_comments[all_comments[,"评论时段"]=="2017-2019",]
all_comments_3 <- all_comments[all_comments[,"评论时段"]=="2020及以后",]
write.csv(all_comments_1, file = "all_comments_1.csv")
write.csv(all_comments_2, file = "all_comments_2.csv")
write.csv(all_comments_3, file = "all_comments_3.csv")

从图中看到,早期的用户讨论的话题略显沉重,如“孤独”“结婚”等,而前文所言17-19年鼎盛时期,新添了很多正能量元素,如“加油”“努力”“感谢”“可爱”等等。为什么我认为这段时间的网易云是最棒的?因为这段时期用户质量高,评论既有情感元素,也有很多正能量鼓舞人心。20年之后,随着用户年龄的下移,一些热评讨论的内容促使了“男孩子”“女孩子”“温柔”这些词词频的上升。这一代用户探讨的话题深度就大幅下降,不过也有着浓浓的青春味道。

这几幅图的共性是远盖过个性的。不论哪个时期,喜欢、希望与爱;一个人、第一次与未来,是网易云云村永远不会褪色的话题。我们每个人也一样。

4.总结

4.1 结论

首先,我们分析了时下具有争议的热门单曲《雪Distance》的评论,得到以下结论:

  • 其评论数在初期及天之内暴涨之后先后经历了两次热度的回升,分别跟这首歌被曝出涉嫌抄袭和四月中旬歌手Capper的争议言论有关。

  • 上述两次热度的回升均伴随着歌曲风评的下降。

  • 评论区在3月5日存在刷评论行为,主要体现为大量重复、无意义语句。但是这种刷评论并不是在单一属地“机刷”,而更有可能是遍布全国的粉丝群体所为。

  • 在歌曲下喜欢留下重复评论的用户除了一大批聚集在3月5号统一行动之外,其余的在每一天分布近乎均匀。

  • 评论区每次风评下降都会伴随着大量时下流行的抽象网络语言的出现,如“丁真”“答辩”“泰裤辣”等;评论区也不乏正面词汇,可以判断歌曲本身也有可圈可点之处。

  • 负面评论的“喷法”大同小异,很少有理性客观分析。判断为看客居多,大量的人是被带了节奏的。

接着,我们放眼整个网易云音乐的评论区,以2000余首华语热歌为样本探究了热评的一些性质:

  • 音乐人的身份更容易让用户登上热门。善于这样做的音乐人有徐秉龙、颜人中等。一般的用户相比之下更难上热评,一般来讲很少有上榜两次及以上的人。用户“长夜看海”善于发表优质评论,在样本记录中就有10次上过热评。

  • 官方号也容易登上热评,一些大V如网易CEO丁磊等时不时做客评论区会带来大量热度;

  • 无论是字数出现的频率、赞数随字数的分布还是跟帖数随字数的分布,都服从双峰分布,并且字数较低的峰更高。换言之,样本中的热评更有可能是30字以内短评或者120-150字长评。字数在70-110或者多于150字的评论在评论区较为少见。

  • 评论区的“抱一抱”功能过于冷门,以至于样本中没有记录。

  • 热评对于“情感”的描述会更多,诸如“喜欢”和“爱”,以及“希望”和“感情”,人对于美好的向往永远是热评的底色;普通的评论涵盖的面便更广了,对于歌曲本身的评价也相对多一些,比如“好听”“前奏”等;一般的评论还倾向于描述评论者此刻的感受,这是热评里面比较少见的,如“想你”“晚安”“难过”等。

  • 无论是什么样的评论,他们出现在评论区里面的情感正向概率是非常高的。

  • “账号已注销”评论的关键词更多与情感有关,而且这种情感有不少是负面的。但是“账号已注销”的情感分布大体与主流评论一致,不过波动稍大。“账号已注销”是网易云较为吸引人注意的群体之一,往往有着复杂而立体的形象。

  • 上热评的要素大致总结如下:

    • 上述表述并不代表短的评论就更容易上热评,相反,长的评论更容易上热评,但是一旦较为短的评论上了热评,它的热度往往比前者高。
    • 上热评需要“早”评论,这体现在在评论区现存评论较少的时候发表评论。这一点在当今流行音乐的范畴要求较高,一般要求卡在歌曲刚出不久的时候发才有可能上热评;如果听众的眼光比较独特,在一些可能会火小众歌曲留下具有前瞻性的评论,是在当今网易云音乐大环境下最有可能上热评的选择之一。
    • 发布短评论上热门难度较大,但是一旦成功热度将不会很低。
    • 从关键词来看,热评更加注重情感,可以少把笔墨花在歌曲本身,多描摹情感体验,主打细腻真实。
  • 从数据随时间变化看得出网易云音乐的评论氛围有着变化:

    • 字数方面,“短热评”数量从2021年到2016年逐年递减,到了2015,2014年反而有增长趋势;“长热评”在2015-2019年较多,而从2020年开始,长热评的比例越来越少了。
    • 点赞和回复方面,用户的积极性在2017-2019年到达顶峰,2020年左右开始走下坡路。
    • 导致这些变迁的原因与网易云用户的更新、饭圈文化的涌入以及快餐文化的盛行有着密不可分的关系。
  • 我的评价:网易云评论区的整体氛围在走下坡路,而遗憾的是这近乎是无法逆转也无法改变的。我希望用户沉浸在情感享受音乐的同时也要保持清醒,切莫被轻易带节奏。我也希望用户能多多贡献有价值有营养的评论,少耍点小聪明,少抖机灵。希望像《雪Distance》这样的评论区越来越少,多一些17年左右纯音乐的感觉就更好了。

(正文完)

4.2 存在的问题及我的感想

感想还是蛮多的。这一次选题目我几乎没有思考立刻选择了研究这个项目,因为作为一个村龄5年有余的用户、年听歌时长超过2000小时的闷骚少年,我非常愿意为这款软件献上自己也许不太专业、不太严谨但是足够走心的报告。这个报告我做着做着慢慢发现自己已经不是在做作业了,我完全是一个想法接一个想法冒出来,再顺着去实现。因此报告里不可避免的有私货或者是情绪化的表达,原因可能真的是我做“上头”了;当然我也希望自己用尽可能接地气的语言,以不负数据分析的初衷——把数据背后的信息尽可能多地、尽可能完整准确地传达给读者。历时快一个星期做完作业的我还是有些许成就感的。

然而回头看,自己觉得可能经历很多,但是一篇报告读下来我觉得这篇报告差的东西太多了。首先我研究的手段太过拙劣,几乎只会画直方图,密度图和箱线图,结论背后明没有体现多么深刻的统计学思想,这是我的极大短板,也是再怎么做也弥补不了的。我使用的语言也不太统一,几乎是python和R五五开了,哪边觉得简单用哪边;而且python那边添加的注释太少,我可能只有一半的内容加了注释。最后,我的样本高度局限。网易云歌曲千千万,这次我仅仅选取了华语乐坛有代表性的歌曲及评论。还有很多的分区有待深究。因此我现阶段得出的结论只对于华语歌曲“上热评”有一定参考价值。

回想起来给我造成困扰最大的或许是爬数据了。API经常不稳定,数据弄不小来的时候确实很紧张。再加上我拿到的是很恶心的格式,需要转换。还有就是之前装anaconda的时候不懂事,瞎建文件夹,我在生成词云的过程中遇到了无数报错,最后一气之下重装一遍,把我搞得半条命都没了。

我深夜总是一边听歌一边写代码,写着写着我总会想起三年前,是在网易云的时光陪我度过了最艰难的日子,写着写着有时候还会鼻子一酸。那个时候的自己情感突然变得丰富起来,我也是在那会儿成为了狂热用户,只是依稀记得,会员是同样的价格,我只会给网易云续费,再也不用QQ音乐了。在那之后我也试过QQ音乐,只看到里面蔡徐坤、时代少年团底下清一色的饭圈评论,我随便说了一句马上就被喷了,于是我立刻离开了。

正如正文里面提到,网易云现在很难再在造就新的现象了。但在其中徜徉的日子,留下来的记忆难以磨灭。如果网易云音乐没有烂到一定地步,我仍会做它的忠实用户。我也希望我自己在意的一些圈子,尽可能的远离浮躁的大环境,继续维持一方友好、有内涵而又很治愈的天地。

谨以此文献给陪伴我许久的网易云音乐。