添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Python爬虫实战,30行代码轻松爬取网易云音乐热歌榜

在开始讲解思路之前,我们首先了解下网络状态码,为什么要看这个呢?以后你会回来感谢我的,嘻嘻!

一般网络状态有以下几种:

200(成功)

服务器成功处理了请求。一般来说,这意味着服务器提供所请求的页面,如果您看到此状态,您的robots.txt文件,这意味着Googlebot的检索成功。

301(永久移动)

请求的网页已永久移动到新的位置,当服务器返回此响应(作为一个GET或HEAD请求的响应),它会自动转发请求到新的位置。你应该使用这个代码让Googlebot的知道一个网页或网站已永久移动到新位置。

302(临时移动)

服务器正在响应请求,从不同位置的网页,但请求者应继续使用原来的位置,为将来的请求。此代码是在这一个GET或HEAD请求的301相似,它会自动转发到不同的位置请求,但你不应该用它来告诉Googlebot的一个网页或网站已移动,因为Googlebot会继续抓取和索引原来的位置。

400(错误请求)

服务器不理解请求的语法。

403(禁止)

服务器拒绝请求。如果你看到在Googlebot尝试抓取您的网站的有效网页(你可以看到在网络上抓取页面在谷歌webmasters诊断下)收到此状态码时,它有可能是您的服务器或主机阻止Googlebot存取。

404(未找到)

服务器找不到请求的页面。例如,服务器返回此代码,如果请求是在服务器上的页面不存在。如果没有您网站上的robots.txt文件,并在webmasters“诊断”标签的robots.txt页上看到此状态,这是正确的状态。然而,如果你有一个robots.txt文件,你会看到这种状态,那么您的robots.txt文件可能被命名为不正确或在错误的位置。它应该是在顶级域,名为robots.txt的。如果你看到的网址,Googlebot尝试抓取(诊断“标签的HTTP错误”页上)此状态, 则表示Googlebot可能从另一页(可能是旧链接或输入有误)的无效链接。

500(内部服务器错误)

服务器遇到了一个错误,并不能满足要求。

503(服务不可用)

服务器目前无法使用(因为它是重载维修或向下),一般来说,这是一个临时的状态。

重点来了,跟上思路

进入正题,我们今天爬取的是网易云音乐热歌榜的歌曲,首先我们要知道这个网址,如下图所示:

网址是这个:https://music.163.com/#/discover/toplist?id=3778678

有了网址就要对这个网址进行尝试访问,一般在进行爬虫时,为了防止反爬机制,我们需要将我们伪装成浏览器身份去进行访问网页,那么怎么进行伪装呢?就是修改我们的访问身份:

  1. 进入网页后按F12;
  2. 然后选择NetWork;
  3. 按F5进行页面刷新;
  4. 点击music.163.com;
  5. 选择最底下的进行复制;

看图中标记位置:

在进行数据爬取时,我们需要对网页进行分析,对网页内容需要进行解析,这时候我们需要几个必备的包:

  1. requests :请求网页,接受网页数据
  2. etree :解析网页

怎么导入了,这个很简单的哈:

import requests
from lxml import etree

这里拓展一下,要是包没有下载,我们可以使用pip install 这个命令去分别下载这两个库

pip install requests
pip install lxml

准备工作做好了,我们来进行代码访问我们的需要爬取的网址

import requests
from lxml import etree
import os   
url='https://music.163.com/discover/toplist?id=3778678'
head={    
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36'
down_url='https://music.163.com/song/media/outer/url?id='
respone=requests.get(url,headers=head)print(respone)

运行代码输出结果如图

上图所示结果就是访问正常了,下面我们开始来解析网页

解析网页我们一般用到的是:

html=etree.HTML(respone.text)

我们进行检查时,发现歌曲的主要信息在这里,那么格式我们可以这样写:

id_list=html.xpath('//a[contains(@href,"song?")]')

这个a标签中包含href中song?及以后的数据

print(id_list)

然后我们能获得一下信息,看图:

是不是感觉有点奇奇怪怪的,好像和我们想象中的有点不太一样,这只是我们获取到的地址,我们还需要进行进一步的提取,怎么提取,往下看

我们需要获取ID:

for id in id_list:
    href=id.xpath('./@href')[0]
    print(href)

我们对获取到的地址进行遍历,取到其href中的值,看下结果:

我们想要的是id后面的那串数字,那么这时候我们对其进行分割,取到我们想要的数据:

music_id=href.split('=')[1]
print(music_id)

分割后的结果如下:

有了这些数字,接下来需要干嘛,当然是获取歌曲的名字

if "$" not in music_id:
	music_name=id.xpath('./text()')[0]
	print(music_name)

这里解释下,为什么要使用这个if判断条件,直接看图

看到了没有,这是因为在进行id获取时,有的id是没有的,字符串里包含$,如果我们不进行处理,那么就会出现索引错误,因为里面没有这些包含$的id,所以就会报错,名字获取到了那么我们就可以对歌曲进行下载并存储。

其实每个歌曲都有自己的下载链接,那么我们采用这个链接并且配合我们获取到的id就可以进行下载啦:

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

拼接链接,把我们之前得到的Id数字加上去:

music_url=down_url + music_id
music=requests.get(url=music_url,headers=head)
print(music_url)

看到了吗,每个歌曲对应一个下载地址,然后我们随机复制一个下载地址,看看能不能下载,

可以下载,对不对?然后我们接下来就可以进行存储了:

if not os.path.exists(r'C:\Users\***\Desktop\music'):
            os.mkdir(r'C:\Users\***\Desktop\music')
        else:
            with open(r'C:\Users\***\Desktop\music/%s.mp3' % music_name, "wb") as f:
                print("正在下载歌曲 《%s》 ..." % music_name)
                f.write(music.content)

是不是有点看不懂,不要急,我来说下这里:

  1. 先查找文件夹,如果不存在则进行创建;
  2. 创建之后打开文件夹,将获取到的文件以刚才获取到的名字进行命名,然后后缀名改为.mp3格式;
  3. 以二进制形式进行写入数据文件。
r'C:\Users\***\Desktop\music/%s.mp3'

这里是什么意思呢:

  1. r:防止位置中的有些字符被转义;
  2. C:\Users\***\Desktop\music这是一个用户位置信息,如果你想直接复制粘贴肯定不行,得改成你自己的用户名哈。

把思路整合,运行下我们的代码,是怎样的结果呢:

桌面是不是有了一个名字为music的文件夹


打开这个文件夹,是不是将歌曲爬取并进行了存储:

这里又有疑问了,这个歌单不是有200首歌曲吗?你这只有191首呀,原因我前面已经讲了哈,为什么加一个if判断条件。

随便点开一个mp3文件,看下文件大小,看看是不是完整版的。

到这里为止,我们就已经将歌曲爬取完毕并存储到了桌面music文件夹里面了,简不简单。

跟着一步一步的走,思路是最重要的,小白也能学会。

最后附上完整的代码:

import requests
from lxml import etree
import os   #创建文件夹
url='https://music.163.com/discover/toplist?id=3778678'
head={
     'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36'
down_url='https://music.163.com/song/media/outer/url?id='
respone=requests.get(url,headers=head)
print(respone)
html=etree.HTML(respone.text)id_list=html.xpath('//a[contains(@href,"song?")]')
print(id_list)
for id in id_list:
    href=id.xpath('./@href')[0]
    print(href)
    music_id=href.split('=')[1]
    print(music_id)
    if "$" not in music_id:
        music_name=id.xpath('./text()')[0]
        print(music_name)
        music_url=down_url + music_id        
        music=requests.get(url=music_url,headers=head)
        print(music_url)