查看原文
其他

网易云下载音乐后续

咪咪怪 咪哥杂谈 2019-10-30
咪哥杂谈

网易云下载音乐

后续


本篇阅读时间约为 6 分钟。


1

前言


本篇文章,承接一星期之前写的的网易云音乐后续。当时思路给大家了,不知道自己动手的有多少人?动手才有收获呀~


今天给大家介绍一下笔者是如何写源码思路的。


网易云歌曲具体思路回顾:还在用网易云音乐客户端?out了~


2

网易云核心代码思路讲解


爬虫的重点在于分析思路,代码实现千万种,笔者这里简单的介绍下自己的核心代码思路(用中文写逻辑,俗称“伪代码”),至于具体源码,详见文末。


本次用到的第三方库分别是 requests 、beautifulsoup4 库。所以如果你想模拟代码运行,确保有此两个库。仔细看过笔者之前写过文章的朋友们,一定知道 Pypi 这个网站,才给大家说下,如何去找第三方库。


百度搜索 Pypi ,第一个网站就是,点开后,直接搜索相应的库名即可,点进去:



pip install beautifulsoup4

requests 库,同理:

pip install requests

1. 模拟请求到网易云,缓存 HTML 源代码


此过程中源码对应的是 __crawl_html() ,使用了 requests 库,在 Python 小课堂中,笔者曾经使用 urllib 这个原生库模拟浏览器爬取熊猫TV。今天推荐的是 Python 届最好用,最人性化的请求库,即 requests 。


使用方法非常简单,一行代码即可实现模拟登陆,具体操作,大家可以自行查看官方文档。搜索,requests库中文官方文档,第一个就是。


笔者一直在强调,新学习一个东西,最快、最有效、最不被误导的做法就是去看官方文档


在笔者的源代码中,使用 requests 模拟请求时,做了一层本地缓存,将服务端的源码写到了本地磁盘中,便于多次调试,不用每一次都访问网易云网页,如果本地有 html 文件的源代码,直接读取即可.


2.  解析歌曲相关信息节点,yield关键字返回


此过程中源码对应的是 __analysis_node() ,其中使用了 beautifulsoup 库,它的作用是将你的HTML源代码,以一种指定的解析器进行解析,源码中我使用的是 lxml 解析器,lxml也是第三方库,需要单独安装。快速上手,自己去查阅官方文档,下面举个例子:


使用方法有点像正则,举个小例子:


from bs4 import BeautifulSoup as bssoup = bs(html, 'lxml')  soup.find(name='ul', attrs={'class': 'f-hide'})


在网上,经常有人说,bs(html,'lxml') 实例化对象时,就像做出“一锅美味的汤”,接下来,你需要对这个“汤”,也就是 soup 进行操作。


soup.find() 中,name就是 html 的标签名称,attrs 是属性的简写,所以,上面的例子中的意思就是,查询出这样的节点:

<ul class = "f-hide">


但是我们需要获取的是歌曲 id ,id的分析去看上一篇中,它是在 ul 下的 li 下的 a 标签中的 href 的内容,代码如下:

ul_node = soup.find(name='ul', attrs={'class': 'f-hide'}) # 获取歌曲id的ulli_node = ul_node.find_all(name='li')for a_node in li_node: href_content = a_node.find(name='a').get('href') # 超链接 song_name = a_node.find(name='a').get_text() yield { 'href_content': href_content, 'song_name': song_name }


最终将所有匹配的信息,用 yield 关键词返回。yield 的用途是将此函数作为生成器,在调用此函数的时候,才会开始计算返回。


生成器不熟悉的,回顾:python小课堂34 - 推导式与生成器


3.  获取到 id,可以对id进行拼接下载


此过程中源码对应的是 __downloader() ,对相关信息进行数据清洗,然后拼接下载地址,继续使用 requests 模拟请求:


mp3_stream = requests.get(url=mp3_url, headers=self.headers).contentmp3_file_name = f'{self.song_list_name}/{song_name}.mp3' # mp3文件名字self.write_file(mp3_file_name, 'wb', mp3_stream) # 二进制写入random_time = random.random()print(f'第{self.count}首下载完成...歌名:{song_name},随机休眠{random_time}s...\n')time.sleep(random_time)


其中,requests.content ,是将文件以二进制流获取,只需将流写入本地,存成 mp3 格式即可。在最后,加上了随机休眠机制,缓慢请求!控制速度~


调用 downloader 时,用了一个 map() 函数,python 的高阶函数,因为设计 downloader 时,按照单一职责制定的,每次 downloader 中只处理一首歌,而不是在 downloader 中去 for 循环遍历。


3

结语


在学习本篇文章时,建议看源代码的同时,结合文章一起观看,效果更佳。


本篇设计角度是从工程性出发,若读者们有不同的设计观点,欢迎探讨!


如需源码,老规矩,后台回复:网易云 ,即可获得!


至此完!




▼往期精彩回顾▼谈谈复利效应新手必会,python中的debug调试还在用网易云音乐客户端?out了~


长按关注

公众号名称:咪哥杂谈

一个咪咪怪的公众号

长按二维码关注哦!


你点的每个在看,我都认真当成了喜欢


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存