美文网首页Python新世界
十秒以内下载五十首网易云音乐!这就是爬虫的强大之处!

十秒以内下载五十首网易云音乐!这就是爬虫的强大之处!

作者: 919b0c54458f | 来源:发表于2018-12-27 14:08 被阅读4次

    1、前言

    最近,网易的音乐很多听不到了,刚好也看到很多教程,跟进学习了一下,也集大全了吧,本来想优化一下的,但是发现问题还是有点复杂,最后另辟捷径,提供了简单的方法啊!

    本文主要参考 python编写GUI版网易云音乐爬虫 后改写,有兴趣的可以看看文章的GUI,了解更多知识~

    2、Python + 爬虫

    首先,说一下准备工作:

    Python:需要基本的python语法基础

    requests:专业用于请求处理, requests库学习文档中文版

    lxml:其实可以用pythonth自带的正则表达式库re,但是为了更加简单入门,用 lxml 中的 etree 进行网页数据定位爬取。

    re:python正则表达式处理

    json:python的json处理库

    如果大家对上面的库还比不懂,可以看看我的之前文章 《Python爬虫实践入门篇》

    然后,说一下我们现在已经知道下载链接是这样的:

    http://music.163.com/song/media/outer/url?id='

    id 就是歌曲的id!

    所以,现在我们爬虫主要的工作就是找到这个id,当然为了更好的保存,也要找到这个歌名啦!

    那现在就是要找到我们需要爬虫的网站链接啦!我分析了一下,大概是下面三种:

    #歌曲清单

    music_list = 'https://music.163.com/#/playlist?id=2412826586'

    #歌手排行榜

    artist_list = 'https://music.163.com/#/artist?id=8325'

    #搜索列表

    search_list = 'https://music.163.com/#/search/m/?order=hot&cat=全部&limit=435&offset=435&s=梁静茹'

    如果你已经只是想下载一首歌,比如静茹-勇气: https://music.163.com/#/song?id=254485 ,那你直接就用浏览器打开 http://music.163.com/song/media/outer/url?id=254485 就可以了,没必要爬虫啊!

    好啦!感觉重点都说完了,提取和解析就是用 lxml,不懂的就看我之前的文章啊 《Python爬虫实践入门篇》

    3、下载歌词

    如果还要下载歌词,那也很简单,通过接口,有歌曲的id就可以:

    url = 'http://music.163.com/api/song/lyric?id={}&lv=-1&kv=-1&tv=-1'.format(song_id)

    返回的json数据大概长这样:

    {

    sgc: true,

    sfy: false,

    qfy: false,

    lrc:

    {

    version: 7,

    lyric: "[00:39.070]开了窗 等待天亮[00:46.160]看这城市 悄悄的 熄了光[00:51.850]听风的方向[00:55.090]这一刻 是否和我一样[00:58.730]孤单的飞翔[01:02.300]模糊了眼眶[01:07.760]广播里 那首歌曲[01:14.830]重复当时 那条街那个你[01:20.410]相同的桌椅[01:23.740]不用言语 就会有默契[01:27.470]这份亲密[01:30.560]那么熟悉[01:33.850]在爱里 等着你[01:37.480]被你疼惜 有种暖意[01:41.090]在梦里 全是你[01:43.920]不要再迟疑 把我抱紧"

    进群:960410445  即可获取数十套PDF!

    },

    klyric:

    {

    version: 0,

    lyric: null

    },

    tlyric:

    {

    version: 0,

    lyric: null

    },

    code: 200

    }

    剩下的也没有什么好说的啦!

    4、坑点与进阶

    表面上很简单,但是需要注意的是,网易返回的链接,数据是js动态加载,也就是爬虫得到的网页数据和浏览器得到的dom内容和结构不一样!

    其中,搜索列表爬虫回来的内容,完全得不到歌曲id!!!

    解决

    解决方法也是有的!

    python模拟浏览器

    使用selenium+phantomjs无界面浏览器,这两者的结合其实就是直接操作浏览器,可以获取JavaScript渲染后的页面数据。

    缺点:

    由于是无界面浏览器,采用此方案效率极低,如果大批量抓取不推荐。

    对于异步请求并且数据在源码中并不存在的,同时也就无法抓取到的数据。

    搜索的歌曲变成歌单

    比如想下载全部的某一歌手的全部音乐,用手机云音乐搜索,然后全部保存到新建一个歌单,这样就可以啦!

    进阶

    如果想使用了解更多网易云音乐js的加密解密过程,可以看看这个 Python 爬虫如何获取 JS 生成的 URL 和网页内容? - 路人甲的回答 - 知乎

    总结

    用python,就一定要简单,我认为复杂的东西,还是尽量少做,能取巧就取巧,所以本文没有使用selenium+phantomjs实践,如果想了解更多 selenium+phantomjs 内容,可以参考文末引用链接。

    注:本文只是技术交流,请不要商业用途~ 如有违反,本人一概不负责。

    全部代码

    又是非常简单的100行代码完事!!!

    GitHub: WebCrawlerExample/163_NeteaseMusic.py at master · iHTCboy/WebCrawlerExample

    import os

    import re

    import json

    import requests

    from lxml import etree

    def download_songs(url=None):

    if url is None:

    url = 'https://music.163.com/#/playlist?id=2384642500'

    url = url.replace('/#', '').replace('https', 'http') # 对字符串进行去空格和转协议处理

    # 网易云音乐外链url接口:http://music.163.com/song/media/outer/url?id=xxxx

    out_link = 'http://music.163.com/song/media/outer/url?id='

    # 请求头

    headers = {

    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',

    'Referer': 'https://music.163.com/',

    'Host': 'music.163.com'

    }

    # 请求页面的源码

    res = requests.get(url=url, headers=headers).text

    tree = etree.HTML(res)

    # 音乐列表

    song_list = tree.xpath('//ul[@class="f-hide"]/li/a')

    # 如果是歌手页面

    artist_name_tree = tree.xpath('//h2[@id="artist-name"]/text()')

    artist_name = str(artist_name_tree[0]) if artist_name_tree else None

    # 如果是歌单页面:

    #song_list_tree = tree.xpath('//*[@id="m-playlist"]/div[1]/div/div/div[2]/div[2]/div/div[1]/table/tbody')

    song_list_name_tree = tree.xpath('//h2[contains(@class,"f-ff2")]/text()')

    song_list_name = str(song_list_name_tree[0]) if song_list_name_tree else None

    # 设置音乐下载的文件夹为歌手名字或歌单名

    folder = './' + artist_name if artist_name else './' + song_list_name

    if not os.path.exists(folder):

    os.mkdir(folder)

    for i, s in enumerate(song_list):

    href = str(s.xpath('./@href')[0])

    song_id = href.split('=')[-1]

    src = out_link + song_id # 拼接获取音乐真实的src资源值

    title = str(s.xpath('./text()')[0]) # 音乐的名字

    filename = title + '.mp3'

    filepath = folder + '/' + filename

    print('开始下载第{}首音乐:{}'.format(i + 1, filename))

    try: # 下载音乐

    #下载歌词

    #download_lyric(title, song_id)

    data = requests.get(src).content # 音乐的二进制数据

    with open(filepath, 'wb') as f:

    f.write(data)

    except Exception as e:

    print(e)

    print('{}首全部歌曲已经下载完毕!'.format(len(song_list)))

    def download_lyric(song_name, song_id):

    url = 'http://music.163.com/api/song/lyric?id={}&lv=-1&kv=-1&tv=-1'.format(song_id)

    # 请求头

    headers = {

    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',

    'Referer': 'https://music.163.com/',

    'Host': 'music.163.com'

    # 'Origin': 'https://music.163.com'

    }

    # 请求页面的源码

    res = requests.get(url=url, headers=headers).text

    json_obj = json.loads(res)

    lyric = json_obj['lrc']['lyric']

    reg = re.compile(r'[.*]')

    lrc_text = re.sub(reg, '', lyric).strip()

    print(song_name, lrc_text)

    if __name__ == '__main__':

    #music_list = 'https://music.163.com/#/playlist?id=2384642500' #歌曲清单

    music_list = 'https://music.163.com/#/artist?id=8325' #歌手排行榜

    # music_list = 'https://music.163.com/#/search/m/?order=hot&cat=全部&limit=435&offset=435&s=梁静茹' #搜索列表

    download_songs(music_list)

    相关文章

      网友评论

        本文标题:十秒以内下载五十首网易云音乐!这就是爬虫的强大之处!

        本文链接:https://www.haomeiwen.com/subject/yvprlqtx.html