功能强大的网易云音乐解析工具 - PHP 版
支持歌曲搜索 · 单曲解析 · 歌单解析 · 专辑解析 · 音乐下载(含元数据与歌词写入) · 扫码登录
基于 Suxiaoqinx/Netease_url Python 项目的 PHP 移植版本,提供完整的网易云音乐解析与下载服务。
纯 PHP 实现,无依赖框架,支持 PHP 内置服务器、Apache、Nginx 三种部署方式。下载时自动写入 ID3/VorbisComment 元数据、专辑封面与歌词(LRC),无需外部工具即可工作。
| 功能 | 说明 |
|---|---|
| 🔍 歌曲搜索 | 关键词搜索网易云音乐库,支持设置返回数量 |
| 🎧 单曲解析 | 解析单首歌曲的详细信息、播放链接、歌词 |
| 📋 歌单解析 | 批量解析歌单中所有歌曲 |
| 💿 专辑解析 | 批量解析专辑中所有歌曲 |
| ⬇️ 音乐下载 | 多音质下载,自动写入元数据 + 封面 + 歌词 |
| 📱 扫码登录 | 二维码扫码自动获取 Cookie |
| 🎤 歌词写入 | MP3 写入 USLT 帧,FLAC 写入 LYRICS/UNSYNCEDLYRICS 字段 |
| 参数 | 说明 | 码率/规格 | 权限 |
|---|---|---|---|
standard |
标准音质 | 128 kbps | 普通 |
exhigh |
极高音质 | 320 kbps | 黑胶 VIP |
lossless |
无损音质 | FLAC | 黑胶 VIP |
hires |
Hi-Res 音质 | 24bit / 96kHz | 黑胶 VIP |
jyeffect |
高清环绕声 | - | 黑胶 VIP |
sky |
沉浸环绕声 | - | 黑胶 SVIP |
jymaster |
超清母带 | - | 黑胶 SVIP |
dolby |
杜比全景声 | EAC3 | 黑胶 SVIP |
下载时自动写入以下信息(无需手动操作):
| 字段 | MP3 (ID3v2.3) | FLAC (VorbisComment) |
|---|---|---|
| 标题 | TIT2 |
TITLE |
| 艺术家 | TPE1 / TPE2 |
ARTIST / ALBUMARTIST |
| 专辑 | TALB |
ALBUM |
| 音轨号 | TRCK |
TRACKNUMBER |
| 备注 | COMM |
COMMENT |
| 封面 | APIC |
PICTURE 块 |
| 歌词(原文) | USLT (UTF-16) |
LYRICS + UNSYNCEDLYRICS |
| 歌词(翻译) | USLT (description=翻译) |
TRANSLATEDLYRICS |
歌词为网易云返回的 LRC 格式文本,包含时间戳。
# 需要 PHP ≥ 7.4,推荐 8.0+
php -v
# 检查必需扩展(curl / openssl / fileinfo)
php -r "foreach(['curl','openssl','fileinfo'] as \$e) echo \$e.': '.(extension_loaded(\$e)?'OK':'MISSING').PHP_EOL;"git clone https://github.com/yourname/Netease_php_url.git
cd Netease_php_url方式 A:手动填入 Cookie(点击展开)
在 cookie.txt 中填入网易云音乐黑胶会员账号的 Cookie:
MUSIC_U=your_music_u_value; __csrf=your_csrf; NMTID=your_nmtid;
获取 Cookie 步骤:
- 登录 网易云音乐网页版
- 按 F12 打开开发者工具 → Network 标签页
- 复制任意请求的 Cookie 值,粘贴到
cookie.txt
方式 B:扫码登录(推荐,点击展开)
php qr_login.php login按提示使用网易云音乐 APP 扫码登录,Cookie 自动保存到 cookie.txt。
# PHP 内置服务器(开发推荐)
php -d extension=curl -d extension=openssl -S 0.0.0.0:5000 index.php打开浏览器访问 http://localhost:5000/
php -d extension=curl -d extension=openssl -S 0.0.0.0:5000 index.php优点:零配置,开箱即用 适用:本地开发、测试
- 将项目放入 Apache Web 目录(如
/var/www/Netease_php_url) - 确保
mod_rewrite已启用:sudo a2enmod rewrite sudo systemctl restart apache2
- 项目根目录的 .htaccess 会自动生效
- 参考 Nginx_Rewrite.txt 创建站点配置:
sudo cp Nginx_Rewrite.txt /etc/nginx/sites-available/netease sudo ln -s /etc/nginx/sites-available/netease /etc/nginx/sites-enabled/
- 修改配置文件中的
root路径和server_name - 测试并重载:
sudo nginx -t && sudo nginx -s reload
FROM php:8.2-apache
RUN apt-get update && apt-get install -y ffmpeg libcurl4-openssl-dev libssl-dev
RUN docker-php-ext-install curl openssl fileinfo
RUN a2enmod rewrite
COPY . /var/www/html/
RUN chown -R www-data:www-data /var/www/html
EXPOSE 80docker build -t netease-php .
docker run -d -p 5000:80 --name netease netease-phpNetease_php_url/
├── index.php # 主入口,路由分发与 API 处理
├── config.php # 配置文件(API 地址、密钥、音质、ffmpeg 路径)
├── music_api.php # API 类(EAPI 加密、HTTP、搜索、歌曲、歌单、专辑、歌词、二维码)
├── music_downloader.php # 下载器类(同步下载、双模式元数据写入、歌词写入)
├── qr_login.php # 二维码登录 CLI 工具
├── cookie.txt # Cookie 配置文件
├── .htaccess # Apache 重写与敏感文件保护
├── Nginx_Rewrite.txt # Nginx 站点配置示例
├── templates/
│ └── index.html # Web 操作界面
├── libs/getid3/ # getID3 纯 PHP 库(元数据写入,无需 ffmpeg)
└── downloads/ # 下载文件目录(自动创建,禁止直接访问)
- 功能选择:歌曲搜索
- 输入关键词,设置返回数量
- 点击 搜索
- 在结果中点击 解析 或 下载
- 功能选择:单曲解析
- 输入歌曲 ID 或链接
- 选择音质,点击 解析
- 查看歌曲信息、歌词、在线试听(APlayer 播放器)
- 点击 点击下载 直接下载(自动重命名为
歌手-歌名-音质.格式)
- 功能选择:歌单解析 或 专辑解析
- 输入 ID 或链接
- 点击解析,查看全部曲目
- 对单首歌曲点击 解析 或 下载
- 功能选择:音乐下载
- 输入音乐 ID 或链接
- 选择音质,点击 下载音乐
- 文件自动下载到本地(含元数据、封面、歌词)
- 功能选择:扫码登录
- 点击 生成二维码
- 使用网易云音乐 APP 扫码
- 手机确认后 Cookie 自动保存到服务器
| 项目 | 值 |
|---|---|
| Base URL | http://localhost:5000 |
| 请求方式 | GET / POST |
| 响应格式 | JSON |
{
"status": 200,
"success": true,
"message": "操作描述",
"data": { ... }
}错误时:
{
"status": 400,
"success": false,
"message": "错误描述"
}GET /health
curl http://localhost:5000/health响应示例
{
"status": 200,
"success": true,
"message": "API服务运行正常",
"data": {
"service": "running",
"timestamp": 1783907849,
"cookie_status": "valid",
"cookie_count": 3,
"downloads_dir": "/var/www/Netease_php_url/downloads",
"metadata": {
"engine": "getID3",
"fallback": null,
"ffmpeg": { "available": false, "path": null, "version": null },
"getid3": { "available": true }
},
"version": "2.0.0-php"
}
}POST /search
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
| keyword | string | ✅ | - | 搜索关键词 |
| limit | int | ❌ | 30 | 返回数量(最大 100) |
curl -X POST http://localhost:5000/search \
-d "keyword=周杰伦 稻香&limit=10"响应示例
{
"status": 200,
"success": true,
"message": "搜索完成",
"data": [
{
"id": 185668,
"name": "稻香",
"artists": "周杰伦",
"album": "魔杰座",
"picUrl": "https://p3.music.126.net/..."
}
]
}POST /song
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
| id | string | ✅ | - | 歌曲 ID 或链接 |
| level | string | ❌ | lossless |
音质等级 |
| type | string | ❌ | url |
返回类型 |
type 取值:
| 值 | 说明 |
|---|---|
url |
仅返回播放链接 |
name |
返回歌曲详情 |
lyric |
返回歌词 |
json |
完整信息(播放链接 + 详情 + 歌词) |
# 获取完整信息
curl -X POST http://localhost:5000/song \
-d "id=185668&level=lossless&type=json"响应示例(type=json)
{
"status": 200,
"success": true,
"message": "获取歌曲信息成功",
"data": {
"id": "185668",
"name": "烟花易冷",
"ar_name": "周杰伦",
"al_name": "跨时代",
"pic": "https://p2.music.126.net/...",
"level": "lossless",
"url": "https://...",
"size": "28.44MB",
"lyric": "[00:00.000] 作词 : ...",
"tlyric": ""
}
}POST /playlist
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | ✅ | 歌单 ID 或链接 |
curl -X POST http://localhost:5000/playlist \
-d "id=123456789"POST /album
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | ✅ | 专辑 ID 或链接 |
curl -X POST http://localhost:5000/album \
-d "id=123456789"POST /download
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
| id | string | ✅ | - | 音乐 ID 或链接 |
| quality | string | ❌ | lossless |
音质等级 |
| format | string | ❌ | file |
返回格式:file / json |
| force | int | ❌ | 0 |
1 = 强制重新下载并写入元数据 |
# 直接下载文件
curl -X POST http://localhost:5000/download \
-d "id=185668&quality=lossless" \
-o "song.flac"
# 仅获取文件信息(不下载实际文件)
curl -X POST http://localhost:5000/download \
-d "id=185668&quality=lossless&format=json"
# 强制重新下载并写入元数据(忽略已存在文件)
curl -X POST http://localhost:5000/download \
-d "id=185668&quality=lossless&force=1"响应说明
format=file:直接返回音频文件流,响应头包含:
Content-Type: audio/flacContent-Disposition: attachment; filename="..."X-Download-Filename: URL 编码的文件名X-Download-Message: Download completed successfully
format=json:返回文件元数据,包含 metadata_written(true=成功 / false=失败 / null=跳过)和 metadata_status 字段。
force 参数:默认情况下,已存在的文件会直接返回(跳过元数据写入)。设置 force=1 会删除已存在文件并重新下载+写入元数据。
生成二维码:
GET /qr/key
curl http://localhost:5000/qr/key响应:
{
"status": 200,
"success": true,
"message": "二维码生成成功",
"data": {
"unikey": "8f604271-...",
"qr_url": "https://music.163.com/login?codekey=...",
"expire_time": 180
}
}检查扫码状态:
GET /qr/status?key=<unikey>
curl "http://localhost:5000/qr/status?key=8f604271-..."状态码说明:
| code | status | 说明 |
|---|---|---|
| 801 | waiting |
等待扫码 |
| 802 | scanned |
已扫码,等待手机确认 |
| 803 | success |
登录成功,Cookie 已保存 |
| 800 | expired |
二维码已过期 |
GET /api/info
qr_login.php 提供命令行扫码登录功能:
# 扫码登录(推荐)
php qr_login.php login
# 查看登录状态
php qr_login.php status
# 登出(清除 Cookie,自动备份)
php qr_login.php logout
# 显示帮助
php qr_login.php help不带参数进入交互模式:
=== 网易云音乐登录工具 ===
1. 二维码登录
2. 查看登录状态
3. 登出
4. 退出
请选择操作 (1-4):
# 歌曲链接
https://music.163.com/song?id=1234567890
https://music.163.com/#/song?id=1234567890
# 歌单链接
https://music.163.com/playlist?id=1234567890
https://music.163.com/#/playlist?id=1234567890
# 专辑链接
https://music.163.com/album?id=1234567890
https://music.163.com/#/album?id=1234567890
# 短链接(自动解析重定向)
https://163cn.tv/xxxxx
# 直接使用 ID
1234567890
主配置文件 config.php:
| 常量 | 默认值 | 说明 |
|---|---|---|
NETEASE_PORT |
5000 |
服务监听端口 |
DOWNLOADS_DIR |
./downloads |
下载目录 |
COOKIE_FILE |
./cookie.txt |
Cookie 文件路径 |
MAX_FILE_SIZE |
500MB |
最大文件大小限制 |
DOWNLOAD_RETENTION_DAYS |
0 |
下载文件保留天数,超过 N 天自动清理(0 = 不清理) |
CORS_ORIGINS |
* |
CORS 跨域来源 |
FFMPEG_PATH |
环境变量 | ffmpeg 路径,留空自动检测;不可用降级 getID3 |
QUALITY_LEVELS |
8 种音质 | 支持的音质等级列表 |
本程序采用 双模式架构 写入音频元数据/封面/歌词,确保在各种环境都能正常工作:
| 模式 | 引擎 | 说明 | 支持格式 |
|---|---|---|---|
| 主模式 | ffmpeg | 命令行工具,支持全格式 | MP3/FLAC/M4A/MP4/OGG/Opus |
| 降级模式 | getID3 | 纯 PHP 库,无需外部依赖 | MP3/FLAC/OGG/Opus |
工作流程:
- 启动时检测 ffmpeg(优先
FFMPEG_PATH常量/环境变量,其次 PATH 查找) - 下载完成后优先调用 ffmpeg 写入元数据
- ffmpeg 不可用或写入失败时,自动降级到 getID3 纯 PHP 库
- 前端在单曲解析和音乐下载界面实时显示当前使用的引擎
ffmpeg 模式的歌词处理:
- FLAC:直接通过
-metadata lyrics=写入 - MP3:ffmpeg 不支持 USLT 帧,写入后调用 getID3 补写歌词
getID3 模式的歌词处理:
- MP3:使用 ID3v2.3 USLT 帧(UTF-16 with BOM 编码)
- FLAC:使用 VORBIS_COMMENT 的
LYRICS+UNSYNCEDLYRICS+TRANSLATEDLYRICS字段 - FLAC 写入使用纯 PHP 实现(流式 I/O),不依赖 getID3 的 metaflac 外部工具
安装 ffmpeg(可选,获得最佳兼容性):
# Ubuntu / Debian
sudo apt install ffmpeg
# CentOS / RHEL (需 EPEL)
sudo yum install ffmpeg
# macOS
brew install ffmpeg
# Windows
# 下载 https://ffmpeg.org/download.html 并添加到 PATH指定 ffmpeg 路径(环境变量,可选):
# Linux / macOS
export FFMPEG_PATH=/usr/local/bin/ffmpeg
# Windows
set FFMPEG_PATH=C:\ffmpeg\bin\ffmpeg.exe即使不安装 ffmpeg,程序也会自动使用内置的 getID3 纯 PHP 库写入元数据和歌词,无需任何额外配置。
以下文件禁止通过 Web 直接访问(返回 403):
| 文件 | 说明 |
|---|---|
cookie.txt |
Cookie 凭据 |
config.php |
配置文件 |
music_api.php |
API 核心代码 |
music_downloader.php |
下载器代码 |
qr_login.php |
CLI 工具 |
.env / .htaccess / .htpasswd |
配置文件 |
downloads/ 目录 |
下载文件(仅可通过 API 访问) |
三层防护:
| Web 服务器 | 实现方式 |
|---|---|
| PHP 内置服务器 | index.php 中正则匹配拦截 |
| Apache | .htaccess 的 <FilesMatch> 规则 |
| Nginx | Nginx_Rewrite.txt 的 location 规则 |
默认 * 允许所有来源跨域。生产环境建议限制为特定域名:
// config.php
define('CORS_ORIGINS', 'https://yourdomain.com');网易云接口使用 EAPI 加密:
- URL 路径
/eapi/替换为/api/ - 计算摘要
MD5("nobody{path}use{payload}md5forencrypt") - 拼接参数
{path}-36cd479b6b5-{payload}-36cd479b6b5-{digest} - AES-128-ECB 加密(PKCS7 填充)
- 转换为十六进制字符串
PHP 实现使用 openssl_encrypt() + AES-128-ECB。
网易云图片直链需对图片 ID 特殊加密:
- 使用魔数串
3go8&$8*3*3h0k(2)2与 ID 逐字符 XOR - 计算 MD5(返回原始二进制)
- Base64 编码,替换为 URL 安全字符(
/→_,+→-)
- 支持标准格式
k1=v1; k2=v2 - 支持换行分隔
- 自动跳过
#开头的注释行 - 有效性判断:检查
MUSIC_U/__csrf/NMTID任一字段存在
下载文件统一命名为 歌手-歌名-音质.格式,例如:
周杰伦-屋顶-lossless.flac
周杰伦/温岚/吴宗宪-屋顶-standard.mp3
- 文件名中的非法字符(
<>:"/\|?*)会被替换为_ - 文件名最大长度 200 字符
- 扩展名优先使用 API 返回的
type字段,URL 后缀兜底
Q:获取播放链接返回 url: null 或 size: 0?
原因:
- Cookie 未配置或已失效 → 执行
php qr_login.php login重新登录 - 音质需要更高 VIP 等级 → 尝试降低音质(如
exhigh) - 歌曲版权限制 → 换其他歌曲
空 cookie.txt 会导致网易云 API 返回 null URL 和 0 size,下载文件会显示 0B。
Q:提示 Call to undefined function curl_init()?
PHP 未启用 curl 扩展:
# 方式 1:修改 php.ini,取消注释
extension=curl
extension=openssl
# 方式 2:启动时临时加载
php -d extension=curl -d extension=openssl -S 0.0.0.0:5000 index.phpQ:下载的文件没有封面/元数据/歌词?
程序采用双模式写入元数据:优先使用 ffmpeg,不可用时降级到内置的 getID3 纯 PHP 库。
- 前端提示检查:单曲解析和音乐下载界面顶部会显示当前元数据引擎状态
- 安装 ffmpeg(推荐,支持全格式含 M4A/MP4):
# Linux
sudo apt install ffmpeg
# macOS
brew install ffmpeg
# Windows: 下载 https://ffmpeg.org/download.html 并添加到 PATH- 或确保 getID3 库完整(纯 PHP,无需安装,支持 MP3/FLAC/OGG/Opus):
git clone https://github.com/JamesHeinrich/getID3.git libs/getid3
rm -rf libs/getid3/.git-
虚拟主机注意:若
shell_exec/exec被禁用,ffmpeg 不可用,程序会自动降级到 getID3 -
文件已存在跳过元数据写入:默认情况下已存在的文件会直接返回,跳过元数据写入。使用
force=1参数强制重新下载并写入元数据。
Q:如何修改监听端口?
# 方式 1:启动时指定
php -S 0.0.0.0:8080 index.php
# 方式 2:修改 config.php
define('NETEASE_PORT', 8080);Q:服务重启后 Cookie 丢失?
不会丢失。扫码登录后 Cookie 写入 cookie.txt 文件持久保存,重启服务不影响。若 Cookie 失效,重新执行 php qr_login.php login。
Q:cookie.txt 中可以写注释吗?
可以。以 # 开头的行会被自动跳过:
# 这是注释,不会被解析
MUSIC_U=xxx; __csrf=yyy; # 行内注释不会被识别,请整行写
NMTID=zzz;
| 端点 | 方法 | 说明 |
|---|---|---|
/ |
GET | Web 界面 |
/health |
GET | 健康检查(含元数据引擎状态) |
/search |
GET/POST | 歌曲搜索 |
/song |
GET/POST | 单曲解析(支持 url/name/lyric/json) |
/playlist |
GET/POST | 歌单解析 |
/album |
GET/POST | 专辑解析 |
/download |
GET/POST | 音乐下载(支持 file/json 格式,force 参数) |
/qr/key |
GET | 生成二维码 |
/qr/status |
GET | 检查扫码状态 |
/api/info |
GET | API 信息 |
- 原项目作者:Suxiaoqinx - Netease_url
- Ravizhan
- getID3 - 纯 PHP 元数据读写库
本项目旨在为开源社区做贡献,鼓励用户在遵守开源精神的前提下使用和分享代码。虽然 MIT 许可证允许商业使用,但希望用户能尊重开源精神,合理使用本项目。