本
文
摘
要
前言
最近,网易的音乐很多听不到了,刚好也看到很多教程,跟进学习了一下,也集大全了吧,本来想优化一下的,但是发现问题还是有点复杂,最后另辟捷径,提供了简单的方法啊!
Python + 爬虫
首先,说一下准备工作:
Python:需要基本的python语法基础requests:专业用于请求处理,requests库学习文档中文版lxml:其实可以用python自带的正则表达式库re,但是为了更加简单入门,用 lxml 中的 etree 进行网页数据定位爬取。re:python正则表达式处理json:python的json处理库然后,说一下现在已经知道下载链接是这样的: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 就可以了,没必要爬虫啊!
下载歌词
如果还要下载歌词,那也很简单,通过接口,有歌曲的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]开了窗 等待天亮\n[00:46.160]看这城市 悄悄的 熄了光\n[00:51.850]听风的方向\n[00:55.090]这一刻 是否和我一样\n[00:58.730]孤单的飞翔\n[01:02.300]模糊了眼眶\n[01:07.760]广播里 那首歌曲\n[01:14.830]重复当时 那条街那个你\n[01:20.410]相同的桌椅\n[01:23.740]不用言语 就会有默契\n[01:27.470]这份亲密\n[01:30.560]那么熟悉\n[01:33.850]在爱里 等着你\n[01:37.480]被你疼惜 有种暖意\n[01:41.090]在梦里 全是你\n[01:43.920]不要再迟疑 把我抱紧"},klyric:{version:0,lyric:null},tlyric:{version:0,lyric:null},code:200}坑点与进阶
表面上很简单,但是需要注意的是,网易返回的链接,数据是js动态加载,也就是爬虫得到的网页数据和浏览器得到的dom内容和结构不一样!
坑
其中,搜索列表爬虫回来的内容,完全得不到歌曲id!!!
解决
解决方法也是有的!
python模拟浏览器
使用selenium+phantomjs无界面浏览器,这两者的结合其实就是直接操作浏览器,可以获取JavaScript渲染后的页面数据。
缺点
由于是无界面浏览器,采用此方案效率极低,如果大批量抓取不推荐。
对于异步请求并且数据在源码中并不存在的,同时也就无法抓取到的数据。
搜索的歌曲变成歌单
比如想下载全部的某一歌手的全部音乐,用手机云音乐搜索,然后全部保存到新建一个歌单,这样就可以啦!
总结
用python,就一定要简单,我认为复杂的东西,还是尽量少做,能取巧就取巧,所以本文没有使用selenium+phantomjs实践。
注:本文只是技术交流,请不要商业用途~ 如有违反,本人一概不负责。
全部代码又是非常简单的100行代码完事!!!
import osimport reimport jsonimport requestsfrom lxml import etreedef download_songs(url=None):ifurl is None: url =https://music.163.com//playlist?id=2384642500url = 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])ifartist_name_treeelseNone 如果是歌单页面: 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])ifsong_list_name_treeelseNone 设置音乐下载的文件夹为歌手名字或歌单名 folder =./+ artist_nameifartist_nameelse./+ song_list_nameifnotos.path.exists(folder):os.mkdir(folder)fori, sinenumerate(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 +.mp3filepath = folder +/+ filenameprint(开始下载第{}首音乐:{}\n.format(i +1, filename)) try: 下载音乐 下载歌词 download_lyric(title, song_id) data = requests.get(src).content 音乐的二进制数据 withopen(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.comOrigin: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)如有疑问,欢迎在评论区一起讨论!如有不正确的地方,欢迎指导!