Skip to main content

cloudmusic

一个轻量的网易云音乐 Python 客户端:查询歌曲、专辑、歌单、歌词、评论和用户公开资料,并下载当前账号有权访问的完整音频。

支持 Python 3.10–3.14。保留 getMusic()、getPlaylist()、search() 等原有调用方式。

当前维护版本为 0.2.0。历史 HTML/PDF 文档对应 0.1.1,当前接口以本 README 为准。

安装

python -m pip install --upgrade cloudmusic

也可以从源码安装:

git clone https://github.com/p697/cloudmusic.git
cd cloudmusic
python -m pip install .

运行时仅依赖 requests 和 pycryptodomex,不再要求 lxml 或 threadpool。

快速开始

import cloudmusic

music = cloudmusic.getMusic(1347630432)
print(music.name, music.artist, music.album)
print(music.getLyrics())  # [原文歌词, 翻译歌词];缺失项为空字符串

results = cloudmusic.search("白日", number=5)
for song in results:
    print(song.id, song.name)

playlist = cloudmusic.getPlaylist(310729011)
print(len(playlist))

歌曲信息与音频权限相互独立。获取歌曲名称、专辑、歌词或评论不需要先获取播放地址。访问 music.url、size、type、level 或 freeTrialInfo 时,才获取音频信息;同一批歌曲共享批量请求。音频信息缓存 60 秒,以减少重复请求和过期链接。

try:
    print(music.url)    # 没有播放权限时可能为 None;接口风控会抛出 APIError
    print(music.level)  # 服务实际返回的品质,可能低于请求品质
    path = music.download(dirs="./downloads")
    print(path)        # 已保存文件的绝对路径
except cloudmusic.CloudMusicError as error:
    print(error)

下载采用流式写入和临时文件替换。只有成功完成下载才覆盖同名目标文件;失败会保留已有文件并清理临时文件。仅有试听音频时抛出 UnavailableError,不会把试听片段当成完整歌曲保存。

配置会话

默认匿名访问。需要账号权限时,可以显式传入自己的 cookie;库不包含任何内置登录凭据,不自动读取浏览器或环境中的凭据。

import os
import cloudmusic

with cloudmusic.Client(
    cookie=os.environ.get("NETEASE_COOKIE"),
    timeout=(5, 20),  # 连接超时、单次读取超时,单位秒
    level="higher",
    # proxies={"https": "http://127.0.0.1:7890"},
) as client:
    music = client.getMusic(1347630432)
    songs = client.search("白日", 5)

# 返回的 Music/User 对象保留配置;关闭 Client 后仍可按需调用。
print(music.getLyrics())

cookie 支持 cookie 字符串或字典。Client 复用查询连接并保留服务端更新的会话 cookie,使用完毕后应调用 close() 或用 with 管理。网络错误和风控错误不会自动反复重试;同批音频遇到验证/登录限制后,在 60 秒内复用该错误,避免批量任务重复触发限制。音频 CDN 请求不携带网易云登录 cookie。

该项目依赖网易云的非官方接口。接口返回内容受登录状态、隐私设置、地区和音频权限限制;升级客户端不能保证获取所有歌曲、无限评论或指定音质。不要将 cookie 提交到 Git 或输出到公开日志。

API

以下函数也可以通过 Client 调用:

函数 返回值
getMusic(id) 一个 Music 对象
getMusic([id, ...]) Music 列表,保留输入顺序和重复 ID;单元素列表仍返回列表;空列表返回 []
getPlaylist(id) 按歌单顺序排列的 Music 列表
getAlbum(id) 按专辑顺序排列的 Music 列表
search(content, number=5) 最多 number 个不重复的搜索结果;支持分页;无结果返回 []
getUser(id) User 对象

ID 支持正整数或整数字符串。无效参数抛出 ValueError;歌曲 ID 不存在时抛出 NotFoundError,其 ids 字段包含缺失 ID。歌单返回数量与服务报告的总数不一致时抛出 IncompleteResultError,不会静默当作完整歌单。

try:
    songs = cloudmusic.getPlaylist(310729011)
except cloudmusic.IncompleteResultError as error:
    print(error.actual_count, error.expected_count)
    songs = error.partial_result  # 调用方明确选择是否使用已获取部分

Music

元数据属性:id(字符串)、name、artist、artistId、album、albumId、picUrl。

按需获取的音频属性:url、size、type、level、freeTrialInfo。

方法 行为
download(dirs="", level=None) 默认保存到当前目录的 cloudmusic 文件夹;level=None 沿用创建对象时的请求品质(默认 higher)
getLyrics() 返回 [原文, 翻译],缺失项为空字符串
getHotComments(number=15) 最多 15 条热评
getComments(number) 按时间从新到旧,使用游标分页;不足时返回可获取的数量
getCommentsCount() 服务报告的评论总数

品质参数保留 standard、higher、exhigh、lossless。实际品质由接口和账号权限决定。指定音质不会丢失下载目录,文件扩展名取服务实际返回值。

评论字段:commentId、likeCount、content、time、userId、nickName、avatarUrl、vipType、userType。用户已注销或字段缺失时,昵称和头像可以为空。若服务表示还有数据但分页无法继续,抛出带 partial_result 的 IncompleteResultError,避免无限循环或重复结果。

User

属性:id、level、listenSongs、createTime、nickname(也支持 nickName)、avatarUrl、city、province、vipType、birthday、signature、fans、follows、eventCount、playlistCount、sex。部分资料可能因隐私设置缺失。

  • getPlaylist():分页获取可访问的用户歌单,返回信息字典列表。字段包括 id、name、creatorId、playCount、createTime、coverImgUrl、updateTime、tags。
  • getRecord(recordType=0):0 为所有时间,正整数为最近一周;返回 {"score": ..., "music": Music} 列表,只请求所需周期。

批量下载

loader = cloudmusic.createLoader(procs=2, dirs="./downloads")
loader.data = cloudmusic.getPlaylist(310729011)
try:
    loader.start()
except cloudmusic.DownloadError:
    print(loader.errors)  # 失败项:以 data 中的索引为键
print(loader.results)     # 成功保存的绝对路径,按输入顺序排列

最多同时使用 32 个工作线程。文件名会处理跨平台非法字符和过长名称;同名歌曲仍会覆盖同一目标文件,请选择适当的目录管理下载结果。

错误类型

均继承 CloudMusicError,无效调用参数使用标准 ValueError。

类型 含义
RequestError 网络/超时/非 200 HTTP 响应;status_code 在 HTTP 失败时可用
APIError 网易云业务错误;保留 code 和 message,包括风控、验证或登录要求
ResponseError JSON 或响应结构异常
NotFoundError 指定歌曲不存在,保留 ids
UnavailableError 没有完整音频可供下载
IncompleteResultError 歌单不完整或分页停止前进;保留 partial_result
DownloadError 文件下载未完整完成或批量下载部分失败

测试与开发

python -m pip install -e '.[test]'
python -m pytest --cov=cloudmusic --cov-branch --cov-report=term-missing
python -m ruff check cloudmusic tests
python -m build

默认测试禁止外部联网,并通过本地 HTTP 服务验证流式下载、错误响应、中断、临时文件清理和已有文件保护。CI 在 Linux、macOS、Windows 上运行 Python 3.10、3.12、3.14 的测试,以及独立 wheel 安装检查。

真实接口测试显式启用,依赖当前网络环境和服务状态,不参与必过 CI:

python -m pytest --live -m live -v

真实测试默认匿名,不修改账号内容,也不批量下载音频。远端拒绝会表现为测试失败,不会被记为成功。若已在本机配置测试账号的 NETEASE_COOKIE 环境变量,可以明确启用登录态测试:

python -m pytest --live --cookie-env NETEASE_COOKIE -m live -v --tb=short

未传 --cookie-env 时测试不会读取任何登录 cookie。具体实测范围和限制见 验收记录。

从 0.1.1 迁移

  • Python 最低版本更新为 3.10。
  • 原有高层函数和对象属性保留,修正了单元素列表返回类型。
  • 音频属性按需读取;网络/权限错误可能在访问这些属性时出现。
  • 下载默认沿用对象品质;明确传入 level="standard" 时会请求该品质。
  • 错误不再以字符串、打印信息、None 或意外 KeyError 混合返回;请处理相应异常。
  • query.py 内部旧 HTML 抓取函数已移除。内部模块不是稳定 API。

发布维护版本

维护者在 GitHub Actions 手动运行 Publish to PyPI,选择 master 并填写与源码一致的版本号。流程先执行跨平台 CI,再构建、检查和独立安装分发包,最后通过 PyPI Trusted Publishing 上传;无需保存长期 API token。

PyPI 的可信发布者配置为仓库 p697/cloudmusic、工作流 release.yml、环境 pypi。发布环境仅允许 master 分支。修改版本号后应先通过 PR 合并,再启动发布。

历史贡献参考:PR #14、PR #17、PR #21。本轮吸收了跨平台路径和音质目录传递的修复方向;封面/标签写入功能暂未纳入。

MIT License · @p697

Metadata

Release files for cloudmusic 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cloudmusic 0.2.0
File Size Uploaded
cloudmusic-0.2.0.tar.gz 34.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cloudmusic 0.2.0
File Interpreter ABI Platform
cloudmusic-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 55.6 kB

Release files / cloudmusic-0.2.0.tar.gz

Download URL cloudmusic-0.2.0.tar.gz
Size 34.2 kB
Tags Source
SHA-256 checksum
How to use checksums
c4ed5d7a40e2b7dda45ba8bca8a2ccff806cb6057bf8e7cc6918021939cfc7f6
BLAKE2b-256 checksum
How to use checksums
779c39859dbc84c6b386823afd7d0a8633e33783c4148a7ac4b6276524ccb770
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release files / cloudmusic-0.2.0-py3-none-any.whl

Download URL cloudmusic-0.2.0-py3-none-any.whl
Size 21.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
396b233f60b98726e3f9fe94ecf91c96d50938fc243733bdc2ae9ed7021beb22
BLAKE2b-256 checksum
How to use checksums
6ef8e52e2e40b510cbb67830ae8d7d162ac30d177804fbc113c786f2493bab0d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.1

1 release file

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page