Eks6666 发表于 2023-11-7 10:15

利用python下载酷狗音乐

# -*- coding: utf-8 -*-
import string
import time
import re
import random
import requests
import pprint

'''
==========================================酷狗音乐解析主要API=============================================
1.get_rank_list()   获取音乐榜单列表   返回形式:(榜单名,榜单地址)
2.get_rank_info(url)url为榜单地址 返回歌曲的信息[{}]
3.get_search_musicData(search_txt,dis_num)   search_txt:搜索内容,dis_num:总共加载几首歌曲,返回歌曲的信息[{}]
=========================================内部函数=========================================================
4.get_musicInfo(hash,id)通过传入的hash、id 返回歌名、播放地址、图片、歌词 字典形式
返回形式:music_info_dic={'audio_name':XXXX,'play_url':XXXX,'lyrics':XXX,'img':XXX}
5.klcTolrc(self,lyrics)通过传入获取的krc歌词   变成lrc形式的歌词
========================================================================================================
可以用主函数测试
'''
class kuGouMusic ():
    def __init__(self):

      self.headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36', }

    def __get_response(self, url, headers):
      res = requests.get (url, headers)
      return res

    # 获取酷狗音乐榜单
    def get_rank_list(self):
      rank_url = 'https://www.kugou.com/yy/html/rank.html'
      res = self.__get_response (rank_url, self.headers)
      res.encoding = res.apparent_encoding
      rank_list_urls = re.findall (r'<a title="(.*?)" .*? hidefocus="true" href="(.*?)"', res.text)
      return rank_list_urls

    # 获取榜单的Hash、id
    def get_rank_info(self, url):
      res = self.__get_response (url, self.headers)
      res.encoding = res.apparent_encoding
      Hash_list = re.findall ('"Hash":"(.*?)"', res.text)
      album_id_list = re.findall ('"album_id":(.*?),', res.text)
      play_list = []
      num=0
      for Hash, album_id in zip (Hash_list, album_id_list):
            print (f'\r正在加歌单歌曲列表,....当前进度:{int ((num + 1) / len (Hash_list) * 100)}%', end='')
            play_list.append (self.__get_musicInfo (Hash, album_id))
            num=num+1
      return play_list
    # ======================以下是搜索部分=============#
    def get_search_musicData(self,word='任贤齐',page_mum=1):
      url = 'http://mobilecdn.kugou.com/api/v3/search/song'
      data_list=[]
      headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
      }
      parameter={
            'keyword': word,
            'page': page_mum,
            'pagesize': '30',
      }
      res = requests.get(url, headers=headers,params=parameter).json()
      info_list=res['data']['info']
      num=0
      for info in info_list:
         print (f'\r正在加载搜索歌曲列表,....当前进度:{int ((num + 1) / len (info_list) * 100)}%', end='')
         data_list.append(self.__get_musicInfo(info['hash'],info['album_id']))
         num=num+1
      return data_list

    # ======================通过Hash,id获取到歌曲地址、LRC、封面、歌曲名共用部分=============#
    # 获取歌曲信息 hash 为字符串 id为整型数据
    def __get_musicInfo(self, hash, id):
      music_url = 'https://wwwapi.kugou.com/yy/index.php'
      parameter = {
            'r': 'play/getdata',
            'hash': hash,
            'dfid': self.__get_dfid (23),
            'mid': self.__get_mid (23),
            'album_id': id,
            '_': str (round (time.time () * 1000))# 时间戳
      }
      json_data = requests.get (music_url, headers=self.headers, params=parameter).json ()
      music_info_dic = {
            'audio_name': json_data['data']['audio_name'],
            'play_url': json_data['data']['play_url'],
            'lyrics': self.__klcTolrc(json_data['data']['lyrics']),
            'img_conntent': json_data['data']['img']
      }
      return music_info_dic

    # 获取a-z A-Z 0-9组成的随机23位数列
    def __get_dfid(self, num):
      random_str = ''.join (random.sample ((string.ascii_letters + string.digits), num))
      return random_str
    # 获取a-z0-9组成的随机23位数列
    def __get_mid(self, num):
      random_str = ''.join (random.sample ((string.ascii_letters[:26] + string.digits), num))
      return random_str
    # krc转成lrc
    def __klcTolrc(self, lyrics):
      index = lyrics.find ('[00:00')
      lyrics = lyrics
      return lyrics



if __name__ == '__main__':
    d = kuGouMusic ()
    # url='https://www.kugou.com/yy/rank/home/1-8888.html?from=rank'
    # lis=d.get_rank_info(url)
    # pprint.pprint(lis)
    lis2=d.get_search_musicData()
    print(lis2)


LeonSmith153 发表于 2023-11-15 01:02

本帖最后由 LeonSmith153 于 2023-11-15 01:04 编辑

感觉蛮好的,改进了一下代码,可以将搜索到的歌曲进行分行列出,用户可以根据需要选择要保存的歌词文件。

# -*- coding: utf-8 -*-
import string
import time
import re
import random
import requests
import pprint

'''
==========================================酷狗音乐解析主要API=============================================
1.get_rank_list()   获取音乐榜单列表   返回形式:(榜单名,榜单地址)
2.get_rank_info(url)url为榜单地址 返回歌曲的信息[{}]
3.get_search_musicData(search_txt,dis_num)   search_txt:搜索内容,dis_num:总共加载几首歌曲,返回歌曲的信息[{}]
=========================================内部函数=========================================================
4.get_musicInfo(hash,id)通过传入的hash、id 返回歌名、播放地址、图片、歌词 字典形式
返回形式:music_info_dic={'audio_name':XXXX,'play_url':XXXX,'lyrics':XXX,'img':XXX}
5.klcTolrc(self,lyrics)通过传入获取的krc歌词   变成lrc形式的歌词
========================================================================================================
可以用主函数测试
'''
class kuGouMusic ():
    def __init__(self):

      self.headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36', }

    def __get_response(self, url, headers):
      res = requests.get (url, headers)
      return res

    # 获取酷狗音乐榜单
    def get_rank_list(self):
      rank_url = 'https://www.kugou.com/yy/html/rank.html'
      res = self.__get_response (rank_url, self.headers)
      res.encoding = res.apparent_encoding
      rank_list_urls = re.findall (r'<a title="(.*?)" .*? hidefocus="true" href="(.*?)"', res.text)
      return rank_list_urls

    # 获取榜单的Hash、id
    def get_rank_info(self, url):
      res = self.__get_response (url, self.headers)
      res.encoding = res.apparent_encoding
      Hash_list = re.findall ('"Hash":"(.*?)"', res.text)
      album_id_list = re.findall ('"album_id":(.*?),', res.text)
      play_list = []
      num=0
      for Hash, album_id in zip (Hash_list, album_id_list):
            print (f'\r正在加歌单歌曲列表,....当前进度:{int ((num + 1) / len (Hash_list) * 100)}%', end='')
            play_list.append (self.__get_musicInfo (Hash, album_id))
            num=num+1
      return play_list
    # ======================以下是搜索部分=============#
    def get_search_musicData(self,word='任贤齐',page_mum=1):
      url = 'http://mobilecdn.kugou.com/api/v3/search/song'
      data_list=[]
      headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
      }
      parameter={
            'keyword': word,
            'page': page_mum,
            'pagesize': '30',
      }
      res = requests.get(url, headers=headers,params=parameter).json()
      info_list=res['data']['info']
      num=0
      for info in info_list:
         print (f'\r正在加载搜索歌曲列表,....当前进度:{int ((num + 1) / len (info_list) * 100)}%', end='')
         data_list.append(self.__get_musicInfo(info['hash'],info['album_id']))
         num=num+1
      return data_list

    # ======================通过Hash,id获取到歌曲地址、LRC、封面、歌曲名共用部分=============#
    # 获取歌曲信息 hash 为字符串 id为整型数据
    def __get_musicInfo(self, hash, id):
      music_url = 'https://wwwapi.kugou.com/yy/index.php'
      parameter = {
            'r': 'play/getdata',
            'hash': hash,
            'dfid': self.__get_dfid (23),
            'mid': self.__get_mid (23),
            'album_id': id,
            '_': str (round (time.time () * 1000))# 时间戳
      }
      json_data = requests.get (music_url, headers=self.headers, params=parameter).json ()
      music_info_dic = {
            'audio_name': json_data['data']['audio_name'],
            'play_url': json_data['data']['play_url'],
            'lyrics': self.__klcTolrc(json_data['data']['lyrics']),
            'img_conntent': json_data['data']['img']
      }
      return music_info_dic

    # 获取a-z A-Z 0-9组成的随机23位数列
    def __get_dfid(self, num):
      random_str = ''.join (random.sample ((string.ascii_letters + string.digits), num))
      return random_str
    # 获取a-z0-9组成的随机23位数列
    def __get_mid(self, num):
      random_str = ''.join (random.sample ((string.ascii_letters[:26] + string.digits), num))
      return random_str
    # krc转成lrc
    def __klcTolrc(self, lyrics):
      index = lyrics.find ('[00:00')
      lyrics = lyrics
      return lyrics



if __name__ == '__main__':
    d = kuGouMusic ()
    # url='https://www.kugou.com/yy/rank/home/1-8888.html?from=rank'
    # lis=d.get_rank_info(url)
    # pprint.pprint(lis)
    lis2=d.get_search_musicData()
    print("\n")
    for i in range(len(lis2)):
      i_audio_name = lis2['audio_name']
      i_play_url = lis2['play_url']
      #i_lyrics = lis2['lyrics']
      i_img_conntent = lis2['img_conntent']
      print(str(i) + "--->" + i_audio_name)
      print(i_play_url)
      print(i_img_conntent)
    print("请输入要保存的歌词索引:")
    number = input()
    with open(lis2['audio_name'] + "_lyrics.txt", 'w') as f:
      f.write(str(lis2['lyrics']))
    #print(lis2)

恋丶你的语 发表于 2023-11-17 15:16

感谢楼主分享,我将代码转换成了PHP的API接口,可以放到自己的网站上
<?php
class kuGouMusicAPI {
    private $headers = array(
      'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
    );

    private function __get_response($url, $headers) {
      $res = file_get_contents($url, false, stream_context_create(array('http' => $headers)));
      return $res;
    }

    public function getRankList() {
      $rank_url = 'https://www.kugou.com/yy/html/rank.html';
      $res = $this->__get_response($rank_url, $this->headers);
      preg_match_all('/<a title="(.*?)" .*? hidefocus="true" href="(.*?)"/', $res, $matches, PREG_SET_ORDER, 1);
      $rank_list_urls = array_slice($matches, 1);
      return $rank_list_urls;
    }

    public function getRankInfo($url) {
      $res = $this->__get_response($url, $this->headers);
      preg_match_all('/"Hash":"(.*?)"/', $res, $hash_matches);
      preg_match_all('/"album_id":(.*?),/', $res, $album_id_matches);
      $Hash_list = $hash_matches;
      $album_id_list = $album_id_matches;
      $play_list = array();
      foreach ($Hash_list as $index => $Hash) {
            $album_id = $album_id_list[$index];
            $play_list[] = $this->__get_musicInfo($Hash, $album_id);
      }
      return $play_list;
    }

    public function getSearchMusicData($word = '任贤齐', $page_num = 1) {
      $url = 'http://mobilecdn.kugou.com/api/v3/search/song';
      $data_list = array();
      $parameter = array(
            'keyword' => $word,
            'page' => $page_num,
            'pagesize' => '30'
      );
      $res = file_get_contents($url . '?' . http_build_query($parameter), false, stream_context_create(array('http' => $this->headers)));
      $res = json_decode($res, true);
      $info_list = $res['data']['info'];
      foreach ($info_list as $info) {
            $data_list[] = $this->__get_musicInfo($info['hash'], $info['album_id']);
      }
      return $data_list;
    }

    private function __get_musicInfo($hash, $id) {
      $music_url = 'https://wwwapi.kugou.com/yy/index.php';
      $parameter = array(
            'r' => 'play/getdata',
            'hash' => $hash,
            'dfid' => $this->__get_dfid(23),
            'mid' => $this->__get_mid(23),
            'album_id' => $id,
            '_' => round(microtime(true) * 1000)
      );
      $music_json = $this->__get_response($music_url . '?' . http_build_query($parameter), $this->headers);
      $music_info = json_decode($music_json, true);
      $music_info_dic = array(
            'audio_name' => $music_info['data']['audio_name'],
            'play_url' => $music_info['data']['play_url'],
            'lyrics' => $this->__klcTolrc($music_info['data']['lyrics']),
            'img_conntent' => $music_info['data']['img']
      );
      return $music_info_dic;
    }

    private function __get_dfid($num) {
      $random_str = substr(str_shuffle(str_repeat('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', $num)), 0, $num);
      return $random_str;
    }

    private function __get_mid($num) {
      $random_str = substr(str_shuffle('abcdefghijklmnopqrstuvwxyz0123456789'), 0, $num);
      return $random_str;
    }

    private function __klcTolrc($lyrics) {
      $index = strpos($lyrics, '[00:00');
      $lyrics = substr($lyrics, $index);
      return $lyrics;
    }
}

// 创建API实例
$kuGouAPI = new kuGouMusicAPI();

// 处理API请求
if (isset($_GET['action'])) {
    $action = $_GET['action'];
    switch ($action) {
      case 'getRankList':
            $result = $kuGouAPI->getRankList();
            echo json_encode($result);
            break;
      case 'getRankInfo':
            if (isset($_GET['url'])) {
                $url = $_GET['url'];
                $result = $kuGouAPI->getRankInfo($url);
                echo json_encode($result);
            } else {
                echo json_encode(array('error' => 'Missing "url" parameter.'));
            }
            break;
      case 'getSearchMusicData':
            $word = isset($_GET['word']) ? $_GET['word'] : '任贤齐';
            $page_num = isset($_GET['page_num']) ? $_GET['page_num'] : 1;
            $result = $kuGouAPI->getSearchMusicData($word, $page_num);
            echo json_encode($result);
            break;
      default:
            echo json_encode(array('error' => 'Invalid action.'));
    }
} else {
    echo json_encode(array('error' => 'Missing "action" parameter.'));
}
?>
用法:
获取音乐榜单列表:http://your-api-url/api.php?action=getRankList
获取榜单详细信息:http://your-api-url/api.php?action=getRankInfo&url=https://www.kugou.com/yy/rank/home/1-8888.html?from=rank
搜索音乐数据:http://your-api-url/api.php?action=getSearchMusicData&word=关键词&page_num=1

action:确定要执行的操作,可以是以下之一:
getRankList:获取音乐榜单列表。
getRankInfo:获取榜单的详细信息,需要提供url参数指定榜单的地址。
getSearchMusicData:搜索音乐数据,可以提供以下参数:
    word:搜索关键词,默认为'任贤齐'。
    page_num:搜索结果的页数,默认为1。

www39012 发表于 2024-1-26 23:57

LeonSmith153 发表于 2024-1-22 20:48
只是获取了资源链接喝资源信息,你根据链接下载对应的音乐资源就好了

谢谢大佬,不懂代码的小白不好意思哈哈

mebyan 发表于 2024-2-29 20:24

复制代码粘贴保存为py文件运行后,出现以下错误,请问是接口变了吗?
in __get_musicInfo
    'audio_name': json_data['data']['audio_name'],

TypeError: list indices must be integers or slices, not str

贾东平 发表于 2023-11-7 10:27

多谢楼主分享。

mei251617 发表于 2023-11-7 10:28

多谢楼主分享。

bydlyzx 发表于 2023-11-7 10:34

可以下载无损吗?

wanjiaoer 发表于 2023-11-7 10:42


多谢楼主分享。

freeflys 发表于 2023-11-7 10:48

多谢楼主分享。

四哥! 发表于 2023-11-7 10:52


多谢楼主分享。

weizhao911 发表于 2023-11-7 11:07

学习了,膜拜

alentonly 发表于 2023-11-7 11:14

谢谢楼主,很有用

bpz1028 发表于 2023-11-7 11:15

做个小程序就好!
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 利用python下载酷狗音乐