网易云音乐上万首hiphop歌曲解析rapper们的最爱(可视化篇)
胡萝卜酱首先道个歉,看见有人告诉我爬虫篇代码有问题,小编赶紧去检查,才发现把代码放错了,真是罪该万死,小编去跪键盘了。
错误的代码是爬歌词那里,首先是循环缩进出现问题,其次是变量名字写错,正确代码如下:
#获取歌词
import requests
import json
import re
lyric,lyric_name = [],[]
def get_lyric(id):
lrc_url = 'http://music.163.com/api/song/lyric?' + 'id=' + str(id) + '&lv=1&kv=1&tv=-1'
lyric_url = requests.get(lrc_url)
if (lyric_url.status_code == 200):
json_obj = lyric_url.text
j = json.loads(json_obj)
if 'lrc' in j:
lrc = j['lrc']['lyric']
pat = re.compile(r'\[.*\]')
lrc = re.sub(pat, "", lrc)
lrc = lrc.strip()
lyric.append(lrc)
else: #错误点
lyric.append("None")
for i in tqdm(range(len(lyric_data))):
k = lyric_data["song_id"][i].split('=')[-1]
get_lyric(k)
lyric_name.append(lyric_data["song_name"][i])
print (len(lyric))
lyric_infos = {'song_name': lyric_name, 'lyric': lyric} #错误点
song = pd.DataFrame(lyric_infos, columns=['song_name', 'lyric'])
song.to_csv("lyric.csv",encoding="utf_8_sig") 小编总共获得近15M的CSV文件,接下来就展开我们的分析吧。
01 数据清洗
数据清洗包括去除因无歌词而加进来的“None”以及“作词:”“作曲:”等字眼,小编用的是正则的方式,匹配去除了部分常见的词,你能根据自己的理解加入需要去除的字眼。代码如下:
import re
import pandas as pd
data = pd.read_csv("lyric.csv")
#print (data.head())
#清洗数据,去除带有“作词”“作曲”等词
lyr=data['lyric']
lyric_after=[]
for ly in lyr:
ly = str(ly)
pat=re.compile(r'\作曲.*?\r') #匹配作曲:....\r
ly=pat.sub('',ly)
pat=re.compile(r'\作词.*?\r')
ly=pat.sub('',ly)
pat=re.compile(r'\制作.*?\r')
ly=pat.sub('',ly)
pat=re.compile(r'\后期.*?\r')
ly=pat.sub('',ly)
pat=re.compile(r'\编曲.*?\r')
ly=pat.sub('',ly)
pat=re.compile(r'\verse.*?\r')
ly=pat.sub('',ly)
pat=re.compile(r'\\hook.*?\r')
ly=pat.sub('',ly)
pat=re.compile(r'\混.*?\r')
ly=pat.sub('',ly)
pat=re.compile(r'\混音.*?\r')
ly=pat.sub('',ly)
pat=re.compile(r'\音乐总监.*?\r')
ly=pat.sub('',ly)
pat=re.compile(r'\和声.*?\r')
ly=pat.sub('',ly)
pat=re.compile(r'None') #去除无歌词加进来的None
ly=pat.sub('',ly)
pat=re.compile(r'\n')
ly=pat.sub('',ly)
lyric_after.append(ly)
data['lyric']=lyric_after
#print (data.head()) 02 jieba分词
小编采用jieba将获得歌词进行分词,这样才能进行分析。值得注意的是,歌词里面同一词会有大写和小写共同出现的情况,而从wordcloud库中导出的STOPWORDS只包含小写,因此小编手动添加了几个常出现的词,你也能用此方式自定义英文停用词。同时,中文的停用词是小编在网上下载的TXT文件,可以https://raw.githubusercontent.com/dongxiexidian/Chinese/master/stopwords.dat右键页面另存为txt即可。代码如下:
from wordcloud import WordCloud, STOPWORDS
import jieba
#分词
lyric=''.join(data['lyric'])
segs=jieba.cut(lyric,True)
stopwords_english = STOPWORDS.copy()
stopwords_english.add("You")
stopwords_english.add("We")
stopwords_english.add("And")
stopwords_english.add("don")
stopwords_english.add("But")
stopwords_english.add("It")
stopwords_chinese = [line.strip() for line in open('stopwords_chinese.txt',encoding='UTF-8').readlines()]
#过滤点单个字
word_list=[]
for seg in segs:
if seg not in stopwords_english:
if seg not in stopwords_chinese:
if len(seg)>1:
word_list.append(seg)
word=pd.DataFrame({'word':word_list}) #分词后的数据框03 rapper最爱唱什么
第一步,当然是来看一下rapper最爱唱什么词呢,这里要注意一下,在停用词里面已经去除了‘I’,‘you’之类的词,所以我们在这部分是不会看见他们出现的。同时,我们去除了单个词,因此中文里面也不会出现“爱”和“做”等词(悄悄告诉你,这些词出现频率高的可怕)。
虽然我们爬取的歌曲包含了中英文,但前30最常用的词居然只有两个中文词:“世界”和“想要”。“know”,“love”,“baby”,“wanna”,“what”等词出现频率相当高,突然脑补rapper们常唱的那句“you know what?”,这里小编能不能猜测rapper最爱唱的是“情歌”?同时,还有一些小编看不懂的词,比如“re”和“ll”,这里难道是小编分词出现的问题!?(啊,崩溃!!!)
将中英文分开,来看看rapper最爱唱的是什么吧!
分开来看,突然觉得上面爱唱情歌的判断可能有点肤浅,“time”,“生活”,“希望”,“未来”等词出现的频率也是相当高的,看来rapper除了“love”,生活,梦想之类的也是他们最爱的主题,果然rapper就是“peace and love”!
同样,可以用词云图如下:
04 rapper最爱唱什么季节
说完“peace and love”,我们还能分析出来什么呢?这里以季节为例做个小小的展示。
春的比例最高,其次是夏,秋最少,看来rapper偏好于温暖的春天和热情的夏天啊。
可视化代码:
import matplotlib.pyplot as plt
import seaborn as sns
word_rank = word["word"].value_counts()
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']#指定默认字体
plt.rcParams['axes.unicode_minus'] =False # 解决保存图像是负号'-'显示为方块的问题
sns.set(font='SimHei') # 解决Seaborn中文显示问题
sns.set_context('talk')
#top30的词
fig = plt.figure(figsize=(20, 10))
ax = sns.barplot(x=word_rank[:30].index, y=word_rank[:30].values)
ax.set_title('Top30 of Word')
ax.set_xticklabels(word_rank.index, rotation=90)
#区分中英文
chinese,english = [],[]
for i in range(len(word)):
if u'\u4e00' <= word["word"][i] <=u'\u9fa5':
chinese.append(word["word"][i])
else:
english.append(word["word"][i])
chinese=pd.DataFrame({'word':chinese})
english=pd.DataFrame({'word':english})
english_rank = english["word"].value_counts()
chinese_rank = chinese["word"].value_counts()
rank = 20
#英文的top20的词
fig = plt.figure(figsize=(20, 10))
ax = sns.barplot(x=english_rank[:rank].index, y=english_rank[:rank].values)
ax.set_title('Top20 of English Word')
ax.set_xticklabels(english_rank.index, rotation=90)
#fig.savefig("english.jpg") #保存图片
#中文前20的词
fig = plt.figure(figsize=(20, 10))
sns.barplot(x=chinese_rank[:rank].index, y=chinese_rank[:rank].values)
ax.set_title('Top20 of Chinese Word')
ax.set_xticklabels(chinese_rank.index, rotation=90)
#fig.savefig("chinese.jpg") #保存图片
from pyecharts import WordCloud
wordcloud_english = WordCloud(width=1500, height=820)
wordcloud_english.add("", english_rank.index, english_rank.values, word_size_range=[20, 200], is_more_utils=True)
wordcloud_english.render("english.html")
wordcloud_chinese = WordCloud(width=1500, height=820)
wordcloud_chinese.add("", chinese_rank.index, chinese_rank.values, word_size_range=[20, 200], is_more_utils=True)
wordcloud_chinese.render("chinese.html")
#季节
spring,summer,autumn,winter = 0,0,0,0
for i in range (len(word)):
if "spring" in word["word"][i] or "春" in word["word"][i]:
spring = spring + 1
elif "summer" in word["word"][i] or "夏" in word["word"][i]:
summer = summer + 1
elif "autumn" in word["word"][i] or "秋" in word["word"][i]:
autumn = autumn + 1
elif "winter" in word["word"][i] or "冬" in word["word"][i]:
winter = winter + 1
else:
pass
from pyecharts import Pie
season = ['春','夏','秋','冬']
times = [spring,summer,autumn,winter]
mypie = Pie("提及季节次数",title_pos='center')
mypie.add("",season,times,radius=[40,75],label_text_color=None,is_label_show=True,
legend_orient='vertical',legend_pos='left')
mypie.render('season.html')05结语
本文只是做了一下数据的可视化,了解了一下rapper们的部分偏好。本来还想分析一下rapper们的脏话,然而,小编没有找到较丰富的脏话表,只能作罢,若你感兴趣,也可以分析他们喜爱的酒,车,究竟爱唱男孩还是女孩?本来想把押韵的部分写完,但是,小编先约会去了,下次再放出来
(明天就是七夕了,祝有对象的甜甜蜜蜜,没对象的代码无bug!!!)
更多代码和详解在QQ群:852113213)
此文花费了不少功夫,赞赏、点赞、转发都是对作者的认可和支持。