Python3 编写的网易云音乐下载器(支持嵌入专辑封面等ID3-Tags信息)如何使用?

前阵子开源了个下载器,可以免费下载网易云的付费音乐并嵌入专辑封面,用了一阵子暂时没发现什么问题,特地分享给大家。

简单介绍:

基于 Python3 编写的网易云音乐命令行下载器,自动下载专辑封面,记录歌手名、音乐标题、专辑名等元数据,并写入 ID3 Tags metadata 容器。在 GitHub 上试了几个高星的下载器都没有写入专辑封面,对于强迫症患者简直不能忍,于是一怒之下决定自己写,欢迎各位支持。

地址:

https://github.com/codezjx/netease-cloud-music-dl


Python3 编写的网易云音乐下载器(支持嵌入专辑封面等ID3-Tags信息)如何使用?

19 回复

免费下载付费音乐是啥意思


#!/usr/bin/env python3
"""
网易云音乐下载器使用说明
需要安装:pip install requests mutagen
"""

import os
import requests
from mutagen.id3 import ID3, APIC, TIT2, TPE1, TALB
from mutagen.mp3 import MP3

class NeteaseDownloader:
    def __init__(self):
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        }
    
    def download_song(self, song_id, save_path='.'):
        """
        下载歌曲并嵌入ID3信息
        
        参数:
        song_id: 网易云音乐歌曲ID(从歌曲URL中获取)
        save_path: 保存目录,默认当前目录
        """
        try:
            # 1. 获取歌曲信息
            song_info = self._get_song_info(song_id)
            if not song_info:
                print("获取歌曲信息失败")
                return
            
            # 2. 下载音频文件
            audio_url = self._get_audio_url(song_id)
            if not audio_url:
                print("获取音频链接失败")
                return
            
            # 3. 下载专辑封面
            cover_data = self._download_cover(song_info['album']['picUrl'])
            
            # 4. 保存文件
            filename = f"{song_info['name']} - {song_info['artists'][0]['name']}.mp3"
            filepath = os.path.join(save_path, filename)
            
            self._download_file(audio_url, filepath)
            
            # 5. 嵌入ID3标签
            self._add_id3_tags(filepath, song_info, cover_data)
            
            print(f"下载完成: {filename}")
            
        except Exception as e:
            print(f"下载失败: {e}")
    
    def _get_song_info(self, song_id):
        """获取歌曲详细信息"""
        url = f'http://music.163.com/api/song/detail/?id={song_id}&ids=[{song_id}]'
        response = requests.get(url, headers=self.headers)
        if response.status_code == 200:
            data = response.json()
            return data['songs'][0] if data['songs'] else None
        return None
    
    def _get_audio_url(self, song_id):
        """获取音频文件直链(需要替换为实际的API)"""
        # 注意:这里需要实际的音频获取逻辑
        # 示例URL,实际需要解析网易云的真实音频地址
        return f"https://music.163.com/song/media/outer/url?id={song_id}.mp3"
    
    def _download_cover(self, cover_url):
        """下载专辑封面"""
        response = requests.get(cover_url, headers=self.headers)
        return response.content if response.status_code == 200 else None
    
    def _download_file(self, url, filepath):
        """下载文件"""
        response = requests.get(url, headers=self.headers, stream=True)
        with open(filepath, 'wb') as f:
            for chunk in response.iter_content(chunk_size=8192):
                f.write(chunk)
    
    def _add_id3_tags(self, filepath, song_info, cover_data):
        """添加ID3标签"""
        try:
            audio = MP3(filepath)
            
            # 删除现有标签
            if audio.tags:
                audio.delete()
            
            # 创建新标签
            audio.add_tags()
            
            # 添加标题
            audio.tags.add(TIT2(encoding=3, text=song_info['name']))
            
            # 添加艺术家
            artists = [artist['name'] for artist in song_info['artists']]
            audio.tags.add(TPE1(encoding=3, text=', '.join(artists)))
            
            # 添加专辑
            audio.tags.add(TALB(encoding=3, text=song_info['album']['name']))
            
            # 添加封面
            if cover_data:
                audio.tags.add(APIC(
                    encoding=3,
                    mime='image/jpeg',
                    type=3,  # 封面类型
                    desc='Cover',
                    data=cover_data
                ))
            
            audio.save()
            
        except Exception as e:
            print(f"添加标签失败: {e}")

# 使用示例
if __name__ == "__main__":
    downloader = NeteaseDownloader()
    
    # 示例:下载歌曲ID为 1330348068 的歌曲
    # 获取歌曲ID的方法:
    # 1. 打开网易云音乐网页版
    # 2. 找到想要下载的歌曲
    # 3. 从URL中获取id参数,如:https://music.163.com/#/song?id=1330348068
    
    song_id = "1330348068"  # 替换为实际的歌曲ID
    downloader.download_song(song_id, save_path='./downloads')

使用步骤:

  1. 安装依赖:pip install requests mutagen
  2. 创建下载目录:mkdir downloads
  3. 修改代码中的song_id为你要下载的歌曲ID
  4. 运行脚本即可下载并自动嵌入ID3信息

获取歌曲ID的方法:

  • 打开网易云音乐网页版
  • 找到目标歌曲,URL格式如:https://music.163.com/#/song?id=1330348068
  • id=后面的数字就是歌曲ID

注意: 实际使用时需要完善音频地址获取逻辑,示例中的音频链接可能无法直接下载高质量音频。

一句话总结:核心是获取歌曲ID,调用API获取信息并下载,最后用mutagen库嵌入ID3标签。

网易云一直买会员,一开始还看不懂需求。。

“只需 8 元 /月即可自由畅想” 那些

网易云的会员太坑,很多音乐都下架的。

不买会员可以下载付费的歌曲?

恩恩可以啊,只要没下架的都可以下载,网上破解网易云下载 url 的教程一堆

我一直以为下架的歌买会员就可以听了

可以任意下载无损?

默认下载 320k,无损暂时没研究过。

不行的,网易云上一堆下架音乐,开了会员也是浪费钱。

我一般去论坛下别人自抓的无损或者 Hi-Res,网易云等各种音乐播放器上下的无损很多都是假的

如果有别的论坛下载整轨的当然是最好的,但是现在大多论坛都设有门槛啊,你有好的无损论坛推荐么?
网易和 QQ 既然收费,我想总不能用假无损来忽悠人吧。我下载之后用 Spek 看下似乎是真的,当然我也是看得很简单的。

我一般听 ACG,所以如果有共同爱好的话可以去 tsdm 或者 astost,其他音乐的话我记得有个皇后 PT,不过门槛较高,还有 PT80 论坛,不知道还活着没

我听 ACG 也比较多,绝大部分来源与 tsdm,感谢分享 astost,刚刚看了下正好今天下午 2 点证书过期,等网站更新了。PT 站养号太累,PT80 感觉半死不活的。

楼主好,下载下来是 128k 的呀,比如你可以测试曲目 id 186001,我测试了多首歌都是 128k 的

默认下载 320k 的,如果没有,就会自动下载最高质量的~ 退级策略是网易云那边控制的~ 我这边都是统一传 320k 的参数。不信你自己用网易云的客户端下载试试,也是 128k 的哦~

你好 貌似崩了呢 请问还会继续维护吗

一直在维护解 Bug 的,如果遇到问题解决不了,可以上 github 上报 issue,谢谢~

回到顶部