【源码】利用python下载酷狗音乐

项目架构与技术栈

Jsoup库的应用

Jsoup是一款Java库,用于解析HTML文档。它提供了一套非常直观且强大的API来提取和操作HTML数据。在本项目中,Jsoup主要用于两个方面:

  • 解析音乐榜单页面和音乐详情页面:通过Jsoup连接到指定URL,获取并解析HTML文档,进而提取出音乐列表、音乐详情链接等信息。
  • 获取音乐下载链接:访问每首歌曲的详情页面,解析页面HTML,获取音乐的高清下载链接、歌词链接和封面图片链接。

Hutool工具库的应用

Hutool是一个小而全的Java工具类库,它简化了Java开发中的文件操作、网络操作等。在本项目中,Hutool的主要作用体现在:

  • 文件下载:使用HttpUtil.downloadFile方法,根据解析得到的音乐、歌词和封面图的URL,下载文件到本地指定路径。
  • 字符串和文件处理:使用Hutool的字符串处理和文件操作功能,生成随机的dfidmid参数,以及处理歌词文件的格式转换。

并发下载管理

尽管原始代码示例中并未使用并发下载,但实际应用中考虑到下载效率,可以利用Java的并发编程机制,如ExecutorService,来实现音乐文件的并行下载,大幅提升爬虫的工作效率。

关键技术细节

网络请求和HTML解析

通过Jsoup发起HTTP GET请求,并携带适当的请求头以模拟浏览器行为,绕过基本的反爬虫策略。随后,利用Jsoup强大的选择器提取所需数据。

歌词格式转换

考虑到酷狗音乐提供的歌词可能是KRC格式,本项目中实现了一个从KRC到LRC(标准歌词格式)的转换方法,确保歌词的可用性和兼容性。

数据提取与处理

使用正则表达式和Jsoup选择器从HTML文档中提取音乐信息,如歌曲名、歌手、下载链接等。并且,通过Hutool工具类库对下载的数据进行管理,如检查文件是否已下载,避免重复下载。

# -*- 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)[1:]
        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-z  0-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[index:]
        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)
  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农之家★资源共享

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值