项目概述

本文将介绍如何使用Python开发一个网易云音乐榜单歌曲批量下载器。这个工具可以帮助你轻松下载网易云音乐任意榜单中的所有歌曲,只需输入榜单名称和ID即可。项目使用requests库进行网络请求,re库进行正则表达式匹配,实现了简单高效的音乐下载功能。

技术栈

  • Python 3.x
  • requests: 用于发送HTTP请求,获取网页内容和下载音乐文件
  • re: 正则表达式,用于解析网页内容,提取歌曲信息
  • os: 用于文件和目录操作
  • tqdm: 用于显示下载进度条,提升用户体验

项目结构

import requests
import re
import os
from tqdm import tqdm

# 请求头配置
headers = {
    # 请求头信息
}

def createFolder(name):
    """创建对应的文件夹"""
    
def get_html(rankId):
    """获取网页的内容"""
    
def get_music(htmlContent):
    """获取歌曲信息"""
    
def downloadMusic(name, InfoList):
    """下载歌曲"""

if __name__ == '__main__':
    # 主程序入口

详细实现

1. 请求头配置

headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'cookie': '_iuqxldmzr_=32; _ntes_nnid=5fe3228939599e5837938ad61adb3b47,1763302635945; _ntes_nuid=5fe3228939599e5837938ad61adb3b47; NMTID=00O-LksnKg26W4HyE87rnxuiV7Dky4AAAGajQb3Mw; WEVNSM=1.0.0; WNMCID=ounhws.1763302636890.01.0; WM_TID=gzL05QFZdMVEEQQUERPTzdGzVHtXCmU%2B; sDeviceId=YD-SrNUhGX1pEZFRlQRURLD3IHyQWtSD5S7; ntes_utid=tid._.QKG8PdhVL3BFV0AAVQfGyZCjRD5SX8X9._.0; __snaker__id=USbawQMECvM3w1un; ntes_kaola_ad=1; __remember_me=true; MUSIC_U=00253093384AAA22E1341DE736D1774F2CD0BDE81EA787B6A25C248181E86B6472E3B5FF91CDBDB5F617E52F7D8CD9C775E245C968CBBDA7175C9538AE2396AD12591839F88E8F03DB8D62F6B9C74BC9E50BC768F7D4E52AE1164D9697A2872D5D56C30A324D5623F098041668CC33A46FC020CAF21430CB58BA0AEAB0AB1C50805933B510B607F9C46F6407E05EEC65D1367ABD73AC498229FBABC6471E664E2A6A139900E943824236EDA120880F6DEE539DA3B9CBB3056873CB500B1240C39E0B0D833C84516FA6717775E03D18F2CF949D548409688DD59232B69A3F43AFA7784790562078E6261A57DFD906339B9402FC72A04A79D5242CAB47DBE963FB386EE1D730CBA177F113E77FD1615B8AD4ED08151B5DA923D9907121A1B6ABA223CDC591C516FFFF1C557EEE821890500DB0B12B6135CDD31A1125546A27233F6AB36EAFF41AEADB3E6399394C2FB3E933FCBB7BDDF75203C436F644D6BF6CE4ED5DBC4226133B71CB4B77855BBBA5C9E3C7B46931594CE3995508F8BE0A52B32F65FE73946A0C17EF069F6DBA1397E9F803BEEEB62F47ED95EE69DFF31963D9EF; vinfo_n_f_l_n3=7c9909ea4d9edf3c.1.0.1766121512724.0.1766121519248; _ntes_origin_from=bing; __csrf=5d21084669e73ce3cfe23f7f9a4fd530; WM_NI=VGerjPqhJ9673ErUbGBzhhHK5Enh8zdTArIpaDulz4qIKaio2yM2mTWLZ2d%2FtBNEZkRrol0QQGqApoCYUmSxTeNGM9PtPY8H9QCcnImOtQaEFLGq9Qjoot5ilt9v0WvwOTU%3D; WM_NIKE=9ca17ae2e6ffcda170e2e6ee8ece7391b28b85ca4ff89a8ab6c85f938e8e87c239b3bcffb0ed5382eb9b86c72af0fea7c3b92a9699ab93e95cb3b886dab53df19bbeb6e14d82a6a889cb41f79ba289bb72a88c8f93cc7ca39cbb8df940b3978582ec65f2a783d3f060959496d3e725b89e82a6d96192aea18db35b9399bfa2f36581879b8ed27498bb82a8d03394aca0babb44fb8f8d84ed43af91bcb2e44f86948992bc5baab1a195b863b0acf797b35db6a981b5d837e2a3; gdxidpyhxdE=PYix989AZJ9SC%2BPUycA7n6QsVxlSGMTlRe0w%2B1mZ2tLH0tIVaXQyLiTy4pjG5j7kHw0hvBujvbCdatWHGpyJvho81%2FE2Wtv9ITYNbaifo%2Fj30Z1wQsuEEDxpSJXNuxbvr6qSevd1o40%5CjcULiA%5CfaBORoKg6Dq7ZDaJxRZlkEbEowPKt%3A1768797806468; JSESSIONID-WYYY=hG9oZpf72h%2Fsx1OAKx3KPgKTHpXucGT6SwIrME7uIPr9%2FEv%5CbfUJ9%2B7PGwJ5U6%5CYJcG5Hd9uO%2FQKu%5CRXCfsCyS75Jf3VU8%2Fj5CE%5C%2BmarKj9iiW%2BcDJ7zuF58FSkfiN3zo4o8%2BSbDnfb0BS%2FY2986m%2F7tNMhnINSylSrzFZWagnYYPQp4%3A1768799532469',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 Edg/144.0.0.0'
}

配置了完整的请求头信息,包括accept、cookie和user-agent,这有助于模拟浏览器行为,避免被网易云音乐的反爬机制识别。

2. 创建文件夹函数

def createFolder(name):
    """
    创建对应的文件夹
    :param name: 文件名
    :return:
    """
    if not os.path.exists(name):
        os.mkdir(name)

这个函数用于创建存储下载音乐的文件夹。它会检查指定名称的文件夹是否已存在,如果不存在则创建新文件夹。

3. 获取网页内容函数

def get_html(rankId):
    """
    获取网页的内容
    :param rankId: 榜单id
    :return: 返回网页内容
    """
    # 榜单网址
    url = f'https://music.163.com/discover/toplist?id={rankId}'
    # 向网页发起请求
    response = requests.get(url, headers=headers)
    # 返回网页内容
    return response.text

这个函数接收一个榜单ID作为参数,构建完整的榜单页面URL,然后发送HTTP GET请求获取页面内容。

4. 提取歌曲信息函数

def get_music(htmlContent):
    """
    获取歌曲
    :param htmlContent: 网页内容
    :return: 返回获取的id和标题列表
    """
    # 获取歌曲的id和标题
    musicInfo = re.findall(r'<a href="/song\?id=(\d+)">(.*?)</a>', htmlContent)
    return musicInfo

这个函数使用正则表达式从网页内容中提取歌曲ID和标题。它查找所有匹配<a href="/song?id=歌曲ID">歌曲标题</a>模式的内容,并返回一个包含(歌曲ID, 歌曲标题)元组的列表。

5. 下载音乐函数

def downloadMusic(name, InfoList):
    """
    下载歌曲
    :param name: 文件名
    :param InfoList: 歌曲的id和标题列表
    :return:
    """
    for music_id, music_title in tqdm(InfoList):
        # 歌曲的url
        music_url = f'https://music.163.com/song/media/outer/url?id={music_id}.mp3'
        music = requests.get(music_url, headers=headers).content
        # 将获取的歌曲存储在文件夹中
        with open(name + '\\' + music_title + '.mp3', 'wb') as f:
            f.write(music)

这个函数负责下载歌曲:

  • 使用tqdm库显示下载进度条
  • 遍历歌曲信息列表,对每首歌曲:
    • 构建音乐文件的URL
    • 发送请求获取音乐文件内容
    • 将音乐文件保存到指定文件夹中

6. 主程序

if __name__ == '__main__':
    filename = input('请输入榜单名称: ')
    createFolder(filename)
    rank_id = input('请输入榜单id: ')
    html = get_html(rank_id)
    # 歌曲信息列表
    musicInfoList = get_music(html)
    # 下载音乐
    downloadMusic(filename, musicInfoList)

主程序流程:

  1. 提示用户输入榜单名称
  2. 创建对应名称的文件夹
  3. 提示用户输入榜单ID
  4. 获取榜单页面内容
  5. 提取歌曲信息
  6. 下载所有歌曲到创建的文件夹中

完整代码

import requests
import re
import os
from tqdm import tqdm

headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'cookie': '_iuqxldmzr_=32; _ntes_nnid=5fe3228939599e5837938ad61adb3b47,1763302635945; _ntes_nuid=5fe3228939599e5837938ad61adb3b47; NMTID=00O-LksnKg26W4HyE87rnxuiV7Dky4AAAGajQb3Mw; WEVNSM=1.0.0; WNMCID=ounhws.1763302636890.01.0; WM_TID=gzL05QFZdMVEEQQUERPTzdGzVHtXCmU%2B; sDeviceId=YD-SrNUhGX1pEZFRlQRURLD3IHyQWtSD5S7; ntes_utid=tid._.QKG8PdhVL3BFV0AAVQfGyZCjRD5SX8X9._.0; __snaker__id=USbawQMECvM3w1un; ntes_kaola_ad=1; __remember_me=true; MUSIC_U=00253093384AAA22E1341DE736D1774F2CD0BDE81EA787B6A25C248181E86B6472E3B5FF91CDBDB5F617E52F7D8CD9C775E245C968CBBDA7175C9538AE2396AD12591839F88E8F03DB8D62F6B9C74BC9E50BC768F7D4E52AE1164D9697A2872D5D56C30A324D5623F098041668CC33A46FC020CAF21430CB58BA0AEAB0AB1C50805933B510B607F9C46F6407E05EEC65D1367ABD73AC498229FBABC6471E664E2A6A139900E943824236EDA120880F6DEE539DA3B9CBB3056873CB500B1240C39E0B0D833C84516FA6717775E03D18F2CF949D548409688DD59232B69A3F43AFA7784790562078E6261A57DFD906339B9402FC72A04A79D5242CAB47DBE963FB386EE1D730CBA177F113E77FD1615B8AD4ED08151B5DA923D9907121A1B6ABA223CDC591C516FFFF1C557EEE821890500DB0B12B6135CDD31A1125546A27233F6AB36EAFF41AEADB3E6399394C2FB3E933FCBB7BDDF75203C436F644D6BF6CE4ED5DBC4226133B71CB4B77855BBBA5C9E3C7B46931594CE3995508F8BE0A52B32F65FE73946A0C17EF069F6DBA1397E9F803BEEEB62F47ED95EE69DFF31963D9EF; vinfo_n_f_l_n3=7c9909ea4d9edf3c.1.0.1766121512724.0.1766121519248; _ntes_origin_from=bing; __csrf=5d21084669e73ce3cfe23f7f9a4fd530; WM_NI=VGerjPqhJ9673ErUbGBzhhHK5Enh8zdTArIpaDulz4qIKaio2yM2mTWLZ2d%2FtBNEZkRrol0QQGqApoCYUmSxTeNGM9PtPY8H9QCcnImOtQaEFLGq9Qjoot5ilt9v0WvwOTU%3D; WM_NIKE=9ca17ae2e6ffcda170e2e6ee8ece7391b28b85ca4ff89a8ab6c85f938e8e87c239b3bcffb0ed5382eb9b86c72af0fea7c3b92a9699ab93e95cb3b886dab53df19bbeb6e14d82a6a889cb41f79ba289bb72a88c8f93cc7ca39cbb8df940b3978582ec65f2a783d3f060959496d3e725b89e82a6d96192aea18db35b9399bfa2f36581879b8ed27498bb82a8d03394aca0babb44fb8f8d84ed43af91bcb2e44f86948992bc5baab1a195b863b0acf797b35db6a981b5d837e2a3; gdxidpyhxdE=PYix989AZJ9SC%2BPUycA7n6QsVxlSGMTlRe0w%2B1mZ2tLH0tIVaXQyLiTy4pjG5j7kHw0hvBujvbCdatWHGpyJvho81%2FE2Wtv9ITYNbaifo%2Fj30Z1wQsuEEDxpSJXNuxbvr6qSevd1o40%5CjcULiA%5CfaBORoKg6Dq7ZDaJxRZlkEbEowPKt%3A1768797806468; JSESSIONID-WYYY=hG9oZpf72h%2Fsx1OAKx3KPgKTHpXucGT6SwIrME7uIPr9%2FEv%5CbfUJ9%2B7PGwJ5U6%5CYJcG5Hd9uO%2FQKu%5CRXCfsCyS75Jf3VU8%2Fj5CE%5C%2BmarKj9iiW%2BcDJ7zuF58FSkfiN3zo4o8%2BSbDnfb0BS%2FY2986m%2F7tNMhnINSylSrzFZWagnYYPQp4%3A1768799532469',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 Edg/144.0.0.0'
}

def createFolder(name):
    """
    创建对应的文件夹
    :param name: 文件名
    :return:
    """
    if not os.path.exists(name):
        os.mkdir(name)

def get_html(rankId):
    """
    获取网页的内容
    :param rankId: 榜单id
    :return: 返回网页内容
    """
    # 榜单网址
    url = f'https://music.163.com/discover/toplist?id={rankId}'
    # 向网页发起请求
    response = requests.get(url, headers=headers)
    # 返回网页内容
    return response.text

def get_music(htmlContent):
    """
    获取歌曲
    :param htmlContent: 网页内容
    :return: 返回获取的id和标题列表
    """
    # 获取歌曲的id和标题
    musicInfo = re.findall(r'<a href="/song\?id=(\d+)">(.*?)</a>', htmlContent)
    return musicInfo

def downloadMusic(name, InfoList):
    """
    下载歌曲
    :param name: 文件名
    :param InfoList: 歌曲的id和标题列表
    :return:
    """
    for music_id, music_title in tqdm(InfoList):
        # 歌曲的url
        music_url = f'https://music.163.com/song/media/outer/url?id={music_id}.mp3'
        music = requests.get(music_url, headers=headers).content
        # 将获取的歌曲存储在文件夹中
        with open(name + '\\' + music_title + '.mp3', 'wb') as f:
            f.write(music)

if __name__ == '__main__':
    filename = input('请输入榜单名称: ')
    createFolder(filename)
    rank_id = input('请输入榜单id: ')
    html = get_html(rank_id)
    # 歌曲信息列表
    musicInfoList = get_music(html)
    # 下载音乐
    downloadMusic(filename, musicInfoList)

在这里插入图片描述

运行前准备

  1. 安装依赖包
pip install requests tqdm
  1. 更新Cookie
    • 由于网易云音乐的反爬机制,Cookie可能会过期
    • 建议在运行前,从浏览器中获取最新的Cookie替换到代码中
    • 获取方法:在浏览器中登录网易云音乐,按F12打开开发者工具,在Network选项卡中找到请求头中的Cookie

如何使用

  1. 获取榜单ID

    • 打开网易云音乐官网,进入任意榜单页面
    • 从URL中获取榜单ID,例如:https://music.163.com/discover/toplist?id=3778678 中的 3778678 就是榜单ID
  2. 运行程序

    python netease_music_downloader.py
    
  3. 输入信息

    • 根据提示输入榜单名称(用于创建文件夹)
    • 输入榜单ID
  4. 查看结果

    • 程序会自动创建以榜单名称命名的文件夹
    • 所有歌曲会下载到该文件夹中

常见榜单ID参考

榜单名称榜单ID
热歌榜3778678
新歌榜3779629
飙升榜19723756
电音榜10520166
古典音乐榜71385702
欧美热歌榜60198
韩国流行榜11641012
日本流行榜60131

总结

这个网易云音乐榜单歌曲批量下载器项目展示了如何使用Python的requests和re库进行简单的网页爬虫和文件下载操作。通过这个项目,你可以轻松下载网易云音乐任意榜单中的所有歌曲,方便离线收听。

希望本文对大家学习Python爬虫和文件下载有所帮助!

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐