当前位置:   article > 正文

网易云音乐爬虫实战——肖战《红梅赞》下评论数据挖掘与分析_网易云音乐反爬

网易云音乐反爬

前言

这个学期终于结束,空余时间慢慢多了。正逢最近肖战余温又起,不如拿网易云练练手,蹭蹭这波热度。让我们本着科学的精神,用python爬虫和数据可视化来分析一下,究竟是怎样一首翻唱能在不到三个月内获得网易云评论100万+的成就。
本文以2020年7月1日0:00-23.59网易云歌曲“肖战 《红梅赞》”下评论进行分析。

本章工具

  • pycharm编译器
  • python3.7环境
  • 来自Binaryify的网易云音乐API这里是他的GitHub主页
  • 重要第三方库:requests、pandas、pyecharts等

这里重点感谢一下Binaryify的API,应该是目前最优秀的网易云音乐API,功能非常强大且相比于官方API不容易被封

数据挖掘部分

1.获取歌曲评论

最开始用的官方API:http://music.163.com/api/v1/resource/comments/R_SO_4_1439975538,但是因为网易云的反爬虫机制,会出现以下错误在这里插入图片描述
然后就找到了Binaryify开发的NeteaseCloudMusicApi,这里再次感谢Binaryify的开发与维护。
官方文档

# 获取URL
def get_url(Offset):
    url = 'http://localhost:3000/comment/music?id=1439975538&offset=' + str(Offset * 20) + '&limit=20'
    return url

# 获取评论
def get_20_imf(now_url):
    r = requests.get(now_url, headers=headers)
    # 评论信息
    result = r.json()['comments']
    # 用户ID
    user_ID = [n['user']['userId'] for n in result]
    # 用户名
    user_name = [n['user']['nickname'] for n in result]
    # 评论时间
    content_time = [n['time'] for n in result]
    # 评论内容
    content = [n['content'] for n in result]
    # 点赞数
    like_count = [n['likedCount'] for n in result]
    imf = pd.DataFrame({
        'userID': user_ID,
        'user_name': user_name,
        'content_time': content_time,
        'content': content,
        'like_count': like_count
    })
    return imf

#存入本地csv文件
HMZ = pd.DataFrame()
for i in range(60):  # 每次最多60页
    url = get_url(i)
    imf = get_20_imf(url)
    HMZ = HMZ.append(imf, ignore_index=True)
    print(i)
    # 休眠一秒
    time.sleep(1)
HMZ.to_csv('D:\\HMZ7.csv', sep=',', header=True, index=True)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

在这里插入图片描述
顺利爬取评论信息,对部分格式进行处理

def IdTrans(userID):
    """ID去小数点变字符串"""
    userID = str(int(userID))
    return userID
data_hmz['userID'] = data_hmz['userID'].apply(lambda x: IdTrans(x))

def likedTrans(like_count):
    """点赞数去小数点"""
    like_count = int(like_count)
    return like_count
data_hmz['like_count'] = data_hmz['like_count'].apply(lambda x: likedTrans(x))

def timeTrans(content_time):
    """时间变为时分秒格式"""
    second = float(content_time / 1000)
    timeArray = time.localtime(second)
    content_time = time.strftime("%Y-%m-%d %H:%M:%S", timeArray)
    return content_time
data_hmz['content_time'] = data_hmz['content_time'].apply(lambda x: timeTrans(x))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

处理过后:
在这里插入图片描述
最终合并7月1日当天评论信息数据共2717条。

2.根据ID获取用户信息

从上文得到的评论信息提取‘userId’字段,获取用户的公开数据。这里用到另一个接口:在这里插入图片描述
主要代码:

def get_user(user_id):
    # 获取用户信息
    data = {}
    url = 'http://localhost:3000/user/detail?uid=' + str(user_id)
    response = requests.get(url=url, headers=headers)
    js = json.loads(response.text)
    if js['code'] == 200:
    	# 性别
        data['gender'] = js['profile']['gender']
        if int(js['profile']['birthday']) < 0:
            # 年龄
            data['age'] = 0
        else:
            data['age'] = (2020 - 1970) - (int(js['profile']['birthday']) // (1000 * 365 * 24 * 3600))
            if int(data['age']) < 0:
                data['age'] = 0
        # 省份
        data['city'] = js['profile']['province']
        # 签名
        data['sign'] = js['profile']['signature']
    else:
        data['gender'] = '无'
        data['age'] = '无'
        data['city'] = '无'
        data['sign'] = '无'
    return data
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

用户信息:
在这里插入图片描述
用户信息爬取完成,共515条用户信息。这也意味着7月1日当天产生的2717条评论来自于515名网易云用户,人均5.3条评论。

数据分析部分

1.评论数时间分布

评论热度按小时分布画出折线图:


data_hmz['content_time'] = pd.to_datetime(data_hmz['content_time'])
hmzHour = data_hmz.content_time.dt.hour
hour_num = hmzHour.value_counts().sort_index()
hs = [str(h) for h in hour_num.index.tolist()]

# 折线图
line1 = (Line(init_opts=opts.InitOpts(width='1350px', height='350px'))
         .add_xaxis(hs)
         .add_yaxis('热度', hour_num.values.tolist(), label_opts=opts.LabelOpts(is_show=False))
         .set_global_opts(title_opts=opts.TitleOpts(title='评论数时间(按小时分布)'), visualmap_opts=opts.VisualMapOpts(max_=350))
         .set_series_opts(linestyle_opts=opts.LineStyleOpts(width=3)))
line1.render()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在这里插入图片描述
可以发现评论的时间主要集中在晚上8点到12点,并且呈现出比较明显的三级分布:

  • 0时-8时:低
  • 8时-20时:中,平均每小时评论数100条左右
  • 20时-24时:高,平均每小时300条左右

可以看出此歌受众者很多有睡前(20-24时)听歌的习惯,休息时间(0-8时)、工作与学习时间(8-20时)听歌频率较少。

2.评论内容词云

这里用到jieba库进行中文分词,wordcloud库绘制词云图片:

ata_hmz = pd.read_csv('data_hmz.csv')
cList = data_hmz.content.value_counts().sort_index().index.tolist()
text = " ".join(cList)

# 用jieba中文分词
jieba.load_userdict("dict.txt")
wordlist_jieba = jieba.lcut(text, cut_all=True)
wl_space_split = " ".join(wordlist_jieba)
# 绘图
my_wordcloud = wordcloud.WordCloud(background_color='white',
                                   width=1000,
                                   height=700,
                                   font_path='msyh.ttc',
                                   max_words=2000,
                                   scale=20,
                                   # 优化虚词
                                   stopwords={'什么','我们','你们','不是','就是','自己'})
my_wordcloud.generate(wl_space_split)
my_wordcloud.to_file('词云.png')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

在这里插入图片描述
观察词云图片,大部分词应该出自肖战粉丝之口,如“哥哥”、“粉丝”、“加油”、“顺利”等。也有部分负面词语:“举报”、“抵制”、“讨厌肖战”、以及最近获得的金“扫帚”奖等

3.年龄分布柱状图

绘图分析年龄分布情况:

# 分箱
age_num['age_cut'] = pd.cut(age_num.age, bins=[10, 15, 20, 25, 30, 35, 40, 45])

# 分组汇总
age_cut_num = age_num.groupby('age_cut')['num'].sum()

# 绘图
bar1 = Bar(init_opts=opts.InitOpts(width='1350px', height='750px'))
bar1.add_xaxis(age_cut_num.index.astype('str').tolist())
bar1.add_yaxis("数量", age_cut_num.tolist(), category_gap='20%')
bar1.set_global_opts(title_opts=opts.TitleOpts(title='评论用户年龄分布'),
                     visualmap_opts=opts.VisualMapOpts(max_=180),
                     toolbox_opts=opts.ToolboxOpts())
bar1.render()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在这里插入图片描述
在这里插入图片描述
年龄分布情况有点让我吃惊,高达74%的用户年龄无法查看——或是为了保护隐私,或是因为网易云社区风气,或是没有设置这些信息。
在已知的年龄信息中可以看到,主要年龄集中在(15,20]区间内,说明主要受众是15-20岁学生群体。另一个有趣的信息是频数第一的年龄为30岁,(25,30]区间也是肖战粉丝的主力军,难道这就是妈妈粉的由来?[/滑稽]

4.性别分布饼图

将性别数据绘成饼图:

pie1 = Pie(init_opts=opts.InitOpts(width='1200px',height='600px'))
pie1.add("",
         [*zip(['女', '未知', '男'],gender_percent.values)],
         radius=["40%", "65%"])
pie1.set_global_opts(title_opts=opts.TitleOpts(title='评论用户性别分布'),
                     legend_opts=opts.LegendOpts(orient="vertical", pos_top="15%", pos_left="2%"),
                     toolbox_opts=opts.TitleOpts())
pie1.set_series_opts(label_opts=opts.LabelOpts(formatter="{b} : {c}%"))
pie1.set_colors(['#D7655A', '#FFAF34', '#3B7BA9', '#EF9050', '#6FB27C'])
pie1.render()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在这里插入图片描述
性别分布比较明显,女性比例达55%,男性则不到20%,还有约25%用户没有公开性别信息。

综上,评论用户以15-20岁女性为主,男女比例约为11:4,评论中粉丝发言比例很高,语言较积极。所以,肖战凉了这个结论现在还为时尚早。

5.热评分析

在这里插入图片描述
肖战翻唱《红梅赞》版本下热评可谓魔幻。
15条热评全部发表在4月13日歌曲发布的7分钟内,且全部为高度赞扬的正面评价,共收获184.1万点赞。
其中4条热评甚至发表于歌曲发布3分钟内,而歌曲时长却大于3分钟。这意味着歌还没有播放完评论就已经发出,并且成为了点赞数最多的15条评论之一。

结语

说到红梅赞,这首闫肃作词的爱国歌曲,曾经是歌剧《江姐》的主题歌。5天前的6月27日,《烈火中永生》中江姐的扮演者于蓝奶奶永远地离开了我们。
在这个流量至上的时代,希望这种“流量焦点”的粉丝,能多去了解歌曲背后的故事,而不是单纯盲目地追求明星与流量、数据。
最后,本文仅为一次对网易云音乐的python爬虫实战,不针对任何人或事件,请勿上升高度。

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

闽ICP备14008679号