目录
对一首歌的爬取(方法一)
对一首歌的爬取(方法二)
批量获取音源
需求分析:
目标网站:酷X音乐(涉及版权)
实现目标:嘉宾这首歌的所有音源爬取
代码实现步骤:
查看网页
通过浏览网页源代码我们可以判断,网页数据是动态加载,还是我们所要获取的数据就在源代码当中,本文中所介绍的XX音乐的音源数据是属于动态加载,我们打开开发者工具,在搜索框中搜索**mp3**,点击**Priview**选项,可以找到我们所要爬取的所有数据,列表页图解如下:
一首歌曲的爬取(方法一)
打开目标页面,按**F12**进入开发者工具,点击**network**中的**Media**,我们可以看到在页面音源没有被播放的时候,**media**中是空的,当我们按下播放键之后,页面会刷新一个响应数据,此时我们双击该响应值,就会自动播放我们的目标歌曲,点击**Headers**,复制**Request URL**:在新的页面打开,也可以播放目标歌曲。图解如下:
找到响应的url后,此时我们可以很简单的就获取到我们想要下载的音乐
url = 'https://webfs.ali.kugou.com/202305080952/93fcfdc0f574c7773ce4596a0f084ef4/KGTX/CLTX003/44c6970389ea89c74c664448a079374a.mp3'
res = requests.get(url,headers=headers)
with open('./music.mp3','wb')as f:
f.write(res.content)
一首歌的爬取(方法二)
当我们浏览歌曲详情页面时,打开开发者工具,在搜索框中搜索mp3,可以找到到歌曲的详情数据,我们可以查看该选项的url,可以发现此时的url是由很多的参数拼接成的,而在**payload**中可以找到相应的参数,我们爬取一首歌的情况下,可以直接复制Url,不用设置param中的参数
url = 'https://complexsearch.kugou.com/v2/search/song?callback=callback123&srcappid=2919&clientver=1000&clienttime=1683514972503&mid=1de90ed5784632bd8408190ba329e30e&uuid=1de90ed5784632bd8408190ba329e30e&dfid=11S2Y02tkykk1pCgJ50d89i5&keyword=%E5%98%89%E5%AE%BE&page=1&pagesize=30&bitrate=0&isfuzzy=0&inputtype=0&platform=WebFilter&userid=0&iscorrection=1&privilege_filter=0&filter=10&token=&appid=1014&signature=e448d282c403d24c32183b97de601e85'
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36',
'Cookie':'kg_mid = 1de90ed5784632bd8408190ba329e30e;kg_dfid = 11S2Y02tkykk1pCgJ50d89i5;kg_dfid_collect = d41d8cd98f00b204e9800998ecf8427e;Hm_lvt_aedee6983d4cfc62f509129360d6bb3d = 1683459911, 1683509659;kg_mid_temp = 1de90ed5784632bd8408190ba329e30e;Hm_lpvt_aedee6983d4cfc62f509129360d6bb3d = 1683523404',
'Referer':'https: // www.kugou.com /'
}
res = requests.get(url,headers=headers)
# # print(res.text)
写到这里的时候,使用json.loads将json格式的数据转换成python数据,我发现运行以后会有报错
loads() 传的是python的dict字典类型,而我们刚刚传递的类型不符合,所以报错了,此时我们打印一下res.text,发现输出的内容除了我们的目标数据,还多了jQuery191033221067126349535_1683528994015();这组数据将我们的目标数据括起来了,使得输出的数据不是完整的json数据,那么只要我们把多出的部分替换成空就好了
此时我们就得到了我们想要获取的音源地址,在请求该地址,再保存文件即可,流程和方法一一样,我就不过多的赘述了。
批量获取目标数据
上面我们已经实现了对一首歌的爬取,那么我们如何实现对多首歌曲的获取呢,前面在查看网页的时候我们已经介绍到了,网页数据是动态加载的,没有在源码中,我们在搜索框中搜索mp3,会出现相应的符合条件的响应对象,我们可以在**priview**的**data**中找到歌曲列表的数据,如图所示:
那么我们如何通过列表页面,获取到歌曲详情页面的音源数据呢,继续查看网页,前面我们说到,歌曲详情页面的Url地址是由以下几个参数拼接成的:
我们可以多看几个详情页,发现**callback**、和**encode_album_audio_id**,这两个参数是会发生变化的,而最后一个参数实际上是一个时间戳,也就是当前浏览页面的时间,而callback中变化的参数实际上是一个时间计时,后续我们可以用time库来处理,自己创造一个时间计时来表示访问时间,而encode_album_audio_id可以在列表页中找到,它对应的就是列表页中,lists下的**EMixSongID**
也就是说其他的不变的参数,我们可以直接复制粘贴,写在param中,那么我们实际要请求的地址就可以是https://wwwapi.kugou.com/yy/index.php?+ 上面介绍的参数。
此时我们整体思路就清晰了:
1、对列表页请求获取data下的Lists中的**EMixSongID**和**FileName**,也可以获取hash,以前url中是写有hash值的,但是现在请求地址中没有了,所以这里我们只获取两个数值。
2、把获取到的id值和其他参数一起写在data{}字典中,再请求详情页的url,获取mp3音源地址
3、请求获取的音源地址,保存音源
第一步:
获取列表页data下的Lists中的**EMixSongID**和**FileName*
url = 'https://complexsearch.kugou.com/v2/search/song?callback=callback123&srcappid=2919&clientver=1000&clienttime=1683514972503&mid=1de90ed5784632bd8408190ba329e30e&uuid=1de90ed5784632bd8408190ba329e30e&dfid=11S2Y02tkykk1pCgJ50d89i5&keyword=%E5%98%89%E5%AE%BE&page=1&pagesize=30&bitrate=0&isfuzzy=0&inputtype=0&platform=WebFilter&userid=0&iscorrection=1&privilege_filter=0&filter=10&token=&appid=1014&signature=e448d282c403d24c32183b97de601e85'
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36',
'Cookie':'kg_mid = 1de90ed5784632bd8408190ba329e30e;kg_dfid = 11S2Y02tkykk1pCgJ50d89i5;kg_dfid_collect = d41d8cd98f00b204e9800998ecf8427e;Hm_lvt_aedee6983d4cfc62f509129360d6bb3d = 1683459911, 1683509659;kg_mid_temp = 1de90ed5784632bd8408190ba329e30e;Hm_lpvt_aedee6983d4cfc62f509129360d6bb3d = 1683523404',
'Referer':'https: // www.kugou.com /'
}
res = requests.get(url,headers=headers)
# # print(res.text)
data = res.content.decode('utf-8')
data = re.sub('callback123\(','',data)
data = re.sub('\)','',data)
# # print(data)
html = json.loads(data)['data']['lists']
# # print(type(html))
for i in html:
filename = i.get('FileName')
filehash = i.get('FileHash')
fileid = i.get('EMixSongID')
第二步
把获取到的id值和其他参数一起写在data{}字典中,再请求详情页的url,获取mp3音源地址
前面我们讲到callback的参数变化使用time库中的time函数解决,我们可以对比几个详情页,发现jQuery1910后的几个数字是变化的,'_'后的16835这几个数字是不变的
'callback': 'jQuery1910{}'.format(math.floor(time.time()*1000))+'_16835{}'.format(math.floor(time.time()*1000))'
第三步
请求获取的音源地址,保存音源
for h in html_box:
res_h = requests.get(url=h,headers=headers)
with open('./{}.mp3'.format(filename),'wb')as f:
f.write(res_h.content)
列表页的音源我们就获取到啦!!!!!
如果是要爬取多个页面的音源,可以浏览几个页面的url的不同之处,再具体问题具体分析具体解决
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。