周末,打开手机听听音乐放松下,发现手机里的音乐好久没换了,想听点其他歌却不知道换什么歌,你们有没有遇到这样的听歌慌,今天就用 python 爬虫来爬取网易云音乐里不同类型歌手的 top 50 热门歌曲。
项目环境
语言环境:python 3.6
编辑工具:PyCharm
模块导入:BeautifulSoup、re、selenium、csv
爬取结果
爬取的数据只用了两列,第一列显示歌手姓名,第二列显示该歌手在网易云音乐里的 top 50 热门歌曲。
程序结构
程序主要是由 6 个函数组成:
get_singer():提取源码中歌手的名字。
song_url():拼接各个歌手的 top 50 歌曲的url。
song_name():根据上面函数提供的歌曲 url 提取 50 首热门歌曲的歌名。
get_data():处理需要保存的数据。
download2csv:将歌曲保存为 csv 文件。
源码提取
分析源码发现需要提取的歌手信息只在 Elements 里面出现,源代码中找不到这些信息,说明这些信息没有放在源代码中,对于这种情况,我们就不能用之前的 requests 方法来提取源码信息了,我们这次用 selenium 自动化测试库来模拟人工打开页面,这种方法提取的就是 Elements 出现的信息,也就是我们需要的信息。关于这两种方法的区别,下篇文章会详细分析。
Python
browser = webdriver.Chrome()
wait = WebDriverWait(browser,5) #设置等待时间
1
2
browser=webdriver.Chrome()
wait=WebDriverWait(browser,5)#设置等待时间
我用的是 chrome 浏览器,此处需要把 chromedriver 驱动下载好放在 python 3 的安装目录下方可操作浏览器。
Python
browser.get(url)
browser.switch_to.frame('g_iframe')
html = browser.page_source
soup=BeautifulSoup(html,'lxml')
1
2
3
4
browser.get(url)
browser.switch_to.frame('g_iframe')
html=browser.page_source
soup=BeautifulSoup(html,'lxml')
用 selenium 操作浏览器需要注意切换框架,因为有可能我们需要的元素的不在主框架里,需要用 switch_to.frame 方法切换到包含元素的子框架。
Python
info=soup.select('.nm.nm-icn.f-thide.s-fc0')
sname=[]
songids=[]
for snames in info:
name=snames.get_text()
songid=str(re.findall('href="(.*?)"',str(snames))).split('=')[1].split('\'')[0]
sname.append(name)
songids.append(songid)
return sname,songids
1
2
3
4
5
6
7
8
9
info=soup.select('.nm.nm-icn.f-thide.s-fc0')
sname=[]
songids=[]
forsnamesininfo:
name=snames.get_text()
songid=str(re.findall('href="(.*?)"',str(snames))).split('=')[1].split('\'')[0]
sname.append(name)
songids.append(songid)
returnsname,songids
用 BeautifulSoup 和 re 库从源码中提取出歌手名字和 top 50 歌曲的链接 id。
获取 top 50 歌曲名
先通过上面 get_singer() 函数返回的 songids 来拼接 top 50 歌曲 url,每个歌手对应的 top 50 歌曲 是唯一的。
Python
def song_url():
sname, songids = get_singer(url)
top50urls=[]
for id in songids:
top50url = '/#/artist?id={}'.format(id)
top50urls.append(top50url)
return top50urls
1
2
3
4
5
6
7
defsong_url():
sname,songids=get_singer(url)
top50urls=[]
foridinsongids:
top50url='/#/artist?id={}'.format(id)
top50urls.append(top50url)
returntop50urls
1
歌曲 url 有了,我们就可以用 selenium 库方法提取歌曲名字。
Python
def song_name():
songnames=[]
for top50url in song_url():
browser.get(top50url)
browser.switch_to.frame('g_iframe')
html = browser.page_source
soup = BeautifulSoup(html, 'lxml')
songinfo = soup.select('div div div span a b')
songname=re.findall('title="(.*?)"',str(songinfo))
songnames.append(songname)
return songnames
1
2
3
4
5
6
7
8
9
10
11
defsong_name():
songnames=[]
fortop50urlinsong_url():
browser.get(top50url)
browser.switch_to.frame('g_iframe')
html=browser.page_source
soup=BeautifulSoup(html,'lxml')
songinfo=soup.select('div div div span a b')
songname=re.findall('title="(.*?)"',str(songinfo))
songnames.append(songname)
returnsongnames
提取了歌曲名信息后,我们再把信息整合下。
Python
def get_data():
sname, songids=get_singer(url)
songnames=song_name()
data=[]
for snames,songs in zip(sname,songnames):
info = {}
info['歌手名字']=snames
info['top50歌曲'] =songs
for i in info:
for j in info[i]:
info2={i:j}
data.append(info2)
return data
1
2
3
4
5
6
7
8
9
10
11
12
13
defget_data():
sname,songids=get_singer(url)
songnames=song_name()
data=[]
forsnames,songsinzip(sname,songnames):
info={}
info['歌手名字']=snames
info['top50歌曲']=songs
foriininfo:
forjininfo[i]:
info2={i:j}
data.append(info2)
returndata
再把信息保存为 csv 文件。
Python
def download2csv():
print('保存歌手信息中...请稍后查看')
with open('E:\\歌手top50.csv','w',newline='',encoding='utf-8') as f:
fieldnames = ['歌手名字', 'top50歌曲']
writer=csv.DictWriter(f,fieldnames=fieldnames)
writer.writeheader()
data=get_data()
writer.writerows(data)
print('保存成功')
1
2
3
4
5
6
7
8
9
defdownload2csv():
print('保存歌手信息中...请稍后查看')
withopen('E:\\歌手top50.csv','w',newline='',encoding='utf-8')asf:
fieldnames=['歌手名字','top50歌曲']
writer=csv.DictWriter(f,fieldnames=fieldnames)
writer.writeheader()
data=get_data()
writer.writerows(data)
print('保存成功')
最后,调用函数就可以去保存想听的类型歌手的信息了。
Python
idlist=[1001,1002,1003,2001,2002,,4001,4002,4003,6001,6002,6003,7001,7002,7003]
#1开头:华语;2开头:欧美,4:其他;6:日本;7:韩国
id=1001
url='/#/discover/artist/cat?id={}&initial=-1'.format(str(id))
download2csv()
1
2
3
4
5
idlist=[1001,1002,1003,2001,2002,,4001,4002,4003,6001,6002,6003,7001,7002,7003]
#1开头:华语;2开头:欧美,4:其他;6:日本;7:韩国
id=1001
url='/#/discover/artist/cat?id={}&initial=-1'.format(str(id))
download2csv()
id 表示歌手的类型,1001 1002 1003 分别表示华语男歌手、女歌手、组合/乐队,2001 2002 分别表示欧美男歌手、女歌手、组合/乐队,6001 6002 6003 分别表示日本男歌手、女歌手、组合/乐队,7001 7002 7003 分别表示韩国男歌手、女歌手、组合/乐队,4001 4002 4003 分别表示其他男歌手、女歌手、组合/乐队。需要保存哪种类型歌手的信息,修改 id 的值即可。
保存后就可以用 Excel 文件形式打开保存的 csv 歌曲信息了,看看自己哪些歌没听过,听听你那些年错过的好歌,解决掉你的听歌慌。
完整代码可以在我公众号后台回复「网易云音乐」获取。