Python 爬虫 4 mins

从零开始写一个音乐爬虫-2:下载音乐文件

25-02-20 / 1509 Words

上一篇文章我写了爬取网易云音乐歌单中音乐ID及下载链接的教程,这一期我们就应该把文件下载下来了。

下载文件,我们通过Python3的urllib模块可以很轻松地实现。 新建一个download.py文件。

下载音乐主要的代码:

 #!/usr/bin/env python
#-*- coding:utf8 -*-
'''
@Author  :   Ray
@Contact :   ray@raycoder.me
@Software:   PyCharm
@File    :   download.py
@Time    :   2019/11/4 21:19
'''
import urllib, time, os

def downloadMusic(music_dictionary, path): #下载音乐
    exist = os.path.exists(path)
    if not exist:
        os.makedirs(path)
    complete = []
    failed = []
    for i in music_dictionary:
        try:
            print(u'正在下载:' + i)
            trans = str.maketrans('\\/*?:"|<>', '         ')
            urllib.request.urlretrieve(music_dictionary[i], path + i.translate(trans) + '.mp3')
            print(u'下载完成!')
            complete.append(i)
            time.sleep(1)
        except OSError as e:
            print(u'下载失败:' + i +'\t' + u'失败原因:' + str(e))
            failed.append(i)
    if complete:
        print("下载成功:")
        for i in complete:
            print(str(complete.index(i) + 1) + '.\t' + i)
        print()
    else:
        print("无下载成功")

    if failed:
        print("下载失败:")
        for i in failed:
            print(str(failed.index(i) + 1) + '.\t' + i)
        print()
    else:
        print("无下载失败")

测试:

import CloudMusicSpider
def _test():
    spider = CloudMusicSpider()
    downloadMusic(spider.getArtUrl('https://music.163.com/#/playlist?id=4874770876'))

if __name__ == '__main__':
    _test()

结果:

正在下载:Prelude
下载完成!
正在下载:Marble Soda [Explicit]
下载完成!
正在下载:Snowdin Town
下载完成!
正在下载:Monkeys Spinning Monkeys
下载完成!
正在下载:Overworld Theme (GFM Trap Remix)
下载完成!
正在下载:Pizza
下载完成!
正在下载:King Dedede
下载完成!
正在下载:Undertale
下载完成!
正在下载:sans.
下载完成!
正在下载:Tem Shop
下载完成!
正在下载:Undertale - Snowdin Town (****** Bootleg)
下载失败:Undertale - Snowdin Town (****** Bootleg)	失败原因:[Errno 22] Invalid argument: 'Undertale - Snowdin Town (****** Bootleg).mp3'
正在下载:It's Not Like I Like You!!(Instrumental)
下载完成!
正在下载:似顔絵広場 (似顔絵チャンネル)
下载完成!
正在下载:ステージ:コミカル (サンドキャニオン)
下载完成!
正在下载:I Love You
下载完成!
正在下载:Ice Cream
下载完成!
正在下载:Dying
下载完成!
下载成功:
1.	Prelude
2.	Marble Soda [Explicit]
3.	Snowdin Town
4.	Monkeys Spinning Monkeys
5.	Overworld Theme (GFM Trap Remix)
6.	Pizza
7.	King Dedede
8.	Undertale
9.	sans.
10.	Tem Shop
11.	It's Not Like I Like You!!(Instrumental)
12.	似顔絵広場 (似顔絵チャンネル)
13.	ステージ:コミカル (サンドキャニオン)
14.	I Love You
15.	Ice Cream
16.	Dying

下载失败:
1.	Undertale - Snowdin Town (****** Bootleg)

之后就可以在保存源文件的目录下downloads文件夹看到音乐文件了。

想要下载歌词的只需修改getArtUrl()函数即可,外链为http://music.163.com/api/song/lyric?id=音乐ID&lv=1&kv=1&tv=-1

P.S:上面那个下载失败的是因为文件名中有*号,而Windows是不让保存的。所以我要用str.translate()方法将这些字符批量替换。

#!/usr/bin/env python
#-*- coding:utf8 -*-
'''
@Author  :   Ray
@Contact :   nn_201412@qq.com
@Software:   PyCharm
@File    :   init.py
@Time    :   2019/11/4 21:19
'''
import requests, re, urllib, os
from fake_useragent import UserAgent
from time import sleep

exist = os.path.exists('downloads/')
if not exist:
    os.makedirs('downloads/')

class CloudmusicSpider():
    HEADER = {  # 伪造请求头,防止被封
        'Accept': '*/*',
        'Accept-Encoding': 'gzip,deflate,sdch',
        'Accept-Language': 'zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4',
        'Connection': 'keep-alive',
        'Content-Type': 'application/x-www-form-urlencoded',
        'Host': 'music.163.com',
        'Referer': 'https://music.163.com/',
        'User-Agent': UserAgent().random
    }
    def getUrl(self, artlist_url): #获取音乐真实ID的函数
        outerUrl = "http://music.163.com/song/media/outer/url?id={0:s}.mp3" #外链地址
        response = requests.get(url=artlist_url.replace('#/', ''), headers=self.HEADER) #网易云音乐使用异步加载,需要去掉"#/"
        songs = {}
        for i in re.findall(r'<a href="/song\?id=(\d+)">(.*?)</a>', response.text):
            songs[i[1]] = outerUrl.format(i[0])
        return songs
    def downloadMusic(self, music_dictionary): #下载音乐
        complete = []
        failed = []
        for i in music_dictionary.keys():
            try:
                print(u'正在下载:' + i)
                trans = str.maketrans('\\/*?:"|<>', '         ') #一一对应
                urllib.request.urlretrieve(music_dictionary[i], 'downloads/' + i.translate(trans) + '.mp3') #字符替换
                print(u'下载完成!')
                complete.append(i)
                sleep(1)
            except OSError as e:
                print(u'下载失败:' + i +'\t' + u'失败原因:' + str(e))
                failed.append(i)
        if complete != []:
            print("下载成功:")
            for i in complete:
                print(str(complete.index(i) + 1) + '.\t' + i)
            print()
        else:
            print("无下载成功")

        if failed != []:
            print("下载失败:")
            for i in failed:
                print(str(failed.index(i) + 1) + '.\t' + i)
            print()
        else:
            print("无下载失败")

这个代码也需要保存为模块,命名为download.py,以后作为模块备用。