查看原文
其他

网易云音乐上万首hiphop歌曲解析rapper们的最爱(爬虫篇)

胡萝卜酱 DataGo数据狗 2019-04-07

去年那个夏天,《中国有嘻哈》火了,人人都知道了freestyle,知道了押韵。今夏,《中国新说唱》虽然热度不如去年了,但是吴亦凡的“skr”还是火了,好吧,这个“skr”最开始被群嘲用错了说法,但是居然被收进了美国俚语词典,也是蛮有趣的。其实胡萝卜酱第一次知道“skr”是在PGone的歌词里面,于是,抱着一颗好奇的心,胡萝卜想分析一下这些rapper的歌词里面偏爱于哪些词。不多说,直接上爬虫。

01 爬虫框架


为了获得说唱歌曲的信息,我们通过歌单分类下的说唱来获取歌单ID,然后根据歌单ID获取歌曲ID,在基于歌曲ID获得歌词。大致框架去下:


02 歌单ID


首先分析网页:

歌单信息就藏在标签“li”里面,打开一个“li”:

这里就藏有我们需要的信息,歌单的名称和ID,但是很遗憾的是,查看源代码你根本就发现不了这些信息,因为它是动态获取的。所以,我们这里采用了selenium库的webdriver(安装自行百度,有很多博客),可以直接获取到上述信息。代码如下:

import pandas as pd
from selenium import webdriver
from tqdm import tqdm
driver = webdriver.PhantomJS()

#获取歌单ID
i = 0
link,name = [],[]

#获取说唱分类下歌单的前三页,每页含有歌单35个
for i in range(0,71,35):
    print("\n获取第{}个页信息!".format( (i//35) +1))
    url = 'https://music.163.com/#/discover/playlist/?order=hot&cat=%E8%AF%B4%E5%94%B1&limit=35&offset='+str(i)
    driver.get(url)
    driver.switch_to.frame("contentFrame")
    data = driver.find_element_by_id("m-pl-container").find_elements_by_tag_name("li")
    for j in tqdm(range(len(data))):
        nb = data[j].find_element_by_class_name("nb").text
        msk = data[j].find_element_by_css_selector("a.msk")
        name.append(msk.get_attribute('title'))
        link.append(msk.get_attribute('href'))
        #print (link)
#url = driver.find_element_by_css_selector("a.zbtn.znxt").get_attribute('href')
infos = {'name': name, 'link': link}
playlist = pd.DataFrame(infos, columns=['name''link'])
playlist.to_csv("playlist.csv",encoding="utf_8_sig")

获取了三页数据,歌单共105个。


03 歌曲ID


首先分析歌单:

歌曲信息就在标签“tr”里面,这里我们用了和获取歌单ID一样的方法,代码如下:

#获取歌曲ID
data = pd.read_csv("playlist.csv")
print (data.head())
song_id = []
song_name = []
for i in tqdm(range(len(data))):
    print("\n获取第{}个歌单信息!".format( i +1))
    driver.get(data["link"][i])
    driver.switch_to.frame("contentFrame")
    data_song = driver.find_element_by_class_name("m-table").find_elements_by_tag_name("tr")
    for j in range(1,len(data_song)):
        song_name.append(data_song[j].find_element_by_css_selector("b").get_attribute('title'))
        song_id.append(data_song[j].find_element_by_css_selector("a").get_attribute('href'))
        #print (song_id)
song_infos = {'song_name': song_name, 'song_id': song_id}
song = pd.DataFrame(song_infos, columns=['song_name''song_id'])
song.to_csv("song.csv",encoding="utf_8_sig"

共获得歌曲13000多首。


03 歌词


歌词的获取本来打算按照上述的方法获得,但是因为有“展开”,我无法获取完整的歌词:

于是只好寻找API了,如下(id为歌曲id):

http://music.163.com/api/song/lyric?' + 'id=' + str(id) + '&lv=1&kv=1&tv=-1

上述的文字部分就是我们需要的歌词了,首先是对重复的歌曲去重,同时要注意没有歌词的情况,代码如下:

#获取歌词
data = pd.read_csv("song.csv")
print (data.head())
print (len(data))
print (type(data))
#去重
lyric_data = data.drop_duplicates(subset=['song_name','song_id'])
lyric_data = lyric_data.reset_index(drop=True)
print (len(lyric_data))
print (type(lyric_data))
#获取歌词
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("")


    #print(lrc)
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])

lyric_infos = {'song_name': song_name, 'lyric': lyric}
song = pd.DataFrame(lyric_infos, columns=['song_name''lyric'])
song.to_csv("lyric.csv",encoding="utf_8_sig")  


04 结语


本文只是爬取了说唱歌曲的歌词,如果你想要爬取评论的话,也是可以通过API爬取的。在下一次推送中,我们将对获得歌词进行数据分析,顺便告诉大家押韵的小秘密


更多代码和详解在QQ群:852113213)

此文花费了不少功夫,赞赏、点赞、转发都是对作者的认可和支持。

    您可能也对以下帖子感兴趣

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