赞
踩
主要目的为爬取酷狗音乐网站 mp3 任意音乐数据,并将爬取后的mp3数据保存为以.mp3后缀的音频文件
hashlib => md5加密:提供了许多加密哈希算法,包括MD5、SHA-1、SHA-256等。 os => 提供了访问操作系统功能的方法,例如文件操作、目录操作、进程管理等。 time => 提供了处理时间的函数,包括获取当前时间、延时等功能。 requests=> 用于发送HTTP请求和处理响应。 re => 提供了正则表达式操作的函数,用于在字符串中搜索、匹配和替换文本。 json => 用于处理JSON数据,用于JSON格式转换。 tkinter => 提供了创建图形用户界面(GUI)的工具包,可以用于构建窗口、按钮、文本框等GUI元素。
打开浏览器,进入酷狗音乐网页,点击F12进入开发者模式
点击上面一栏的媒体,可以看到mp3音乐文件
可以发现这个文件就是当前音乐mp3媒体文件,但是我们需要找到它的来源处,可以在搜索出直接搜索横线那部分
对比一下我们可以发现,我们所需要的mp3文件来源于此处。且位于play_url参数中,因此我们现在需要的就是爬取当前此文件。
所以,我们先确定它的url。通过对比url与字符串参数发现,网页url只为“https://wwwapi.kugou.com/play/songinfo?”,其余都只是参数。
我们再取对比其他音乐的当前地址,发现他们只有“clienttime”,"encode","signature"这几个参数有变化。因此,我们可以知道,在爬取其他音乐时我们也只是需要改这几个参数便可以。
其中,发现“clienttime”为时间戳,"encode"为音乐ID,"signature"为md5加密的参数所以,我们只需要解密'signature'此参数,我们可以通过Ctrl+Swift+f打开全局搜索,搜索'signature',发现signature参数来与此js中,我们可以点击进入js查看
进入此处,我们在signature所需要的参数此行点击打上断电,并刷新页面。鼠标选中参数详细。会发现,此处就是我们所需要的参数。32位字母数字组合。再去查看它组合方式,就会发现它就是s的参数列表,转换成字符串直接用md5加密便可。而再通过对比一下s发现它的参数除了时间戳和音乐id完全一样,因此我们可以自己组合
而后组合加密得出signature参数,便可通过改变音乐id直接请求当前音乐的MP3信息。
简单描述此操作 就是输入你想要的 音乐名 或 音乐名加作者名 搜索到音乐,获取 音乐ID 交给
第一步操作获得音乐mp3文件
我们现在需要模拟酷狗搜索栏操作,通过关键字搜索,并获取与关键字最相识的第一个音乐。
继续之前的操作,F12进入,并在左上角点击搜索按钮,搜索当前音乐名,点击进入。并进行对比发现song就是我们需要的数据
进入之后,我们会发现,搜索的所有的音乐内容都在lists中,我们只需要第一条的音乐内容,
并获取此音乐的ID与名字
再通过对比参数中signature发现和之前参数区别一样。因此,复制之前的操作便可
具体的步骤为同样搜索signature找到其js文件,打上断点调试,复制第一步的操作,得到signature参数,加入需要请求的url地址中“https://complexsearch.kugou.com/v2/search/song?”,便可得到搜索的音乐id "EAlbumID"。将其给到第一步id中运行,便可以得到想要的音乐mp3数据。
获取到此音频地址后,对地址发送请求,将请求得到的数据以二进制的方式保存到指定目录文件夹中
- import hashlib
- import os
- import time
- import requests
- import re
- import json
- from tkinter import *
-
- def directory_create():
- """判断文件是否存在。不存在则创建改文件"""
- directory = "./music_files"
- if not os.path.exists(directory):
- os.makedirs(directory)
- def audio_id_list(music_name):
- """
- 通过搜索栏参数(音乐名)获取 搜索第一个的 音乐名 and ID
- :param music_name: 搜索栏参数(音乐名) 例如: 苏星婕 - 把回忆拼好给你
- :return: 音乐名 音乐ID(苏星婕 - 把回忆拼好给你 72jrv7fa)
- """
- timestamp = int(time.time() * 1000)
-
- headers = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
- }
- sign = MD5_sign_search(timestamp, music_name)
- datas = {
- 'callback': 'callback123',
- 'srcappid': '2919',
- 'clientver': '1000',
- 'clienttime': timestamp,
- 'mid': 'c4de83c1ebb2e73fc5ae95304a674918',
- 'uuid': 'c4de83c1ebb2e73fc5ae95304a674918',
- 'dfid': '3MmrUf3e5zpy3cStkN3Bn9oS',
- 'keyword': music_name,
- 'page': '1',
- 'pagesize': '30',
- 'bitrate': '0',
- 'isfuzzy': '0',
- 'inputtype': '0',
- 'platform': 'WebFilter',
- 'userid': '2078452878',
- 'iscorrection': '1',
- 'privilege_filter': '0',
- 'filter': '10',
- 'token': '483ef68936faa09268f3a42f7ab7ee31b584a3f155828a100c95fadf7c5ddd1e',
- 'appid': '1014',
- 'signature': sign,
- }
- response = requests.get(url='https://complexsearch.kugou.com/v2/search/song?', headers=headers, params=datas)
- callback_dict = re.findall('callback123\((.*)\)', response.text)[0]
- jsurl = json.loads(callback_dict)
- fileName = jsurl['data']['lists'][0]['FileName']
- eMixSongID = jsurl['data']['lists'][0]['EMixSongID']
- return fileName, eMixSongID
- def fetch_url(audio_id):
- """
- 通过音乐ID爬取当前音乐的md3地址
- :param audio_id: 音乐ID(72jrv7fa)
- :return:音乐url(........mp3)
- """
- timestamp = int(time.time() * 1000)
- print('audio_id:', audio_id)
- headers = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
- }
- sign = MD5_sign(timestamp, audio_id)
- datas = {
- 'srcappid': '2919',
- 'clientver': '20000',
- 'clienttime': timestamp,
- 'mid': 'c4de83c1ebb2e73fc5ae95304a674918',
- 'uuid': 'c4de83c1ebb2e73fc5ae95304a674918',
- 'dfid': '3MmrUf3e5zpy3cStkN3Bn9oS',
- 'appid': '1014',
- 'platid': '4',
- 'encode_album_audio_id': audio_id,
- 'token': '483ef68936faa09268f3a42f7ab7ee31b584a3f155828a100c95fadf7c5ddd1e',
- 'userid': '2078452878',
- 'signature': sign,
- }
- response = requests.get(url='https://wwwapi.kugou.com/play/songinfo?', headers=headers, params=datas)
- jsurl = response.json()
- # print('jsurl: ', jsurl)
- play_url = jsurl['data']['play_url']
- return play_url
- def download_url(file_name, url_mp3):
- """
- 通过已经获取的mp3文件保存到文件夹中
- :param file_name: 音乐名
- :param url_mp3: 音乐url(.....mp3)
- :return: 无
- """
- response = requests.get(url_mp3)
- try:
- with open(f"./music_files/{file_name}.mp3", "wb") as f:
- f.write(response.content)
- except:
- with open(f"./music_files/{int(time.time() * 1000)}.mp3", "wb") as f:
- f.write(response.content)
-
- print(f'{file_name}-----下载成功')
- def MD5_sign(timestamp, audio_id):
- """
- 通过音乐id解密详情页单个音乐的signature参数
- :param timestamp: 时间戳
- :param audio_id: 音乐id(例如:72jrv7fa)
- :return:
- """
- signature_list = ['NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt',
- 'appid=1014',
- f'clienttime={timestamp}',
- 'clientver=20000',
- 'dfid=3MmrUf3e5zpy3cStkN3Bn9oS',
- f'encode_album_audio_id={audio_id}',
- 'mid=c4de83c1ebb2e73fc5ae95304a674918',
- 'platid=4',
- 'srcappid=2919',
- 'token=483ef68936faa09268f3a42f7ab7ee31b584a3f155828a100c95fadf7c5ddd1e',
- 'userid=2078452878',
- 'uuid=c4de83c1ebb2e73fc5ae95304a674918',
- 'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt']
- string = "".join(signature_list)
- MD5 = hashlib.md5()
- MD5.update(string.encode('utf-8'))
- sign = MD5.hexdigest() # md5 32位加密内容
- return sign
-
-
- def MD5_sign_search(timestamp, music_name):
- """
- 通过音乐id解密搜索页的signature参数
- :param timestamp:时间戳
- :param music_name:搜索框音乐名(例如:把回忆拼好给你)
- :return:加密后32位md5参数(例如:72181cc6baf76ee0404837d5d657dd5c)
- """
- signature_list = ['NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt',
- 'appid=1014',
- 'bitrate=0',
- 'callback=callback123',
- f'clienttime={timestamp}',
- 'clientver=1000',
- 'dfid=3MmrUf3e5zpy3cStkN3Bn9oS',
- 'filter=10',
- 'inputtype=0',
- 'iscorrection=1',
- 'isfuzzy=0',
- f'keyword={music_name}',
- 'mid=c4de83c1ebb2e73fc5ae95304a674918',
- 'page=1',
- 'pagesize=30',
- 'platform=WebFilter',
- 'privilege_filter=0',
- 'srcappid=2919',
- 'token=483ef68936faa09268f3a42f7ab7ee31b584a3f155828a100c95fadf7c5ddd1e',
- 'userid=2078452878',
- 'uuid=c4de83c1ebb2e73fc5ae95304a674918',
- 'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt']
- string = "".join(signature_list)
- MD5 = hashlib.md5()
- MD5.update(string.encode('utf-8'))
- sign_lis = MD5.hexdigest() # md5 32位加密内容
- return sign_lis
-
- import hashlib
- import os
- import time
- import requests
- import re
- import json
- from tkinter import *
-
-
- def MD5_sign(timestamp, audio_id):
- """
- 通过音乐id解密详情页单个音乐的signature参数
- :param timestamp: 时间戳
- :param audio_id: 音乐id(例如:72jrv7fa)
- :return:
- """
- signature_list = ['NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt',
- 'appid=1014',
- f'clienttime={timestamp}',
- 'clientver=20000',
- 'dfid=3MmrUf3e5zpy3cStkN3Bn9oS',
- f'encode_album_audio_id={audio_id}',
- 'mid=c4de83c1ebb2e73fc5ae95304a674918',
- 'platid=4',
- 'srcappid=2919',
- 'token=483ef68936faa09268f3a42f7ab7ee31b584a3f155828a100c95fadf7c5ddd1e',
- 'userid=2078452878',
- 'uuid=c4de83c1ebb2e73fc5ae95304a674918',
- 'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt']
- string = "".join(signature_list)
- MD5 = hashlib.md5()
- MD5.update(string.encode('utf-8'))
- sign = MD5.hexdigest() # md5 32位加密内容
- return sign
-
-
- def MD5_sign_search(timestamp, music_name):
- """
- 通过音乐id解密搜索页的signature参数
- :param timestamp:时间戳
- :param music_name:搜索框音乐名(例如:把回忆拼好给你)
- :return:加密后32位md5参数(例如:72181cc6baf76ee0404837d5d657dd5c)
- """
- signature_list = ['NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt',
- 'appid=1014',
- 'bitrate=0',
- 'callback=callback123',
- f'clienttime={timestamp}',
- 'clientver=1000',
- 'dfid=3MmrUf3e5zpy3cStkN3Bn9oS',
- 'filter=10',
- 'inputtype=0',
- 'iscorrection=1',
- 'isfuzzy=0',
- f'keyword={music_name}',
- 'mid=c4de83c1ebb2e73fc5ae95304a674918',
- 'page=1',
- 'pagesize=30',
- 'platform=WebFilter',
- 'privilege_filter=0',
- 'srcappid=2919',
- 'token=483ef68936faa09268f3a42f7ab7ee31b584a3f155828a100c95fadf7c5ddd1e',
- 'userid=2078452878',
- 'uuid=c4de83c1ebb2e73fc5ae95304a674918',
- 'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt']
- string = "".join(signature_list)
- MD5 = hashlib.md5()
- MD5.update(string.encode('utf-8'))
- sign_lis = MD5.hexdigest() # md5 32位加密内容
- return sign_lis
-
-
- def fetch_url(audio_id):
- """
- 通过音乐ID爬取当前音乐的md3地址
- :param audio_id: 音乐ID(72jrv7fa)
- :return:音乐url(........mp3)
- """
- timestamp = int(time.time() * 1000)
- print('audio_id:', audio_id)
- headers = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
- }
- sign = MD5_sign(timestamp, audio_id)
- datas = {
- 'srcappid': '2919',
- 'clientver': '20000',
- 'clienttime': timestamp,
- 'mid': 'c4de83c1ebb2e73fc5ae95304a674918',
- 'uuid': 'c4de83c1ebb2e73fc5ae95304a674918',
- 'dfid': '3MmrUf3e5zpy3cStkN3Bn9oS',
- 'appid': '1014',
- 'platid': '4',
- 'encode_album_audio_id': audio_id,
- 'token': '483ef68936faa09268f3a42f7ab7ee31b584a3f155828a100c95fadf7c5ddd1e',
- 'userid': '2078452878',
- 'signature': sign,
- }
- response = requests.get(url='https://wwwapi.kugou.com/play/songinfo?', headers=headers, params=datas)
- jsurl = response.json()
- # print('jsurl: ', jsurl)
- play_url = jsurl['data']['play_url']
- return play_url
-
-
- def audio_id_list(music_name):
- """
- 通过搜索栏参数(音乐名)获取 搜索第一个的 音乐名 and ID
- :param music_name: 搜索栏参数(音乐名) 例如: 苏星婕 - 把回忆拼好给你
- :return: 音乐名 音乐ID(苏星婕 - 把回忆拼好给你 72jrv7fa)
- """
- timestamp = int(time.time() * 1000)
-
- headers = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
- }
- sign = MD5_sign_search(timestamp, music_name)
- datas = {
- 'callback': 'callback123',
- 'srcappid': '2919',
- 'clientver': '1000',
- 'clienttime': timestamp,
- 'mid': 'c4de83c1ebb2e73fc5ae95304a674918',
- 'uuid': 'c4de83c1ebb2e73fc5ae95304a674918',
- 'dfid': '3MmrUf3e5zpy3cStkN3Bn9oS',
- 'keyword': music_name,
- 'page': '1',
- 'pagesize': '30',
- 'bitrate': '0',
- 'isfuzzy': '0',
- 'inputtype': '0',
- 'platform': 'WebFilter',
- 'userid': '2078452878',
- 'iscorrection': '1',
- 'privilege_filter': '0',
- 'filter': '10',
- 'token': '483ef68936faa09268f3a42f7ab7ee31b584a3f155828a100c95fadf7c5ddd1e',
- 'appid': '1014',
- 'signature': sign,
- }
- response = requests.get(url='https://complexsearch.kugou.com/v2/search/song?', headers=headers, params=datas)
- callback_dict = re.findall('callback123\((.*)\)', response.text)[0]
- jsurl = json.loads(callback_dict)
- fileName = jsurl['data']['lists'][0]['FileName']
- eMixSongID = jsurl['data']['lists'][0]['EMixSongID']
- return fileName, eMixSongID
-
-
- def download_url(file_name, url_mp3):
- """
- 通过已经获取的mp3文件保存到文件夹中
- :param file_name: 音乐名
- :param url_mp3: 音乐url(.....mp3)
- :return: 无
- """
- response = requests.get(url_mp3)
- try:
- with open(f"./music_files/{file_name}.mp3", "wb") as f:
- f.write(response.content)
- except:
- with open(f"./music_files/{int(time.time() * 1000)}.mp3", "wb") as f:
- f.write(response.content)
-
- print(f'{file_name}-----下载成功')
-
-
- def directory_create():
- """判断文件是否存在。不存在则创建改文件"""
- directory = "./music_files"
- if not os.path.exists(directory):
- os.makedirs(directory)
-
-
- if __name__ == '__main__':
- directory_create() # 判断music_flie文件是否存在
-
- music_name = '听说你'
- audio_id = audio_id_list(music_name) # (苏星婕 - 把回忆拼好给你, 72jrv7fa)
- file_name = audio_id[0] # 苏星婕 - 把回忆拼好给你
- emixsong_id = audio_id[1] # 72jrv7fa
- time.sleep(2)
- url_mp3 = fetch_url(emixsong_id) # 获取 ......mp3
- download_url(file_name, url_mp3) # 下载保存
本次爬取结束,如果有什么其他问题或不懂可以私信哦~
另外还有GUI渲染过的的exe便携版,想要了解的话可以看下一篇文章
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。