本帖最后由 lijt16 于 2020-1-12 16:05 编辑
原先开了几个月的黑胶,新年过期了,发现很多之前下的本地歌曲也无法播放,有点无语,故想把自己的歌单上的歌下下来上传到音乐云盘上。
在论坛了找了几个,包括网易云音乐歌曲批量下载,免VIP【支持歌单,排名榜】、【Python】某易云音乐歌曲批量下载,免VIP
,可惜失效了,就自己参考了些代码写了个:
import warnings
import os,requests
from selenium import webdriver
warnings.filterwarnings("ignore")
class DownMusic():
"""
下载网易云音乐歌单
用selenium+PhantomJS配合
在https://phantomjs.org/download.html下载phantomjs
在webdriver.PhantomJS()括号里填入PhantomJS.exe绝对路径
或将PhantomJS.exe放到python安装目录下
若python3下的selenium默认版本安装,会报警告,忽略不管可继续下载
若失败,一种方案是卸载selenium,重新安装指定版本2.48.0;另一种方案自行搜索解决
"""
def __init__(self, playid):
self.url = 'https://music.163.com/#/playlist?id=' + playid
def is_filename(self, uchar):
"""
排除文件名不可用的字符\/:*?"<>|
注意都是在英文输入法下的,若是中文输入法下的例如?“等是可以用来生成文件名的
以及不间断空白符 :\xa0
:param uchar:
:return:
"""
if uchar == u'\u005c' or uchar == u'\u002f' or uchar == u'\u003a' or uchar == u'\u002a' or uchar == u'\u003f' \
or uchar == u'\u007c' or uchar == u'\u003c' or uchar == u'\u003e' or uchar == u'\u0022' or uchar == u'\xa0':
return False
else:
return True
def format_str(self, content):
"""
将字符串content中的字符逐个判断
:param content: <str>输入文本
:return: <str>输出可作为文件和文件夹名的字符串
"""
content_str = ''
for i in content:
if self.is_filename(i):
content_str = content_str+i
return content_str
def download(self):
headers = {'User-Agent':'User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',}
driver = webdriver.PhantomJS() #括号内填入PhantomJS.exe绝对路径,或将PhantomJS.exe单独放到python安装目录下
driver.get(self.url)
driver.implicitly_wait(10) #隐式等待10s
driver.switch_to.frame('g_iframe') #跳转到id为g_iframe的iframe框架下
list_name = driver.find_element_by_class_name('f-ff2').text #歌单名称
print('-'*10, '歌单: ', list_name, '-'*10)
list_path = os.getcwd()+ '/' + self.format_str(list_name) #以歌单名创建新文件夹
if os.path.exists(list_path):
pass
else:
os.mkdir(list_path)
ids = driver.find_elements_by_xpath('//a[starts-with(@href,"/song?id=")]')
names = driver.find_elements_by_xpath('//a[starts-with(@href,"/song?id=")]/b')
for i in range(0, len(ids)):
id = ids[i].get_attribute('href').replace('https://music.163.com/song?id=','')
name = self.format_str(names[i].get_attribute('title').strip().replace('/',''))
print('第%d首下载中... Id:'%(i+1), id, 'Name:', name)
link = 'http://music.163.com/song/media/outer/url?id=' + id + '.mp3' #网易云下载外链地址
song = list_path + '/' + name + '.mp3'
# 若歌曲存在且能正常播放(此处判断为大于100kb)则不再下载
if os.path.exists(song) and (os.path.getsize(song)) >= 102400:
pass
else:
try:
with open(song, 'wb') as f:
f.write(requests.get(link, headers=headers).content)
if (os.path.getsize(song)) < 102400: #网易云上显示但是无法在线听的音乐
os.remove(song)
except:
print('第%d首下载失败!'%(i+1))
driver.switch_to.default_content()#返回主文档
if __name__ == '__main__':
playid = input('输入网易云歌单ID: ')
DownMusic(playid).download()
我没注意是否黑胶或者付费什么的问题,总之下了一个日语歌单和一个粤语歌单,里面应该是有黑胶下载的歌曲,不过估计付费的应该不行,因为上面代码终究是根据网易云外链地址下载的。欢迎各位有其他方法的一起交流。
|