python爬虫--下载酷我音乐

本次练习的主要内容:

通过python爬虫,破解酷我音乐的api,下载音乐文件到本地。


(一)项目概况

1. 这里酷我音乐的首页:



2. 点击左上角的榜单,进去之后再点击具体歌名,跳转到音乐播放页面,可以在线听音乐:



3. 本次项目的主要目标,就是通过音乐具体的播放页面url,

即这样的链接:http://www.kuwo.cn/yinyue/42484721?catalog=yueku2016

下载该音乐到本地。


(二)网页分析

1. 在音乐播放页面打开开发者工具,查看网络请求:

在众多网络请求中,可以找到一个以.aac结尾的请求,猜测该请求就是目标音乐的请求。



2. 分析可知,该请求具体情况如下:

请求类型:get

请求url:

http://ip.h5.nf03.sycdn.kuwo.cn/ee3a8426c1def769b22e5c23639d6220/5b2b12a1/resource/a1/65/1/2669068103.aac

所以,只要模拟该get请求,就能拿到aac文件。

但是该url里面有许多陌生的字段,具体是从哪里来的呢?


3. 经查找,可以在下面的请求中的response的headers里面,找到上面的url:



4. 经分析该请求的情况如下:

请求类型:get

请求url:

http://antiserver.kuwo.cn/anti.s?format=aac|mp3&rid=MUSIC_42484721&type=convert_url&response=res

注意该请求返回的状态码是302。

仔细观察该请求的参数,发现只有“MUSIC_42484721”这个字段是动态变更的,其他都是固定的。

那么该MUSIC字段是从哪里来的呢?

仔细想想,原来就是音乐播放页面的url中包含的一个字段:http://www.kuwo.cn/yinyue/42484721?catalog=yueku2016


5. 这样就很明确了,下面梳理下思路:

- 通过音乐播放页面url,拿到类似这样的字段 “42484721”

- 通过该字段,构造第4步的get请求,拿到response的headers的location字段

- 通过location字段,发送get请求,拿到aac文件


(三)核心代码实现

1. 获取音乐播放url中特定字段

import requests
import re

s = requests.session()
filename = input("请输入音乐文件保存的本地路径:").strip()
base_url = input("请输入音乐播放页面url:").strip()
base_number = re.findall(r"(?:http://www.kuwo.cn/yinyue/)(\d+)(?:\?catalog=yueku2016)", base_url)[0]


2. 通过上面的字段,构造第一个get请求,获取返回头中的location字段

def get_url():
    headers = {
        'Accept': '*/*',
        'Accept-Encoding': 'identity;q=1, *;q=0',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'Connection': 'keep-alive',
        'Host':'antiserver.kuwo.cn',
        'Range': 'bytes=0-',
        'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36',
        'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'Referer':base_url
    }
    url = "http://antiserver.kuwo.cn/anti.s?format=aac|mp3&rid=MUSIC_"+ base_number +"&type=convert_url&response=res"
    r = s.get(url, headers=headers, allow_redirects=False)
    return r.headers['Location']


3. 通过location字段中的url,获取到aac文件数据

注意在网络分析时的截图,可以看到该请求的返回的状态码是206,这是由于该请求的请求头中添加了Range字段,代表仅请求部分内容,我这里设置为了'Range': 'bytes=0-',意思是请求从0字节之后的所有内容。

def get_aac(url):
	base_host = re.findall(r"(?:http://)(.*)", url)[0]
	base_host = base_host.split('/')[0]
	headers ={
            'Accept': '*/*',
            'Accept-Encoding': 'identity;q=1, *;q=0',
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
            'Connection': 'keep-alive',
            'Host': base_host,
            'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36',
            'Referer':base_url,
            'Range': 'bytes=0-'
           }
	r = s.get(url, headers=headers, stream=True)
	return r

4. 将aac文件数据写入到本地

def save_aac(filename, res):
	with open(filename, 'wb') as fd:
	    for chunk in res.iter_content(chunk_size=128):
	        fd.write(chunk)


5. 代码中的注意事项

实际写代码的过程中,发现酷我对请求头的检查非常严格,因此请求头务必根据实际情况编写准确,否则无法正确获取数据。



(四)项目结果

通过给定的音乐播放url,就可以将该音乐下载到指定的本地文件存储路径中。


(五)下一步

1. 代码中增加相应的错误检查

2. 可将本次代码作为批量爬取酷我音乐项目的一部分。




本文仅供学习交流使用,请勿将其用于违法目的。




展开阅读全文

没有更多推荐了,返回首页