使用python获取歌单音乐

前言

前几天听音乐的时候突然想到网易云音乐是可以通过外链公式来获得下载链接的,如下:

http://music.163.com/song/media/outer/url?id=ID数字.mp3

于是就思考:是否可以通过python批量获取网易云排行榜上的歌曲id来实现批量下载呢?

构思与实践:

通过过去的学习,只要从网页中爬取到音乐ID就不难实现上述目标。但是实践中发现网易云页面是由嵌套网页构成的,想要获取到排行榜信息必须爬取子页面,这是我未曾了解的领域。

通过网上搜索得知爬取iframe信息可以通过selenium库的switch_to.frame函数实现,经过两天的研究憋出了以下代码:

1
2
3
4
5
6
7
def Askurl(url):
s = Service(r"E:\python\PyCharm Community Edition 2021.3.1\plugins\python-ce\helpers\typeshed\stubs\selenium\selenium\webdriver\chrome\chromedriver.exe") #这是chromedriver存放位置
driver = webdriver.Chrome(service=s)
driver.get(url)
driver.switch_to.frame("g_iframe") #锁定子页面
text = driver.page_source
return text

使用 webdriver 必须下载驱动器,且驱动器版本必须与相应浏览器版本一致,否则报错。 chrome历史版本下载:Google Chrome 64bit Windows版_chrome浏览器,chrome插件,谷歌浏览器下载,谈笑有鸿儒 (chromedownloads.net) chromedriver下载链接:chromedriver.storage.googleapis.com/index.html chromedriver要放入指定位置(如代码所示)

大致意思是通过webdriver控制浏览器锁定iframe,并用driver.page_source返回整个页面的源码

得到了子页面的源码,剩下的问题便迎刃而解了

剩下的便是老一套的Getdata,Savedata了,但得到信息并不是最终目的,如何批量下载是一个问题,我的想法是通过for循环反复执行下载程序,于是从网络上找到一个靠谱的下载源码,经过调试可以完美运行。

最终效果:

img

(或许歌手id也是可以操作一下的)

img

这样虽然方便了不少,但总感觉下载速度感人

附源码

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# -*- codeing = utf-8 -*-
# @time:2021/12/31 12:44

from bs4 import BeautifulSoup
import re
import xlwt
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import os
import requests

def Askurl(url):
s = Service(r"E:\python\PyCharm Community Edition 2021.3.1\plugins\python-ce\helpers\typeshed\stubs\selenium\selenium\webdriver\chrome\chromedriver.exe")
driver = webdriver.Chrome(service=s)
driver.get(url)
driver.switch_to.frame("g_iframe")
text = driver.page_source
return text

Sing = []
Singer = []

def Getdata(url):

FindName = re.compile(r'<b title="(.*?)">')
FindId = re.compile(r'<a href="(.*?)">')
FindSinger = re.compile(r'<span title="(.*?)">')
FindSingerId = re.compile(r'<a class="" hidefocus="true" href="(.*?)">')

html = Askurl(url)
soup = BeautifulSoup(html,"html.parser")

for item in soup.find_all('div', class_="ttc"):
item = str(item)
data1 = []
name = re.findall(FindName, item)[0]
name = name.replace('\xa0'," ")
data1.append(name)

Id = re.findall(FindId, item)
surl ='http://music.163.com/song/media/outer/url?id=' + str(Id).strip('[').strip(']').strip("'").strip('/song?id=') + '.mp3'
data1.append(surl)

Sing.append(data1)
for index in soup.find_all('div', class_="text"):
index = str(index)
data2 = []

sname = re.findall(FindSinger, index)[0]
data2.append(sname)

sid = re.findall(FindSingerId, index)
sid = str(sid).strip('[').strip(']')
sid=re.sub('\'', '', str(sid))
data2.append(sid)

Singer.append(data2)

# for index in Singer:
# print(index)
# for index in Sing:
# print(index)

def Savedata(path):
work = xlwt.Workbook(encoding="utf-8", style_compression=0)
sheet = work.add_sheet("wyyMusic", cell_overwrite_ok=True)
col = ('歌曲名称', '歌手', '下载链接', '歌手ID')
for i in range(0, 4):
sheet.write(0, i, col[i]) # write前两个数据分别是行和列的坐标
for j in range(0, len(Sing)):
data = Sing[j]
sdata = Singer[j]
for k in range(0, 2):
if k==0:
i=0
else:
i=2
sheet.write(j + 1,i, data[k])
for k in range(0, 2):
if k == 0:
i = 1
else:
i = 3
sheet.write(j + 1, i, sdata[k])
work.save(path)
print("save completely")

def download():
for i in range(0,3): #这是要下载的歌曲的排名区段(一到三名)
item = Sing[i]
url = item[1]
# MP3保存文件夹
save ='E:\py下载'
name = item[0] + '.mp3'
# 文件夹不存在,则创建文件夹
folder = os.path.exists(save)
if not folder:
os.makedirs(save)
# 读取MP3资源
res = requests.get(url,stream=True)
# 获取文件地址
file_path = os.path.join(save, name)
print('开始写入文件:', file_path)
# 打开本地文件夹路径file_path,以二进制流方式写入,保存到本地
with open(file_path, 'wb') as fd:
for chunk in res.iter_content():
fd.write(chunk)
print(name+' 成功下载!')


def main():
baseurl = 'https://music.163.com/#/discover/toplist' #排行榜链接
savepath = "网易云.xls"
Getdata(baseurl)
Savedata(savepath)
download()
print('hello world')

if __name__ == "__main__":
main()