From 788570d1253ffd46000b2f68c07b8d8a2dd91371 Mon Sep 17 00:00:00 2001 From: yuluo <2216847528@qq.com> Date: Thu, 9 May 2024 09:53:39 +0800 Subject: [PATCH] updates for promise --- docs/.vitepress/config.mts | 4 - ...344\272\221\351\237\263\344\271\220API.md" | 3363 +++++++++++++++++ docs/front-end/04-ES6/17-promise.md | 58 +- ...se\350\207\252\345\256\232\344\271\211.md" | 1471 +++++++ 4 files changed, 4885 insertions(+), 11 deletions(-) create mode 100644 "docs/blogs/01-technology/02-\347\275\221\346\230\223\344\272\221\351\237\263\344\271\220API.md" create mode 100644 "docs/front-end/04-ES6/18-promise\350\207\252\345\256\232\344\271\211.md" diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 0b780880..0bfd30ef 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -55,10 +55,6 @@ export default defineConfig({ text: 'Ajax', link: '/front-end/07-ajax/' }, - { - text: 'Promise', - link: '/front-end/' - }, { text: 'Nodejs', link: '/front-end/05-Node.js/' diff --git "a/docs/blogs/01-technology/02-\347\275\221\346\230\223\344\272\221\351\237\263\344\271\220API.md" "b/docs/blogs/01-technology/02-\347\275\221\346\230\223\344\272\221\351\237\263\344\271\220API.md" new file mode 100644 index 00000000..b2ef5aa8 --- /dev/null +++ "b/docs/blogs/01-technology/02-\347\275\221\346\230\223\344\272\221\351\237\263\344\271\220API.md" @@ -0,0 +1,3363 @@ +## 接口地址 + +接口地址:http://api.fuming.site:54255/ + +文档地址:https://neteasecloudmusicapi-docs.4everland.app/#/ + +## [接口文档](https://neteasecloudmusicapi.vercel.app/#/?id=接口文档) + +### [调用前须知](https://neteasecloudmusicapi.vercel.app/#/?id=调用前须知) + +本项目不提供线上 demo,请不要轻易信任使用他人提供的公开服务,以免发生安全问题,泄露自己的账号和密码 + +为使用方便,降低门槛, 文档示例接口直接使用了 GET 请求,本项目同时支持 GET/POST 请按实际需求使用 (POST 请求 url 必须添加时间戳,使每次请求 url 不一样,不然请求会被缓存) + +由于接口做了缓存处理 ( 缓存 2 分钟,不缓存数据极容易引起网易服务器高频 ip 错误 , 可在 app.js 设置 , 可能会导致登录后获取不到 cookie), **相同的 url** 会在两分钟内只向网易服务器发一次请求 , 如果遇到不需要缓 存结果的接口 , 可在请求 url 后面加一个时间戳参数使 url 不同 , 例子 : `/simi/playlist?id=347230×tamp=1503019930000` (之所以加入缓存机制是因为项目早期没有缓存机制,很多 issues 都是报 IP 高频,请按自己需求改造缓存中间件(app.js),源码不复杂) + +不要频繁调登录接口,不然可能会被风控,登录状态还存在就不要重复调登录接口 + +如果是跨域请求 , 请在所有请求带上 `xhrFields: { withCredentials: true }` (axios 为 `withCredentials: true`, Fetch API 为 `fetch(url, { credentials: 'include' })`), 或直接手动传入 cookie (参见 `登录`), 否则 可能会因为没带上 cookie 导致 301, 具体例子可看 `public/test.html`, 访问`http://localhost:3000/test.html`(默认端口的话) 例子使用 jQuery 和 axios + +301 错误基本都是没登录就调用了需要登录的接口,如果登录了还是提示 301, 基本都是缓存把数据缓存起来了,解决方法是加时间戳或者等待 2 分钟或者重启服务重新登录后再调用接口,可自行改造缓存方法 + +部分接口如登录接口不能调用太频繁 , 否则可能会触发 503 错误或者 ip 高频错误 ,若需频繁调用 , 需要准备 IP 代理池 (更新:已加入缓存机制,但仍需注意). + +本项目仅供学习使用,请尊重版权,请勿利用此项目从事商业行为或进行破坏版权行为 + +文档可能会有缓存 , 如果文档版本和 github 上的版本不一致,请清除缓存再查看 + +由于网易限制,此项目在国外服务器或部分国内云服务上使用会受到限制,如 `460 cheating异常`,如需解决 , 可使用`realIP`参数,传进国内IP解决,如:`?realIP=116.25.146.177` 即可解决 + +图片加上 `?param=宽y高` 可控制图片尺寸,如 `http://p4.music.126.net/JzNK4a5PjjPIXAgVlqEc5Q==/109951164154280311.jpg?param=200y200`, `http://p4.music.126.net/JzNK4a5PjjPIXAgVlqEc5Q==/109951164154280311.jpg?param=50y50` + +分页接口返回字段里有`more`,more 为 true 则为有下一页 + +### [登录](https://neteasecloudmusicapi.vercel.app/#/?id=登录) + +说明 : 登录有三个接口,建议使用`encodeURIComponent`对密码编码或者使用`POST`请求,避免某些特殊字符无法解析,如`#`(`#`在 url 中会被识别为 hash,而不是 query) + +不要频繁调登录接口,不然可能会被风控,登录状态还存在就不要重复调登录接口 + +#### [1. 手机登录](https://neteasecloudmusicapi.vercel.app/#/?id=_1-手机登录) + +**必选参数 :** +`phone`: 手机号码 + +`password`: 密码 + +**可选参数 :** +`countrycode`: 国家码,用于国外手机号登录,例如美国传入:`1` + +`md5_password`: md5 加密后的密码,传入后 `password` 参数将失效 + +`captcha`: 验证码,使用 [`/captcha/sent`](https://neteasecloudmusicapi.vercel.app/#/?id=发送验证码)接口传入手机号获取验证码,调用此接口传入验证码,可使用验证码登录,传入后 `password` 参数将失效 + +**接口地址 :** `/login/cellphone` + +**调用例子 :** `/login/cellphone?phone=xxx&password=yyy` `/login/cellphone?phone=xxx&md5_password=yyy` `/login/cellphone?phone=xxx&captcha=1234` + +#### [2. 邮箱登录](https://neteasecloudmusicapi.vercel.app/#/?id=_2-邮箱登录) + +**必选参数 :** + +`email`: 163 网易邮箱 + +`password`: 密码 + +**可选参数 :** + +`md5_password`: md5 加密后的密码,传入后 `password` 将失效 + +**接口地址 :** `/login` + +**调用例子 :** `/login?email=xxx@163.com&password=yyy` + +完成登录后 , 会在浏览器保存一个 Cookies 用作登录凭证 , 大部分 API 都需要用到这个 Cookies,非跨域情况请求会自动带上 Cookies,跨域情况参考`调用前须知` + +v3.30.0 后支持手动传入 cookie,登录接口返回内容新增 `cookie` 字段,保存到本地后,get 请求带上`?cookie=xxx` (先使用 `encodeURIComponent()` 编码 cookie 值) 或者 post 请求 body 带上 `cookie` 即可,如:`/user/cloud?cookie=xxx` 或者 + +``` +{ + ..., + cookie:"xxx" +} +``` + +#### [3. 二维码登录](https://neteasecloudmusicapi.vercel.app/#/?id=_3-二维码登录) + +说明: 二维码登录涉及到 3 个接口,调用务必带上时间戳,防止缓存 + +##### [1. 二维码 key 生成接口](https://neteasecloudmusicapi.vercel.app/#/?id=_1-二维码-key-生成接口) + +说明: 调用此接口可生成一个 key + +**接口地址 :** `/login/qr/key` + +##### [2. 二维码生成接口](https://neteasecloudmusicapi.vercel.app/#/?id=_2-二维码生成接口) + +说明: 调用此接口传入上一个接口生成的 key 可生成二维码图片的 base64 和二维码信息,可使用 base64 展示图片,或者使用二维码信息内容自行使用第三方二维码生成库渲染二维码 + +必选参数: `key`,由第一个接口生成 + +可选参数: `qrimg` 传入后会额外返回二维码图片 base64 编码 + +**接口地址 :** `/login/qr/create` + +**调用例子 :** `/login/qr/create?key=xxx` + +##### [3. 二维码检测扫码状态接口](https://neteasecloudmusicapi.vercel.app/#/?id=_3-二维码检测扫码状态接口) + +说明: 轮询此接口可获取二维码扫码状态,800 为二维码过期,801 为等待扫码,802 为待确认,803 为授权登录成功(803 状态码下会返回 cookies) + +必选参数: `key`,由第一个接口生成 + +**接口地址 :** `/login/qr/check` + +**调用例子 :** `/login/qr/check?key=xxx` + +调用可参考项目文件例子`/public/qrlogin.html` (访问地址:http://localhost:3000/qrlogin.html) + +#### [3. 游客登录](https://neteasecloudmusicapi.vercel.app/#/?id=_3-游客登录) + +说明 : 直接调用此接口, 可获取游客cookie,如果遇到其他接口未登录状态报400状态码需要验证的错误,可使用此接口获取游客cookie避免报错 + +**接口地址 :** `/register/anonimous` + +#### [注意](https://neteasecloudmusicapi.vercel.app/#/?id=注意) + +调用登录接口的速度比调用其他接口慢 , 因为登录过程调用了加密算法 + +### [刷新登录](https://neteasecloudmusicapi.vercel.app/#/?id=刷新登录) + +说明 : 调用此接口 , 可刷新登录状态,返回内容包含新的cookie(不支持刷新二维码登录的cookie) + +**调用例子 :** `/login/refresh` + +### [发送验证码](https://neteasecloudmusicapi.vercel.app/#/?id=发送验证码) + +说明 : 调用此接口 ,传入手机号码, 可发送验证码 + +**必选参数 :** `phone`: 手机号码 + +**可选参数 :** `ctcode`: 国家区号,默认 86 即中国 + +**接口地址 :** `/captcha/sent` + +**调用例子 :** `/captcha/sent?phone=13xxx` + +### [验证验证码](https://neteasecloudmusicapi.vercel.app/#/?id=验证验证码) + +说明 : 调用此接口 ,传入手机号码和验证码, 可校验验证码是否正确 + +**必选参数 :** `phone`: 手机号码 + +`captcha`: 验证码 + +**可选参数 :** + +`ctcode`: 国家区号,默认 86 即中国 + +**接口地址 :** `/captcha/verify` + +**调用例子 :** `/captcha/verify?phone=13xxx&captcha=1597` + +### [注册(修改密码)](https://neteasecloudmusicapi.vercel.app/#/?id=注册修改密码) + +说明 : 调用此接口 ,传入手机号码和验证码,密码,昵称, 可注册网易云音乐账号(同时可修改密码) + +**必选参数 :** + +`captcha`: 验证码 + +`phone` : 手机号码 + +`password`: 密码 + +`nickname`: 昵称 + +**可选参数 :** + +`countrycode`: 国家码,用于国外手机号,例如美国传入:`1` ,默认 86 即中国 + +**接口地址 :** `/register/cellphone` + +**调用例子 :** `/register/cellphone?phone=13xxx&password=xxxxx&captcha=1234&nickname=binary1345` + +### [检测手机号码是否已注册](https://neteasecloudmusicapi.vercel.app/#/?id=检测手机号码是否已注册) + +说明 : 调用此接口 ,可检测手机号码是否已注册 +**必选参数 :** +`phone` : 手机号码 + +**可选参数 :** +`countrycode`: 国家码,用于国外手机号,例如美国传入:`1` ,默认 86 即中国 + +**接口地址 :** `/cellphone/existence/check` + +**调用例子 :** `/cellphone/existence/check?phone=13xxx` + +### [初始化昵称](https://neteasecloudmusicapi.vercel.app/#/?id=初始化昵称) + +说明 : 刚注册的账号(需登录),调用此接口 ,可初始化昵称 +**必选参数 :** `nickname` : 昵称 + +**接口地址 :** `/activate/init/profile` + +**调用例子 :** `/activate/init/profile?nickname=testUser2019` + +### [重复昵称检测](https://neteasecloudmusicapi.vercel.app/#/?id=重复昵称检测) + +说明 : 调用此接口 ,可检测昵称是否重复,并提供备用昵称 **必选参数 :** `nickname` : 昵称 + +**接口地址 :** `/nickname/check` + +**调用例子 :** `/nickname/check?nickname=binaryify` + +### [更换绑定手机](https://neteasecloudmusicapi.vercel.app/#/?id=更换绑定手机) + +说明 : 调用此接口 ,可更换绑定手机(流程:先发送验证码到原手机号码,再发送验证码到新手机号码然后再调用此接口) + +**必选参数 :** `oldcaptcha`: 原手机验证码 + +`captcha`: 新手机验证码 + +`phone` : 手机号码 + +`ctcode` : 国家区号,默认 86 即中国 + +**接口地址 :** `/rebind` + +**调用例子 :** `/rebind?phone=xxx&oldcaptcha=1234&captcha=5678` + +### [退出登录](https://neteasecloudmusicapi.vercel.app/#/?id=退出登录) + +说明 : 调用此接口 , 可退出登录 + +**调用例子 :** `/logout` + +### [登录状态](https://neteasecloudmusicapi.vercel.app/#/?id=登录状态) + +说明 : 调用此接口,可获取登录状态 + +**接口地址 :** `/login/status` + +### [获取用户详情](https://neteasecloudmusicapi.vercel.app/#/?id=获取用户详情) + +说明 : 登录后调用此接口 , 传入用户 id, 可以获取用户详情 + +**必选参数 :** `uid` : 用户 id + +**接口地址 :** `/user/detail` + +**调用例子 :** `/user/detail?uid=32953014` + +### [获取账号信息](https://neteasecloudmusicapi.vercel.app/#/?id=获取账号信息) + +说明 : 登录后调用此接口 ,可获取用户账号信息 + +**接口地址 :** `/user/account` + +**调用例子 :** `/user/account` + +### [获取用户信息 , 歌单,收藏,mv, dj 数量](https://neteasecloudmusicapi.vercel.app/#/?id=获取用户信息-歌单,收藏,mv-dj-数量) + +说明 : 登录后调用此接口 , 可以获取用户信息 + +**接口地址 :** `/user/subcount` + +**调用例子 :** `/user/subcount` + +### [获取用户等级信息](https://neteasecloudmusicapi.vercel.app/#/?id=获取用户等级信息) + +说明 : 登录后调用此接口 , 可以获取用户等级信息,包含当前登录天数,听歌次数,下一等级需要的登录天数和听歌次数,当前等级进度,对应 https://music.163.com/#/user/level + +**接口地址 :** `/user/level` + +**调用例子 :** `/user/level` + +### [获取用户绑定信息](https://neteasecloudmusicapi.vercel.app/#/?id=获取用户绑定信息) + +说明 : 登录后调用此接口 , 可以获取用户绑定信息 + +**必选参数 :** `uid` : 用户 id + +**接口地址 :** `/user/binding` + +**调用例子 :** `/user/binding?uid=32953014` + +### [用户绑定手机](https://neteasecloudmusicapi.vercel.app/#/?id=用户绑定手机) + +说明 : 登录后调用此接口 , 可以更换绑定手机 + +**必选参数 :** + +`phone` : 手机号码 + +`oldcaptcha`: 原手机号码的验证码 + +`captcha`:新手机号码的验证码 + +**可选参数 :** + +`countrycode`: 国家地区代码,默认 86 + +**接口地址 :** `/user/replacephone` + +**调用例子 :** `/user/replacephone?phone=xxx&captcha=1234&oldcaptcha=2345` + +### [更新用户信息](https://neteasecloudmusicapi.vercel.app/#/?id=更新用户信息) + +说明 : 登录后调用此接口 , 传入相关信息,可以更新用户信息 + +**必选参数 :** + +``` +gender: 性别 0:保密 1:男性 2:女性 + +birthday: 出生日期,时间戳 unix timestamp + +nickname: 用户昵称 + +province: 省份id + +city: 城市id + +signature:用户签名 +``` + +**接口地址 :** `/user/update` + +**调用例子 :** `/user/update?gender=0&signature=测试签名&city=440300&nickname=binary&birthday=1525918298004&province=440000` + +### [更新头像](https://neteasecloudmusicapi.vercel.app/#/?id=更新头像) + +说明 : 登录后调用此接口,使用`'Content-Type': 'multipart/form-data'`上传图片 formData(name 为'imgFile'),可更新头像(参考: https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/public/avatar_update.html ),支持命令行调用,参考module_example目录下`avatar_upload.js` + +**可选参数 :** + +`imgSize` : 图片尺寸,默认为 300 + +`imgX` : 水平裁剪偏移,方形图片可不传,默认为 0 `imgY` : 垂直裁剪偏移,方形图片可不传,默认为 0 + +**接口地址 :** `/avatar/upload` + +**调用例子 :** `/avatar/upload?imgSize=200` + +### [国家编码列表](https://neteasecloudmusicapi.vercel.app/#/?id=国家编码列表) + +说明 : 调用此接口,可获取国家编码列表 + +**接口地址 :** `/countries/code/list` + +### [获取用户歌单](https://neteasecloudmusicapi.vercel.app/#/?id=获取用户歌单) + +说明 : 登录后调用此接口 , 传入用户 id, 可以获取用户歌单 + +**必选参数 :** `uid` : 用户 id + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +`offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 + +**接口地址 :** `/user/playlist` + +**调用例子 :** `/user/playlist?uid=32953014` + +返回数据如下图 : ![用户歌单](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/%E7%94%A8%E6%88%B7%E6%AD%8C%E5%8D%95.png) + +### [更新歌单](https://neteasecloudmusicapi.vercel.app/#/?id=更新歌单) + +说明 : 登录后调用此接口,可以更新用户歌单 + +**必选参数 :** + +``` +id:歌单id + +name:歌单名字 + +desc:歌单描述 + +tags:歌单tag ,多个用 `;` 隔开,只能用官方规定标签 +``` + +**接口地址 :** `/playlist/update` + +**调用例子 :** `/playlist/update?id=24381616&name=新歌单&desc=描述&tags=欧美` + +### [更新歌单描述](https://neteasecloudmusicapi.vercel.app/#/?id=更新歌单描述) + +说明 : 登录后调用此接口,可以单独更新用户歌单描述 + +**必选参数 :** + +``` +id:歌单id + +desc:歌单描述 +``` + +**接口地址 :** `/playlist/desc/update` + +**调用例子 :** `/playlist/desc/update?id=24381616&desc=描述` + +### [更新歌单名](https://neteasecloudmusicapi.vercel.app/#/?id=更新歌单名) + +说明 : 登录后调用此接口,可以单独更新用户歌单名 + +**必选参数 :** + +``` +id: 歌单id + +name: 歌单名 +``` + +**接口地址 :** `/playlist/name/update` + +**调用例子 :** `/playlist/name/update?id=24381616&name=歌单名` + +### [更新歌单标签](https://neteasecloudmusicapi.vercel.app/#/?id=更新歌单标签) + +说明 : 登录后调用此接口,可以单独更新用户歌单标签 + +**必选参数 :** + +``` +id: 歌单id + +tags: 歌单标签 +``` + +**接口地址 :** `/playlist/tags/update` + +**调用例子 :** `/playlist/tags/update?id=24381616&tags=学习` + +### [歌单封面上传](https://neteasecloudmusicapi.vercel.app/#/?id=歌单封面上传) + +说明 : 登录后调用此接口,使用`'Content-Type': 'multipart/form-data'`上传图片 formData(name 为'imgFile'),可更新歌单封面(参考:https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/public/playlist_cover_update.html) + +**必选参数 :** +`id`: 歌单 id 3143833470 + +**可选参数 :** + +`imgSize` : 图片尺寸,默认为 300 + +`imgX` : 水平裁剪偏移,方形图片可不传,默认为 0 `imgY` : 垂直裁剪偏移,方形图片可不传,默认为 0 + +**接口地址 :** `/playlist/cover/update` + +**调用例子 :** `/playlist/cover/update?id=3143833470&imgSize=200` + +### [调整歌单顺序](https://neteasecloudmusicapi.vercel.app/#/?id=调整歌单顺序) + +说明 : 登录后调用此接口,可以根据歌单 id 顺序调整歌单顺序 + +**必选参数 :** + +`ids`: 歌单 id 列表 + +**接口地址 :** `/playlist/order/update` + +**调用例子 :** `/playlist/order/update?ids=[111,222]` + +### [调整歌曲顺序](https://neteasecloudmusicapi.vercel.app/#/?id=调整歌曲顺序) + +说明 : 登录后调用此接口,可以根据歌曲 id 顺序调整歌曲顺序 + +**必选参数 :** +`pid`: 歌单 id + +`ids`: 歌曲 id 列表 + +**接口地址 :** `/song/order/update` + +**调用例子 :** `/song/order/update?pid=2039116066&ids=[5268328,1219871]` + +### [获取用户历史评论](https://neteasecloudmusicapi.vercel.app/#/?id=获取用户历史评论) + +说明 : 登录后调用此接口 , 传入用户 id, 可以获取用户历史评论 + +**必选参数 :** `uid` : 用户 id + +**可选参数 :** + +`limit` : 返回数量 , 默认为 10 + +`time`: 上一条数据的 time,第一页不需要传,默认为 0 + +**接口地址 :** `/user/comment/history` + +**调用例子 :** `/user/comment/history?uid=32953014` `/user/comment/history?uid=32953014&limit=1&time=1616217577564` (需要换成自己的用户 id) + +### [获取用户电台](https://neteasecloudmusicapi.vercel.app/#/?id=获取用户电台) + +说明 : 登录后调用此接口 , 传入用户 id, 可以获取用户电台 + +**必选参数 :** `uid` : 用户 id + +**接口地址 :** `/user/dj` + +**调用例子 :** `/user/dj?uid=32953014` + +### [获取用户关注列表](https://neteasecloudmusicapi.vercel.app/#/?id=获取用户关注列表) + +说明 : 登录后调用此接口 , 传入用户 id, 可以获取用户关注列表 + +**必选参数 :** `uid` : 用户 id + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +`offset` : 偏移数量,用于分页 ,如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 + +**接口地址 :** `/user/follows` + +**调用例子 :** `/user/follows?uid=32953014` + +### [获取用户粉丝列表](https://neteasecloudmusicapi.vercel.app/#/?id=获取用户粉丝列表) + +说明 : 登录后调用此接口 , 传入用户 id, 可以获取用户粉丝列表 + +**必选参数 :** `uid` : 用户 id + +**可选参数 :** `limit` : 返回数量 , 默认为 30 + +`offset` : 偏移数量,用于分页 ,如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 + +**接口地址 :** `/user/followeds` + +**调用例子 :** `/user/followeds?uid=32953014` `/user/followeds?uid=416608258&limit=1` `/user/followeds?uid=416608258&limit=1&offset=1` + +### [获取用户动态](https://neteasecloudmusicapi.vercel.app/#/?id=获取用户动态) + +说明 : 登录后调用此接口 , 传入用户 id, 可以获取用户动态 + +**必选参数 :** `uid` : 用户 id + +**可选参数 :** `limit` : 返回数量 , 默认为 30 + +`lasttime` : 返回数据的 `lasttime` ,默认-1,传入上一次返回结果的 lasttime,将会返回下一页的数据 + +**接口地址 :** `/user/event` + +**调用例子 :** `/user/event?uid=32953014` `/user/event?uid=32953014&limit=1&lasttime=1558011138743` + +返回结果的`type`参数对应: + +``` +18 分享单曲 +19 分享专辑 +17、28 分享电台节目 +22 转发 +39 发布视频 +35、13 分享歌单 +24 分享专栏文章 +41、21 分享视频 +``` + +### [转发用户动态](https://neteasecloudmusicapi.vercel.app/#/?id=转发用户动态) + +说明 : 登录后调用此接口 ,可以转发用户动态 + +**必选参数 :** `uid` : 用户 id + +`evId` : 动态 id + +`forwards` : 转发的评论 + +**接口地址 :** `/event/forward` + +**调用例子 :** `/event/forward?evId=6712917601&uid=32953014&forwards=测试内容` + +### [删除用户动态](https://neteasecloudmusicapi.vercel.app/#/?id=删除用户动态) + +说明 : 登录后调用此接口 ,可以删除用户动态 + +**必选参数 :** `evId` : 动态 id + +**接口地址 :** `/event/del` + +**调用例子 :** `/event/del?evId=6712917601` + +### [分享文本、歌曲、歌单、mv、电台、电台节目到动态](https://neteasecloudmusicapi.vercel.app/#/?id=分享文本、歌曲、歌单、mv、电台、电台节目到动态) + +说明 : 登录后调用此接口 ,可以分享文本、歌曲、歌单、mv、电台、电台节目到动态 + +**必选参数 :** `id` : 资源 id (歌曲,歌单,mv,电台,电台节目对应 id) + +**可选参数 :** `type`: 资源类型,默认歌曲 song,可传 `song`,`playlist`,`mv`,`djradio`,`djprogram` + +`msg`: 内容,140 字限制,支持 emoji,@用户名(`/user/follows`接口获取的用户名,用户名后和内容应该有空格),图片暂不支持 + +**接口地址 :** `/share/resource` + +**调用例子 :** `/share/resource?id=1297494209&msg=测试` `/share/resource?type=djradio&id=336355127` `/share/resource?type=djprogram&id=2061034798` `/share/resource?type=djprogram&id=2061034798&msg=测试@binaryify 测试` `/share/resource?type=noresource&msg=测试` + +### [获取动态评论](https://neteasecloudmusicapi.vercel.app/#/?id=获取动态评论) + +说明 : 登录后调用此接口 , 可以获取动态下评论 + +**必选参数 :** `threadId` : 动态 id,可通过 `/event`,`/user/event` 接口获取 + +**接口地址 :** `/comment/event` + +**调用例子 :** `/comment/event?threadId=A_EV_2_6559519868_32953014` + +### [关注/取消关注用户](https://neteasecloudmusicapi.vercel.app/#/?id=关注取消关注用户) + +说明 : 登录后调用此接口 , 传入用户 id, 和操作 t,可关注/取消关注用户 + +**必选参数 :** + +`id` : 用户 id + +`t` : `1`为关注,其他为取消关注 + +**接口地址 :** `/follow` + +**调用例子 :** `/follow?id=32953014&t=1` + +### [获取用户播放记录](https://neteasecloudmusicapi.vercel.app/#/?id=获取用户播放记录) + +说明 : 登录后调用此接口 , 传入用户 id, 可获取用户播放记录 + +**必选参数 :** `uid` : 用户 id + +**可选参数 :** `type` : type=1 时只返回 weekData, type=0 时返回 allData + +**接口地址 :** `/user/record` + +**调用例子 :** `/user/record?uid=32953014&type=1` + +### [获取热门话题](https://neteasecloudmusicapi.vercel.app/#/?id=获取热门话题) + +说明 : 调用此接口 , 可获取热门话题 + +**可选参数 :** `limit`: 取出评论数量 , 默认为 20 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*20, 其中 20 为 limit 的值 + +**接口地址 :** `/hot/topic` + +**调用例子 :** `/hot/topic?limit=30&offset=30` + +### [获取话题详情](https://neteasecloudmusicapi.vercel.app/#/?id=获取话题详情) + +说明 : 调用此接口 , 可获取话题详情 + +**接口地址 :** `/topic/detail` + +**调用例子 :** `/topic/detail?actid=111551188` + +### [获取话题详情热门动态](https://neteasecloudmusicapi.vercel.app/#/?id=获取话题详情热门动态) + +说明 : 调用此接口 , 可获取话题详情热门动态 + +**接口地址 :** `/topic/detail/event/hot` + +**调用例子 :** `/topic/detail/event/hot?actid=111551188` + +### [云村热评(官方下架,暂不能用)](https://neteasecloudmusicapi.vercel.app/#/?id=云村热评官方下架暂不能用) + +说明 : 登录后调用此接口 , 可获取云村热评 + +**接口地址 :** `/comment/hotwall/list` + +**调用例子 :** `/comment/hotwall/list` + +### [心动模式/智能播放](https://neteasecloudmusicapi.vercel.app/#/?id=心动模式智能播放) + +说明 : 登录后调用此接口 , 可获取心动模式/智能播放列表 **必选参数 :** `id` : 歌曲 id + +`pid` : 歌单 id + +**可选参数 :** `sid` : 要开始播放的歌曲的 id + +**接口地址 :** `/playmode/intelligence/list` + +**调用例子 :** `/playmode/intelligence/list?id=33894312&pid=24381616` , `/playmode/intelligence/list?id=33894312&pid=24381616&sid=36871368` + +### [获取动态消息](https://neteasecloudmusicapi.vercel.app/#/?id=获取动态消息) + +说明 : 调用此接口 , 可获取各种动态 , 对应网页版网易云,朋友界面里的各种动态消息 ,如分享的视频,音乐,照片等! + +**必选参数 :** `pagesize` : 每页数据,默认 20 + +`lasttime` : 返回数据的 `lasttime` ,默认-1,传入上一次返回结果的 lasttime,将会返回下一页的数据 + +**接口地址 :** `/event` + +**调用例子 :** `/event?pagesize=30&lasttime=1556740526369` + +### [歌手分类列表](https://neteasecloudmusicapi.vercel.app/#/?id=歌手分类列表) + +说明 : 调用此接口,可获取歌手分类列表 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +`offset` : 偏移数量,用于分页 , 如 : 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 `initial`: 按首字母索引查找参数,如 `/artist/list?type=1&area=96&initial=b` 返回内容将以 name 字段开头为 b 或者拼音开头为 b 为顺序排列, 热门传-1,#传 0 + +`type` 取值: + +``` +-1:全部 +1:男歌手 +2:女歌手 +3:乐队 +``` + +`area` 取值: + +``` +-1:全部 +7华语 +96欧美 +8:日本 +16韩国 +0:其他 +``` + +**接口地址 :** `/artist/list` + +**调用例子 :** `/artist/list?type=1&area=96&initial=b` `/artist/list?type=2&area=2&initial=b` + +### [收藏/取消收藏歌手](https://neteasecloudmusicapi.vercel.app/#/?id=收藏取消收藏歌手) + +说明 : 调用此接口,可收藏歌手 + +**必选参数 :** + +`id` : 歌手 id + +`t`:操作,1 为收藏,其他为取消收藏 + +**接口地址 :** `/artist/sub` + +**调用例子 :** `/artist/sub?id=6452&t=1` + +### [歌手热门 50 首歌曲](https://neteasecloudmusicapi.vercel.app/#/?id=歌手热门-50-首歌曲) + +说明 : 调用此接口,可获取歌手热门 50 首歌曲 + +**必选参数 :** + +`id` : 歌手 id + +**接口地址 :** `/artist/top/song` + +**调用例子 :** `/artist/top/song?id=6452` + +### [歌手全部歌曲](https://neteasecloudmusicapi.vercel.app/#/?id=歌手全部歌曲) + +说明 : 调用此接口,可获取歌手全部歌曲 **必选参数 :** + +`id` : 歌手 id + +**可选参数 :** + +`order` : `hot` ,`time` 按照热门或者时间排序 + +`limit`: 取出歌单数量 , 默认为 50 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*50, 其中 50 为 limit 的值 + +**接口地址 :** `/artist/songs` + +**调用例子 :** `/artist/songs?id=6452` + +### [收藏的歌手列表](https://neteasecloudmusicapi.vercel.app/#/?id=收藏的歌手列表) + +说明 : 调用此接口,可获取收藏的歌手列表 + +**接口地址 :** `/artist/sublist` + +**调用例子 :** `/artist/sublist` + +### [收藏的专栏](https://neteasecloudmusicapi.vercel.app/#/?id=收藏的专栏) + +说明 : 调用此接口,可获取收藏的专栏 + +**可选参数 :** + +`limit`: 取出歌单数量 , 默认为 50 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*50, 其中 50 为 limit 的值 + +**接口地址 :** `/topic/sublist` + +**调用例子 :** `/topic/sublist?limit=2&offset=1` + +### [收藏视频](https://neteasecloudmusicapi.vercel.app/#/?id=收藏视频) + +说明 : 调用此接口,可收藏视频 + +**必选参数 :** + +`id` : 视频 id + +`t` : 1 为收藏,其他为取消收藏 + +**接口地址 :** `/video/sub` + +**调用例子 :** `/video/sub` + +### [收藏/取消收藏 MV](https://neteasecloudmusicapi.vercel.app/#/?id=收藏取消收藏-mv) + +说明 : 调用此接口,可收藏/取消收藏 MV + +**必选参数 :** + +`mvid` : MV id + +`t` : 1 为收藏,其他为取消收藏 + +**接口地址 :** `/mv/sub` + +**调用例子 :** `/mv/sub` + +### [收藏的 MV 列表](https://neteasecloudmusicapi.vercel.app/#/?id=收藏的-mv-列表) + +说明 : 调用此接口,可获取收藏的 MV 列表 + +**接口地址 :** `/mv/sublist` + +**调用例子 :** `/mv/sublist` + +### [歌单分类](https://neteasecloudmusicapi.vercel.app/#/?id=歌单分类) + +说明 : 调用此接口,可获取歌单分类,包含 category 信息 + +**接口地址 :** `/playlist/catlist` + +**调用例子 :** `/playlist/catlist` + +### [热门歌单分类](https://neteasecloudmusicapi.vercel.app/#/?id=热门歌单分类) + +说明 : 调用此接口,可获取歌单分类,包含 category 信息 + +**接口地址 :** `/playlist/hot` + +**调用例子 :** `/playlist/hot` + +### [歌单 ( 网友精选碟 )](https://neteasecloudmusicapi.vercel.app/#/?id=歌单-网友精选碟-) + +说明 : 调用此接口 , 可获取网友精选碟歌单 + +**可选参数 :** `order`: 可选值为 'new' 和 'hot', 分别对应最新和最热 , 默认为 'hot' + +`cat`: tag, 比如 " 华语 "、" 古风 " 、" 欧美 "、" 流行 ", 默认为 "全部",可从歌单分类接口获取(/playlist/catlist) + +`limit`: 取出歌单数量 , 默认为 50 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*50, 其中 50 为 limit 的值 + +**接口地址 :** `/top/playlist` + +**调用例子 :** `/top/playlist?limit=10&order=new` + +### [精品歌单标签列表](https://neteasecloudmusicapi.vercel.app/#/?id=精品歌单标签列表) + +说明 : 调用此接口 , 可获取精品歌单标签列表 + +**接口地址 :** `/playlist/highquality/tags` + +**调用例子 :** `/playlist/highquality/tags` + +### [获取精品歌单](https://neteasecloudmusicapi.vercel.app/#/?id=获取精品歌单) + +说明 : 调用此接口 , 可获取精品歌单 + +**可选参数 :** `cat`: tag, 比如 " 华语 "、" 古风 " 、" 欧美 "、" 流行 ", 默认为 "全部",可从精品歌单标签列表接口获取(`/playlist/highquality/tags`) + +`limit`: 取出歌单数量 , 默认为 20 + +`before`: 分页参数,取上一页最后一个歌单的 `updateTime` 获取下一页数据 + +**接口地址 :** `/top/playlist/highquality` + +**调用例子 :** `/top/playlist/highquality?before=1503639064232&limit=3` + +### [相关歌单推荐](https://neteasecloudmusicapi.vercel.app/#/?id=相关歌单推荐) + +说明 : 调用此接口,传入歌单 id 可获取相关歌单(对应页面 https://music.163.com/#/playlist?id=1) + +**必选参数 :** `id` : 歌单 id + +**接口地址 :** `/related/playlist` + +**调用例子 :** `/related/playlist?id=1` + +### [获取歌单详情](https://neteasecloudmusicapi.vercel.app/#/?id=获取歌单详情) + +说明 : 歌单能看到歌单名字, 但看不到具体歌单内容 , 调用此接口 , 传入歌单 id, 可 以获取对应歌单内的所有的音乐(未登录状态只能获取不完整的歌单,登录后是完整的),但是返回的 trackIds 是完整的,tracks 则是不完整的,可拿全部 trackIds 请求一次 `song/detail` 接口获取所有歌曲的详情 (https://github.com/Binaryify/NeteaseCloudMusicApi/issues/452) + +**必选参数 :** `id` : 歌单 id + +**可选参数 :** `s` : 歌单最近的 s 个收藏者,默认为 8 + +**接口地址 :** `/playlist/detail` + +**调用例子 :** `/playlist/detail?id=24381616` + +### [获取歌单所有歌曲](https://neteasecloudmusicapi.vercel.app/#/?id=获取歌单所有歌曲) + +说明 : 由于网易云接口限制,歌单详情只会提供 10 首歌,通过调用此接口,传入对应的歌单`id`,即可获得对应的所有歌曲 + +**必选参数 :** `id` : 歌单 id + +**可选参数 :** `limit` : 限制获取歌曲的数量,默认值为当前歌单的歌曲数量 + +**可选参数 :** `offset` : 默认值为0 + +**接口地址 :** `/playlist/track/all` + +**调用例子 :** `/playlist/track/all?id=24381616&limit=10&offset=1` + +> 注:关于`offset`,你可以这样理解,假设你当前的歌单有100首歌 +> +> 你传入limit=10&offset=0等价于limit=10,你会得到第1-10首歌曲 +> +> 你传入limit=10&offset=1,你会得到第2-11首歌曲 +> +> 如果你设置limit=10&offset=2,你就会得到第3-12首歌曲 + +### [歌单详情动态](https://neteasecloudmusicapi.vercel.app/#/?id=歌单详情动态) + +说明 : 调用后可获取歌单详情动态部分,如评论数,是否收藏,播放数 + +**必选参数 :** `id` : 歌单 id + +**接口地址 :** `/playlist/detail/dynamic` + +**调用例子 :** `/playlist/detail/dynamic?id=24381616` + +### [歌单更新播放量](https://neteasecloudmusicapi.vercel.app/#/?id=歌单更新播放量) + +说明 : 调用后可更新歌单播放量 + +**必选参数 :** `id` : 歌单 id + +**接口地址 :** `/playlist/update/playcount` + +**调用例子 :** `/playlist/update/playcount?id=24381616` + +### [获取音乐 url](https://neteasecloudmusicapi.vercel.app/#/?id=获取音乐-url) + +说明 : 使用歌单详情接口后 , 能得到的音乐的 id, 但不能得到的音乐 url, 调用此接口, 传入的音乐 id( 可多个 , 用逗号隔开 ), 可以获取对应的音乐的 url,未登录状态或者非会员返回试听片段(返回字段包含被截取的正常歌曲的开始时间和结束时间) + +> 注 : 部分用户反馈获取的 url 会 403,[hwaphon](https://github.com/hwaphon)找到的解决方案是当获取到音乐的 id 后,将 https://music.163.com/song/media/outer/url?id=id.mp3 以 src 赋予 Audio 即可播放 + +**必选参数 :** `id` : 音乐 id + +**可选参数 :** `br`: 码率,默认设置了 999000 即最大码率,如果要 320k 则可设置为 320000,其他类推 + +**接口地址 :** `/song/url` + +**调用例子 :** `/song/url?id=33894312` `/song/url?id=405998841,33894312` + +### [音乐是否可用](https://neteasecloudmusicapi.vercel.app/#/?id=音乐是否可用) + +说明: 调用此接口,传入歌曲 id, 可获取音乐是否可用,返回 `{ success: true, message: 'ok' }` 或者 `{ success: false, message: '亲爱的,暂无版权' }` + +**必选参数 :** `id` : 歌曲 id + +**可选参数** : `br`: 码率,默认设置了 999000 即最大码率,如果要 320k 则可设置为 320000,其他类推 + +**接口地址 :** `/check/music` + +**调用例子 :** `/check/music?id=33894312` + +### [搜索](https://neteasecloudmusicapi.vercel.app/#/?id=搜索) + +说明 : 调用此接口 , 传入搜索关键词可以搜索该音乐 / 专辑 / 歌手 / 歌单 / 用户 , 关键词可以多个 , 以空格隔开 , 如 " 周杰伦 搁浅 "( 不需要登录 ), 可通过 `/song/url` 接口传入歌曲 id 获取具体的播放链接 + +**必选参数 :** `keywords` : 关键词 + +**可选参数 :** `limit` : 返回数量 , 默认为 30 `offset` : 偏移数量,用于分页 , 如 : 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 + +`type`: 搜索类型;默认为 1 即单曲 , 取值意义 : 1: 单曲, 10: 专辑, 100: 歌手, 1000: 歌单, 1002: 用户, 1004: MV, 1006: 歌词, 1009: 电台, 1014: 视频, 1018:综合, 2000:声音(搜索声音返回字段格式会不一样) + +**接口地址 :** `/search` 或者 `/cloudsearch`(更全) + +**调用例子 :** `/search?keywords=海阔天空` `/cloudsearch?keywords=海阔天空` + +### [默认搜索关键词](https://neteasecloudmusicapi.vercel.app/#/?id=默认搜索关键词) + +说明 : 调用此接口 , 可获取默认搜索关键词 + +**接口地址 :** `/search/default` + +### [热搜列表(简略)](https://neteasecloudmusicapi.vercel.app/#/?id=热搜列表简略) + +说明 : 调用此接口,可获取热门搜索列表 + +**接口地址 :** `/search/hot` + +**调用例子 :** `/search/hot` + +### [热搜列表(详细)](https://neteasecloudmusicapi.vercel.app/#/?id=热搜列表详细) + +说明 : 调用此接口,可获取热门搜索列表 + +**接口地址 :** `/search/hot/detail` + +**调用例子 :** `/search/hot/detail` + +### [搜索建议](https://neteasecloudmusicapi.vercel.app/#/?id=搜索建议) + +说明 : 调用此接口 , 传入搜索关键词可获得搜索建议 , 搜索结果同时包含单曲 , 歌手 , 歌单信息 + +**必选参数 :** `keywords` : 关键词 + +**可选参数 :** `type` : 如果传 'mobile' 则返回移动端数据 + +**接口地址 :** `/search/suggest` + +**调用例子 :** `/search/suggest?keywords=海阔天空` `/search/suggest?keywords=海阔天空&type=mobile` + +### [搜索多重匹配](https://neteasecloudmusicapi.vercel.app/#/?id=搜索多重匹配) + +说明 : 调用此接口 , 传入搜索关键词可获得搜索结果 + +**必选参数 :** `keywords` : 关键词 + +**接口地址 :** `/search/multimatch` + +**调用例子 :** `/search/multimatch?keywords=海阔天空` + +### [新建歌单](https://neteasecloudmusicapi.vercel.app/#/?id=新建歌单) + +说明 : 调用此接口 , 传入歌单名字可新建歌单 + +**必选参数 :** `name` : 歌单名 + +**可选参数 :** + +`privacy` : 是否设置为隐私歌单,默认否,传'10'则设置成隐私歌单 + +`type` : 歌单类型,默认'NORMAL',传 'VIDEO'则为视频歌单,传 'SHARED'则为共享歌单 + +**接口地址 :** `/playlist/create` + +**调用例子 :** `/playlist/create?name=测试歌单`,`/playlist/create?name=test&type=VIDEO` + +### [删除歌单](https://neteasecloudmusicapi.vercel.app/#/?id=删除歌单) + +说明 : 调用此接口 , 传入歌单 id 可删除歌单 + +**必选参数 :** `id` : 歌单 id,可多个,用逗号隔开 + +**接口地址 :** `/playlist/delete` + +**调用例子 :** `/playlist/delete?id=2947311456` , `/playlist/delete?id=5013464397,5013427772` + +### [收藏/取消收藏歌单](https://neteasecloudmusicapi.vercel.app/#/?id=收藏取消收藏歌单) + +说明 : 调用此接口 , 传入类型和歌单 id 可收藏歌单或者取消收藏歌单 + +**必选参数 :** + +`t` : 类型,1:收藏,2:取消收藏 `id` : 歌单 id + +**接口地址 :** `/playlist/subscribe` + +**调用例子 :** `/playlist/subscribe?t=1&id=106697785` `/playlist/subscribe?t=2&id=106697785` + +### [歌单收藏者](https://neteasecloudmusicapi.vercel.app/#/?id=歌单收藏者) + +说明 : 调用此接口 , 传入歌单 id 可获取歌单的所有收藏者 +**必选参数 :** + +`id` : 歌单 id + +**可选参数 :** `limit`: 取出评论数量 , 默认为 20 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*20, 其中 20 为 limit 的值 + +**接口地址 :** `/playlist/subscribers` + +**调用例子 :** `/playlist/subscribers?id=544215255&limit=30` + +### [对歌单添加或删除歌曲](https://neteasecloudmusicapi.vercel.app/#/?id=对歌单添加或删除歌曲) + +说明 : 调用此接口 , 可以添加歌曲到歌单或者从歌单删除某首歌曲 ( 需要登录 ) + +**必选参数 :** + +`op`: 从歌单增加单曲为 add, 删除为 del + +`pid`: 歌单 id `tracks`: 歌曲 id,可多个,用逗号隔开 + +**接口地址 :** `/playlist/tracks` + +**调用例子 :** `/playlist/tracks?op=add&pid=24381616&tracks=347231` ( 对应把歌曲添加到 ' 我 ' 的歌单 , 测试的时候请把这里的 pid 换成你自己的, id 和 tracks 不对可能会报 502 错误) + +### [收藏视频到视频歌单](https://neteasecloudmusicapi.vercel.app/#/?id=收藏视频到视频歌单) + +说明 : 调用此接口 , 可收藏视频到视频歌单 ( 需要登录 ) + +**必选参数 :** + +`pid` : 歌单 id + +`ids` : 视频 id,支持多个,用`,`隔开 + +**接口地址 :** `/playlist/track/add` + +**调用例子 :** `/playlist/track/add?pid=5271999357&ids=186041` + +### [删除视频歌单里的视频](https://neteasecloudmusicapi.vercel.app/#/?id=删除视频歌单里的视频) + +说明 : 调用此接口 , 可删除视频歌单里的视频 ( 需要登录 ) **必选参数 :** + +`pid` : 歌单 id + +`ids` : 视频 id,支持多个,用`,`隔开 + +**接口地址 :** `/playlist/track/delete` + +**调用例子 :** `/playlist/track/delete?pid=5271999357&ids=186041` + +### [最近播放的视频](https://neteasecloudmusicapi.vercel.app/#/?id=最近播放的视频) + +说明 : 调用此接口 , 可获取最近播放的视频 ( 需要登录 ) + +**接口地址 :** `/playlist/video/recent` + +**调用例子 :** `/playlist/video/recent` + +### [获取歌词](https://neteasecloudmusicapi.vercel.app/#/?id=获取歌词) + +说明 : 调用此接口 , 传入音乐 id 可获得对应音乐的歌词 ( 不需要登录 ) + +**必选参数 :** `id`: 音乐 id + +**接口地址 :** `/lyric` + +**调用例子 :** `/lyric?id=33894312` + +返回数据如下图 : ![获取歌词](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/%E6%AD%8C%E8%AF%8D.png) + +### [新歌速递](https://neteasecloudmusicapi.vercel.app/#/?id=新歌速递) + +说明 : 调用此接口 , 可获取新歌速递 + +**必选参数 :** + +`type`: 地区类型 id,对应以下: + +``` +全部:0 + +华语:7 + +欧美:96 + +日本:8 + +韩国:16 +``` + +**接口地址 :** `/top/song` + +**调用例子 :** `/top/song?type=96` + +### [首页-发现](https://neteasecloudmusicapi.vercel.app/#/?id=首页-发现) + +说明 : 调用此接口 , 可获取 APP 首页信息 + +**接口地址 :** `/homepage/block/page` + +**可选参数 :** `refresh`: 是否刷新数据,默认为 false + +`cursor`: 上一条数据返回的 cursor + +### [首页-发现-圆形图标入口列表](https://neteasecloudmusicapi.vercel.app/#/?id=首页-发现-圆形图标入口列表) + +说明 : 调用此接口 , 可获取 APP 首页圆形图标入口列表 + +**接口地址 :** `/homepage/dragon/ball` + +### [歌曲评论](https://neteasecloudmusicapi.vercel.app/#/?id=歌曲评论) + +说明 : 调用此接口 , 传入音乐 id 和 limit 参数 , 可获得该音乐的所有评论 ( 不需要登录 ) + +**必选参数 :** `id`: 音乐 id + +**可选参数 :** `limit`: 取出评论数量 , 默认为 20 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*20, 其中 20 为 limit 的值 + +`before`: 分页参数,取上一页最后一项的 `time` 获取下一页数据(获取超过 5000 条评论的时候需要用到) + +**接口地址 :** `/comment/music` + +**调用例子 :** `/comment/music?id=186016&limit=1` 对应晴天评论 + +返回数据如下图 : ![获取评论](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/comment.png) + +### [楼层评论](https://neteasecloudmusicapi.vercel.app/#/?id=楼层评论) + +说明 : 调用此接口 , 传入资源 parentCommentId 和资源类型 type 和资源 id 参数, 可获得该资源的歌曲楼层评论 + +**必选参数 :** +`parentCommentId`: 楼层评论 id + +`id` : 资源 id + +`type`: 数字 , 资源类型 , 对应歌曲 , mv, 专辑 , 歌单 , 电台, 视频对应以下类型 + +``` +0: 歌曲 + +1: mv + +2: 歌单 + +3: 专辑 + +4: 电台 + +5: 视频 +``` + +**可选参数 :** `limit`: 取出评论数量 , 默认为 20 + +`time`: 分页参数,取上一页最后一项的 `time` 获取下一页数据 + +**接口地址 :** `/comment/floor` + +**调用例子 :** `/comment/floor?parentCommentId=1438569889&id=29764564&type=0` + +### [专辑评论](https://neteasecloudmusicapi.vercel.app/#/?id=专辑评论) + +说明 : 调用此接口 , 传入音乐 id 和 limit 参数 , 可获得该专辑的所有评论 ( 不需要 登录 ) + +**必选参数 :** `id`: 专辑 id + +**可选参数 :** `limit`: 取出评论数量 , 默认为 20 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*20, 其中 20 为 limit 的值 + +`before`: 分页参数,取上一页最后一项的 `time` 获取下一页数据(获取超过 5000 条评论的时候需要用到) + +**接口地址 :** `/comment/album` + +**调用例子 :** `/comment/album?id=32311` + +### [歌单评论](https://neteasecloudmusicapi.vercel.app/#/?id=歌单评论) + +说明 : 调用此接口 , 传入音乐 id 和 limit 参数 , 可获得该歌单的所有评论 ( 不需要 登录 ) + +**必选参数 :** `id`: 歌单 id + +**可选参数 :** `limit`: 取出评论数量 , 默认为 20 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*20, 其中 20 为 limit 的值 + +`before`: 分页参数,取上一页最后一项的 `time` 获取下一页数据(获取超过 5000 条评论的时候需要用到) + +**接口地址 :** `/comment/playlist` + +**调用例子 :** `/comment/playlist?id=705123491` + +### [mv 评论](https://neteasecloudmusicapi.vercel.app/#/?id=mv-评论) + +说明 : 调用此接口 , 传入音乐 id 和 limit 参数 , 可获得该 mv 的所有评论 ( 不需要 登录 ) + +**必选参数 :** `id`: mv id + +**可选参数 :** `limit`: 取出评论数量 , 默认为 20 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*20, 其中 20 为 limit 的值 + +`before`: 分页参数,取上一页最后一项的 `time` 获取下一页数据(获取超过 5000 条评论的时候需要用到) + +**接口地址 :** `/comment/mv` + +**调用例子 :** `/comment/mv?id=5436712` + +### [电台节目评论](https://neteasecloudmusicapi.vercel.app/#/?id=电台节目评论) + +说明 : 调用此接口 , 传入音乐 id 和 limit 参数 , 可获得该 电台节目 的所有评论 ( 不需要登录 ) + +**必选参数 :** `id`: 电台节目的 id + +**可选参数 :** `limit`: 取出评论数量 , 默认为 20 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*20, 其中 20 为 limit 的值 + +`before`: 分页参数,取上一页最后一项的 `time` 获取下一页数据(获取超过 5000 条评论的时候需要用到) + +**接口地址 :** `/comment/dj` + +**调用例子 :** `/comment/dj?id=794062371` + +### [视频评论](https://neteasecloudmusicapi.vercel.app/#/?id=视频评论) + +说明 : 调用此接口 , 传入音乐 id 和 limit 参数 , 可获得该 视频 的所有评论 ( 不需要登录 ) + +**必选参数 :** `id`: 视频的 id + +**可选参数 :** `limit`: 取出评论数量 , 默认为 20 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*20, 其中 20 为 limit 的值 + +`before`: 分页参数,取上一页最后一项的 `time` 获取下一页数据(获取超过 5000 条评论的时候需要用到) + +**接口地址 :** `/comment/video` + +**调用例子 :** `/comment/video?id=89ADDE33C0AAE8EC14B99F6750DB954D` + +### [热门评论](https://neteasecloudmusicapi.vercel.app/#/?id=热门评论) + +说明 : 调用此接口 , 传入 type, 资源 id 可获得对应资源热门评论 ( 不需要登录 ) + +**必选参数 :** + +`id` : 资源 id + +`type`: 数字 , 资源类型 , 对应歌曲 , mv, 专辑 , 歌单 , 电台, 视频对应以下类型 + +``` +0: 歌曲 + +1: mv + +2: 歌单 + +3: 专辑 + +4: 电台 + +5: 视频 +``` + +**可选参数 :** `limit`: 取出评论数量 , 默认为 20 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*20, 其中 20 为 limit 的值 + +`before`: 分页参数,取上一页最后一项的 `time` 获取下一页数据(获取超过 5000 条评论的时候需要用到) + +**接口地址 :** `/comment/hot` + +**调用例子 :** `/comment/hot?id=186016&type=0` + +### [新版评论接口](https://neteasecloudmusicapi.vercel.app/#/?id=新版评论接口) + +说明 : 调用此接口 , 传入资源类型和资源 id,以及排序方式,可获取对应资源的评论 + +**必选参数 :** +`id` : 资源 id, 如歌曲 id,mv id + +`type`: 数字 , 资源类型 , 对应歌曲 , mv, 专辑 , 歌单 , 电台, 视频对应以下类型 + +``` +0: 歌曲 + +1: mv + +2: 歌单 + +3: 专辑 + +4: 电台 + +5: 视频 + +6: 动态 +``` + +**可选参数 :** +`pageNo`:分页参数,第 N 页,默认为 1 + +`pageSize`:分页参数,每页多少条数据,默认 20 + +`sortType`: 排序方式, 1:按推荐排序, 2:按热度排序, 3:按时间排序 + +`cursor`: 当`sortType`为 3 时且页数不是第一页时需传入,值为上一条数据的 time + +**接口地址 :** `/comment/new` + +**调用例子 :** `/comment/new?type=0&id=1407551413&sortType=3`, `/comment/new?type=0&id=1407551413&sortType=3&cursor=1602072870260&pageSize=20&pageNo=2` + +### [给评论点赞](https://neteasecloudmusicapi.vercel.app/#/?id=给评论点赞) + +说明 : 调用此接口 , 传入 type, 资源 id, 和评论 id cid 和 是否点赞参数 t 即可给对 应评论点赞 ( 需要登录 ) + +**必选参数 :** `id` : 资源 id, 如歌曲 id,mv id + +`cid` : 评论 id + +`t` : 是否点赞 , 1 为点赞 ,0 为取消点赞 + +`type`: 数字 , 资源类型 , 对应歌曲 , mv, 专辑 , 歌单 , 电台, 视频对应以下类型 + +``` +0: 歌曲 + +1: mv + +2: 歌单 + +3: 专辑 + +4: 电台 + +5: 视频 + +6: 动态 +``` + +**接口地址 :** `/comment/like` + +**调用例子 :** `/comment/like?id=29178366&cid=12840183&t=1&type=0` 对应给 https://music.163.com/#/song?id=29178366 最热门的评论点赞 + +注意: 动态点赞不需要传入 id 参数,需要传入动态的 `threadId` 参数,如:`/comment/like?type=6&cid=1419532712&threadId=A_EV_2_6559519868_32953014&t=0`, `threadId` 可通过 `/event`,`/user/event` 接口获取 + +### [抱一抱评论](https://neteasecloudmusicapi.vercel.app/#/?id=抱一抱评论) + +说明 : 调用此接口,可抱一抱评论 + +**必选参数 :** + +`uid`: 用户 id + +`cid`: 评论 id + +`sid`: 资源 id + +**接口地址 :** `/hug/comment` + +**调用例子 :** `/hug/comment?uid=285516405&cid=1167145843&sid=863481066` + +### [评论抱一抱列表](https://neteasecloudmusicapi.vercel.app/#/?id=评论抱一抱列表) + +说明 : 调用此接口,可获取评论抱一抱列表 + +**必选参数 :** + +`uid`: 用户 id + +`cid`: 评论 id + +`sid`: 资源 id + +**可选参数 :** + +`page`: 页数 + +`cursor`: 上一页返回的 cursor,默认-1,第一页不需要传 + +`idCursor`: 上一页返回的 idCursor,默认-1,第一页不需要传 + +`pageSize` : 每页页数,默认 100 + +**接口地址 :** `/comment/hug/list` + +**调用例子 :** `/comment/hug/list?uid=285516405&cid=1167145843&sid=863481066&pageSize=2&page=1` + +### [发送/删除评论](https://neteasecloudmusicapi.vercel.app/#/?id=发送删除评论) + +说明 : 调用此接口,可发送评论或者删除评论 + +**接口地址 :** `/comment` + +1. 发送评论 + + **必选参数** + + `t`:1 发送, 2 回复 + + `type`: 数字,资源类型,对应歌曲,mv,专辑,歌单,电台,视频对应以下类型 + + ``` + 0: 歌曲 + + 1: mv + + 2: 歌单 + + 3: 专辑 + + 4: 电台 + + 5: 视频 + + 6: 动态 + ``` + + `id`:对应资源 id + + `content` :要发送的内容 + + `commentId` :回复的评论 id (回复评论时必填) + + **调用例子** : `/comment?t=1&type=1&id=5436712&content=test` (往广岛之恋 mv 发送评论: test) + + 注意:如给动态发送评论,则不需要传 id,需要传动态的 `threadId`,如:`/comment?t=1&type=6&threadId=A_EV_2_6559519868_32953014&content=test` + +2. 删除评论 + + **必选参数** + + `t`:0 删除 + + `type`: 数字,资源类型,对应歌曲,mv,专辑,歌单,电台,视频对应以下类型 + +``` + 0: 歌曲 + + 1: mv + + 2: 歌单 + + 3: 专辑 + + 4: 电台 + + + 5: 视频 + + 6: 动态 +``` + +`id`:对应资源 id `content` :内容 id,可通过 `/comment/mv` 等接口获取 + +**调用例子** : `/comment?t=0&type=1&id=5436712&commentId=1535550516319` (在广岛之恋 mv 删除评论) + +注意:如给动态删除评论,则不需要传 id,需要传动态的 `threadId`,如:`/comment?t=0&type=6&threadId=A_EV_2_6559519868_32953014&commentId=1419516382` + +### [banner](https://neteasecloudmusicapi.vercel.app/#/?id=banner) + +说明 : 调用此接口 , 可获取 banner( 轮播图 ) 数据 + +**可选参数 :** + +`type`:资源类型,对应以下类型,默认为 0 即 PC + +``` +0: pc + +1: android + +2: iphone + +3: ipad +``` + +**接口地址 :** `/banner` + +**调用例子 :** `/banner`, `/banner?type=2` + +### [资源点赞( MV,电台,视频)](https://neteasecloudmusicapi.vercel.app/#/?id=资源点赞-mv电台视频) + +说明 : 调用此接口 , 可对 MV,电台,视频点赞 + +**必选参数 :** + +`type`:资源类型,对应以下类型 + +``` +1: mv + +4: 电台 + +5: 视频 + +6: 动态 +``` + +`t`: 操作,1 为点赞,其他为取消点赞 + +`id`: 资源 id + +**接口地址 :** `/resource/like` + +**调用例子 :** `/resource/like?t=1&type=1&id=5436712` + +注意:如给动态点赞,不需要传入 id,需要传入 `threadId`,可通过 `event`,`/user/event` 接口获取,如: `/resource/like?t=1&type=6&threadId=A_EV_2_6559519868_32953014` + +### [获取点赞过的视频](https://neteasecloudmusicapi.vercel.app/#/?id=获取点赞过的视频) + +说明 : 调用此接口, 可获取获取点赞过的视频 + +**接口地址 :** `/playlist/mylike` + +**调用例子 :** `/playlist/mylike` + +### [获取歌曲详情](https://neteasecloudmusicapi.vercel.app/#/?id=获取歌曲详情) + +说明 : 调用此接口 , 传入音乐 id(支持多个 id, 用 `,` 隔开), 可获得歌曲详情(dt为歌曲时长) + +**必选参数 :** `ids`: 音乐 id, 如 `ids=347230` + +**接口地址 :** `/song/detail` + +**调用例子 :** `/song/detail?ids=347230`,`/song/detail?ids=347230,347231` + +返回字段说明(感谢 [@tuxzz](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1121#issuecomment-774438040) 整理): + +``` +name: String, 歌曲标题 +id: u64, 歌曲ID +pst: 0,功能未知 +t: enum, + 0: 一般类型 + 1: 通过云盘上传的音乐,网易云不存在公开对应 + 如果没有权限将不可用,除了歌曲长度以外大部分信息都为null。 + 可以通过 `/api/v1/playlist/manipulate/tracks` 接口添加到播放列表。 + 如果添加到“我喜欢的音乐”,则仅自己可见,除了长度以外各种信息均为未知,且无法播放。 + 如果添加到一般播放列表,虽然返回code 200,但是并没有效果。 + 网页端打开会看到404画面。 + 属于这种歌曲的例子: https://music.163.com/song/1345937107 + 2: 通过云盘上传的音乐,网易云存在公开对应 + 如果没有权限则只能看到信息,但无法直接获取到文件。 + 可以通过 `/api/v1/playlist/manipulate/tracks` 接口添加到播放列表。 + 如果添加到“我喜欢的音乐”,则仅自己可见,且无法播放。 + 如果添加到一般播放列表,则自己会看到显示“云盘文件”,且云盘会多出其对应的网易云公开歌曲。其他人看到的是其对应的网易云公开歌曲。 + 网页端打开会看到404画面。 + 属于这种歌曲的例子: https://music.163.com/song/435005015 +ar: Vec, 歌手列表 +alia: Vec, + 别名列表,第一个别名会被显示作副标题 + 例子: https://music.163.com/song/536623501 +pop: 小数,常取[0.0, 100.0]中离散的几个数值, 表示歌曲热度 +st: 0: 功能未知 +rt: Option, None、空白字串、或者类似`600902000007902089`的字符串,功能未知 +fee: enum, + 0: 免费或无版权 + 1: VIP 歌曲 + 4: 购买专辑 + 8: 非会员可免费播放低音质,会员可播放高音质及下载 + fee 为 1 或 8 的歌曲均可单独购买 2 元单曲 +v: u64, 常为[1, ?]任意数字, 功能未知 +crbt: Option, None或字符串表示的十六进制,功能未知 +cf: Option, 空白字串或者None,功能未知 +al: Album, 专辑,如果是DJ节目(dj_type != 0)或者无专辑信息(single == 1),则专辑id为0 +dt: u64, 歌曲时长 +h: Option, 高质量文件信息 +m: Option, 中质量文件信息 +l: Option, 低质量文件信息 +a: Option, 常为None, 功能未知 +cd: Option, None或如"04", "1/2", "3", "null"的字符串,表示歌曲属于专辑中第几张CD,对应音频文件的Tag +no: u32, 表示歌曲属于CD中第几曲,0表示没有这个字段,对应音频文件的Tag +rtUrl: Option, 常为None, 功能未知 +rtUrls: Vec, 常为空列表, 功能未知 +dj_id: u64, + 0: 不是DJ节目 + 其他:是DJ节目,表示DJ ID +copyright: u32, 0, 1, 2: 功能未知 +s_id: u64, 对于t == 2的歌曲,表示匹配到的公开版本歌曲ID +mark: u64, 功能未知 +originCoverType: enum + 0: 未知 + 1: 原曲 + 2: 翻唱 +originSongSimpleData: Option, 对于翻唱曲,可选提供原曲简单格式的信息 +single: enum, + 0: 有专辑信息或者是DJ节目 + 1: 未知专辑 +noCopyrightRcmd: Option, None表示可以播,非空表示无版权 +mv: u64, 非零表示有MV ID +rtype: 常为0,功能未知 +rurl: Option, 常为None,功能未知 +mst: u32, 偶尔为0, 常为9,功能未知 +cp: u64, 功能未知 +publish_time: i64, 毫秒为单位的Unix时间戳 +pc: 云盘歌曲信息,如果不存在该字段,则为非云盘歌曲 +``` + +### [获取专辑内容](https://neteasecloudmusicapi.vercel.app/#/?id=获取专辑内容) + +说明 : 调用此接口 , 传入专辑 id, 可获得专辑内容 + +**必选参数 :** `id`: 专辑 id + +**接口地址 :** `/album` + +**调用例子 :** `/album?id=32311` + +### [专辑动态信息](https://neteasecloudmusicapi.vercel.app/#/?id=专辑动态信息) + +说明 : 调用此接口 , 传入专辑 id, 可获得专辑动态信息,如是否收藏,收藏数,评论数,分享数 + +**必选参数 :** `id`: 专辑 id + +**接口地址 :** `/album/detail/dynamic` + +**调用例子 :** `/album/detail/dynamic?id=32311` + +### [收藏/取消收藏专辑](https://neteasecloudmusicapi.vercel.app/#/?id=收藏取消收藏专辑) + +说明 : 调用此接口,可收藏/取消收藏专辑 + +**必选参数 :** + +`id` : 专辑 id + +`t` : 1 为收藏,其他为取消收藏 + +**接口地址 :** `/album/sub` + +**调用例子 :** `/album/sub?t=1` `/album/sub?t=0` + +### [获取已收藏专辑列表](https://neteasecloudmusicapi.vercel.app/#/?id=获取已收藏专辑列表) + +说明 : 调用此接口 , 可获得已收藏专辑列表 + +**可选参数 :** +`limit`: 取出数量 , 默认为 25 + +`offset`: 偏移数量 , 用于分页 , 如 :( 页数 -1)*25, 其中 25 为 limit 的值 , 默认 为 0 + +**接口地址 :** `/album/sublist` + +**调用例子 :** `/album/sublist` ( 周杰伦 ) + +### [获取歌手单曲](https://neteasecloudmusicapi.vercel.app/#/?id=获取歌手单曲) + +说明 : 调用此接口 , 传入歌手 id, 可获得歌手部分信息和热门歌曲 + +**必选参数 :** `id`: 歌手 id, 可由搜索接口获得 + +**接口地址 :** `/artists` + +**调用例子 :** `/artists?id=6452` + +返回数据如下图 : ![获取歌手单曲](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/artists.png) + +### [获取歌手 mv](https://neteasecloudmusicapi.vercel.app/#/?id=获取歌手-mv) + +说明 : 调用此接口 , 传入歌手 id, 可获得歌手 mv 信息 , 具体 mv 播放地址可调 用`/mv`传入此接口获得的 mvid 来拿到 , 如 : `/artist/mv?id=6452`,`/mv?mvid=5461064` + +**必选参数 :** `id`: 歌手 id, 可由搜索接口获得 + +**接口地址 :** `/artist/mv` + +**调用例子 :** `/artist/mv?id=6452` + +### [获取歌手专辑](https://neteasecloudmusicapi.vercel.app/#/?id=获取歌手专辑) + +说明 : 调用此接口 , 传入歌手 id, 可获得歌手专辑内容 + +**必选参数 :** `id`: 歌手 id + +**可选参数 :** `limit`: 取出数量 , 默认为 30 + +`offset`: 偏移数量 , 用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认 为 0 + +**接口地址 :** `/artist/album` + +**调用例子 :** `/artist/album?id=6452&limit=5` ( 周杰伦 ) + +返回数据如下图 : ![获取专辑内容](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/artist_album.png) + +### [获取歌手描述](https://neteasecloudmusicapi.vercel.app/#/?id=获取歌手描述) + +说明 : 调用此接口 , 传入歌手 id, 可获得歌手描述 + +**必选参数 :** `id`: 歌手 id + +**接口地址 :** `/artist/desc` + +**调用例子 :** `/artist/desc?id=6452` ( 周杰伦 ) + +### [获取歌手详情](https://neteasecloudmusicapi.vercel.app/#/?id=获取歌手详情) + +说明 : 调用此接口 , 传入歌手 id, 可获得获取歌手详情 + +**必选参数 :** `id`: 歌手 id + +**接口地址 :** `/artist/detail` + +**调用例子 :** `/artist/detail?id=11972054` (Billie Eilish) + +### [获取相似歌手](https://neteasecloudmusicapi.vercel.app/#/?id=获取相似歌手) + +说明 : 调用此接口 , 传入歌手 id, 可获得相似歌手 + +**必选参数 :** `id`: 歌手 id + +**接口地址 :** `/simi/artist` + +**调用例子 :** `/simi/artist?id=6452` ( 对应和周杰伦相似歌手 ) + +### [获取相似歌单](https://neteasecloudmusicapi.vercel.app/#/?id=获取相似歌单) + +说明 : 调用此接口 , 传入歌曲 id, 可获得相似歌单 + +**必选参数 :** `id`: 歌曲 id + +**接口地址 :** `/simi/playlist` + +**调用例子 :** `/simi/playlist?id=347230` ( 对应 ' 光辉岁月 ' 相似歌单 ) + +### [相似 mv](https://neteasecloudmusicapi.vercel.app/#/?id=相似-mv) + +说明 : 调用此接口 , 传入 `mvid` 可获取相似 mv + +**必选参数 :** `mvid`: mv id + +**接口地址 :** `/simi/mv` + +**调用例子 :** `/simi/mv?mvid=5436712` + +### [获取相似音乐](https://neteasecloudmusicapi.vercel.app/#/?id=获取相似音乐) + +说明 : 调用此接口 , 传入歌曲 id, 可获得相似歌曲 + +**必选参数 :** `id`: 歌曲 id + +**接口地址 :** `/simi/song` + +**调用例子 :** `/simi/song?id=347230` ( 对应 ' 光辉岁月 ' 相似歌曲 ) + +### [获取最近 5 个听了这首歌的用户](https://neteasecloudmusicapi.vercel.app/#/?id=获取最近-5-个听了这首歌的用户) + +说明 : 调用此接口 , 传入歌曲 id, 最近 5 个听了这首歌的用户 + +**必选参数 :** `id`: 歌曲 id + +**接口地址 :** `/simi/user` + +**调用例子 :** `/simi/user?id=347230` ( 对应 ' 光辉岁月 ' 相似歌曲 ) + +### [获取每日推荐歌单](https://neteasecloudmusicapi.vercel.app/#/?id=获取每日推荐歌单) + +说明 : 调用此接口 , 可获得每日推荐歌单 ( 需要登录 ) + +**接口地址 :** `/recommend/resource` + +**调用例子 :** `/recommend/resource` + +返回数据如下图 : ![每日推荐歌单](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/%E6%8E%A8%E8%8D%90%E6%AD%8C%E5%8D%95.png) + +### [获取每日推荐歌曲](https://neteasecloudmusicapi.vercel.app/#/?id=获取每日推荐歌曲) + +说明 : 调用此接口 , 可获得每日推荐歌曲 ( 需要登录 ) + +**接口地址 :** `/recommend/songs` + +**调用例子 :** `/recommend/songs` + +返回数据如下图 : ![每日推荐歌曲](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/%E6%8E%A8%E8%8D%90%E6%AD%8C%E6%9B%B2.png) + +### [获取历史日推可用日期列表](https://neteasecloudmusicapi.vercel.app/#/?id=获取历史日推可用日期列表) + +说明 : 调用此接口 , 可获得历史日推可用日期列表 + +**接口地址 :** `/history/recommend/songs` + +**调用例子 :** `/history/recommend/songs` + +### [获取历史日推详情数据](https://neteasecloudmusicapi.vercel.app/#/?id=获取历史日推详情数据) + +说明 : 调用此接口 ,传入当日日期, 可获得当日历史日推数据 + +**必选参数 :** `date`: 日期,通过历史日推可用日期列表接口获取,不能任意日期 + +**接口地址 :** `/history/recommend/songs/detail` + +**调用例子 :** `/history/recommend/songs/detail?date=2020-06-21` + +### [私人 FM](https://neteasecloudmusicapi.vercel.app/#/?id=私人-fm) + +说明 : 私人 FM( 需要登录 ) + +**接口地址 :** `/personal_fm` + +**调用例子 :** `/personal_fm` + +返回数据如下图 : + +![私人 FM](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/personal_fm.png) + +### [签到](https://neteasecloudmusicapi.vercel.app/#/?id=签到) + +说明 : 调用此接口 , 传入签到类型 ( 可不传 , 默认安卓端签到 ), 可签到 ( 需要登录 ), 其中安卓端签到可获得 3 点经验 , web/PC 端签到可获得 2 点经验 + +**可选参数 :** `type`: 签到类型 , 默认 0, 其中 0 为安卓端签到 ,1 为 web/PC 签到 + +**接口地址 :** `/daily_signin` + +**调用例子 :** `/daily_signin` + +返回数据如下图 : + +![签到成功](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/signinSuccess.png) + +![签到失败](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/signinError.png) + +### [乐签信息](https://neteasecloudmusicapi.vercel.app/#/?id=乐签信息) + +说明 : 调用此接口, 可获取乐签信息 + +**接口地址 :** `/sign/happy/info` + +### [喜欢音乐](https://neteasecloudmusicapi.vercel.app/#/?id=喜欢音乐) + +说明 : 调用此接口 , 传入音乐 id, 可喜欢该音乐 + +**必选参数 :** `id`: 歌曲 id + +**可选参数 :** `like`: 布尔值 , 默认为 true 即喜欢 , 若传 false, 则取消喜欢 + +**接口地址 :** `/like` + +**调用例子 :** `/like?id=347230` + +返回数据如下图 : + +![喜欢成功](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/like.png) + +喜欢成功则返回数据的 code 为 200, 其余为失败 + +![喜欢成功截图](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/likeSuccess.png) + +### [喜欢音乐列表](https://neteasecloudmusicapi.vercel.app/#/?id=喜欢音乐列表) + +说明 : 调用此接口 , 传入用户 id, 可获取已喜欢音乐 id 列表(id 数组) + +**必选参数 :** `uid`: 用户 id + +**接口地址 :** `/likelist` + +**调用例子 :** `/likelist?uid=32953014` + +### [垃圾桶](https://neteasecloudmusicapi.vercel.app/#/?id=垃圾桶) + +说明 : 调用此接口 , 传入音乐 id, 可把该音乐从私人 FM 中移除至垃圾桶 + +**必选参数 :** `id`: 歌曲 id + +**接口地址 :** `/fm_trash` + +**调用例子 :** `/fm_trash?id=347230` + +返回数据如下图 : + +![移除成功](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/fm_trash.png) + +### [新碟上架](https://neteasecloudmusicapi.vercel.app/#/?id=新碟上架) + +说明 : 调用此接口 , 可获取新碟上架列表 , 如需具体音乐信息需要调用获取专辑列表接 口 `/album` , 然后传入 id, 如 `/album?id=32311&limit=30` + +**可选参数 :** + +`limit`: 取出数量 , 默认为 50 + +`offset`: 偏移数量 , 用于分页 , 如 :( 页数 -1)*50, 其中 50 为 limit 的值 , 默认 为 0 + +`area`: ALL:全部,ZH:华语,EA:欧美,KR:韩国,JP:日本 + +`type` : new:全部 hot:热门,默认为 new + +`year` : 年,默认本年 + +`month` : 月,默认本月 + +**接口地址 :** `/top/album` + +**调用例子 :** `/top/album?offset=0&limit=30&year=2019&month=6` + +### [全部新碟](https://neteasecloudmusicapi.vercel.app/#/?id=全部新碟) + +说明 : 登录后调用此接口 ,可获取全部新碟 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +`offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 + +`area` : ALL:全部,ZH:华语,EA:欧美,KR:韩国,JP:日本 + +**接口地址 :** `/album/new` + +**调用例子 :** `/album/new?area=KR&limit=10` + +### [最新专辑](https://neteasecloudmusicapi.vercel.app/#/?id=最新专辑) + +说明 : 调用此接口 ,获取云音乐首页新碟上架数据 + +**接口地址 :** `/album/newest` + +**调用例子 :** `/album/newest` + +### [听歌打卡](https://neteasecloudmusicapi.vercel.app/#/?id=听歌打卡) + +说明 : 调用此接口 , 传入音乐 id, 来源 id,歌曲时间 time,更新听歌排行数据 + +**必选参数 :** `id`: 歌曲 id, `sourceid`: 歌单或专辑 id + +**可选参数 :** `time`: 歌曲播放时间,单位为秒 + +**接口地址 :** `/scrobble` + +**调用例子 :** `/scrobble?id=518066366&sourceid=36780169&time=291` + +### [热门歌手](https://neteasecloudmusicapi.vercel.app/#/?id=热门歌手) + +说明 : 调用此接口 , 可获取热门歌手数据 + +**可选参数 :** `limit`: 取出数量 , 默认为 50 + +`offset`: 偏移数量 , 用于分页 , 如 :( 页数 -1)*50, 其中 50 为 limit 的值 , 默认 为 0 + +**接口地址 :** `/top/artists` + +**调用例子 :** `/top/artists?offset=0&limit=30` + +返回数据如下图 : + +![热门歌手](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/top_artists.png) + +### [全部 mv](https://neteasecloudmusicapi.vercel.app/#/?id=全部-mv) + +说明 : 调用此接口 , 可获取全部 mv + +**可选参数 :** +`area`: 地区,可选值为全部,内地,港台,欧美,日本,韩国,不填则为全部 `type`: 类型,可选值为全部,官方版,原生,现场版,网易出品,不填则为全部 + +`order`: 排序,可选值为上升最快,最热,最新,不填则为上升最快 + +`limit`: 取出数量 , 默认为 30 + +`offset`: 偏移数量 , 用于分页 , 如 :( 页数 -1)*50, 其中 50 为 limit 的值 , 默认 为 0 + +**接口地址 :** `/mv/all` + +**调用例子 :** `/mv/all?area=港台` + +### [最新 mv](https://neteasecloudmusicapi.vercel.app/#/?id=最新-mv) + +说明 : 调用此接口 , 可获取最新 mv + +**可选参数 :** `area`: 地区,可选值为全部,内地,港台,欧美,日本,韩国,不填则为全部 + +**可选参数 :** `limit`: 取出数量 , 默认为 30 + +**接口地址 :** `/mv/first` + +**调用例子 :** `/mv/first?limit=10` + +### [网易出品 mv](https://neteasecloudmusicapi.vercel.app/#/?id=网易出品-mv) + +说明 : 调用此接口 , 可获取网易出品 mv + +**可选参数 :** `limit`: 取出数量 , 默认为 30 + +`offset`: 偏移数量 , 用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认 为 0 + +**接口地址 :** `/mv/exclusive/rcmd` + +**调用例子 :** `/mv/exclusive/rcmd?limit=10` + +### [推荐 mv](https://neteasecloudmusicapi.vercel.app/#/?id=推荐-mv) + +说明 : 调用此接口 , 可获取推荐 mv + +**接口地址 :** `/personalized/mv` + +**调用例子 :** `/personalized/mv` + +### [推荐歌单](https://neteasecloudmusicapi.vercel.app/#/?id=推荐歌单) + +说明 : 调用此接口 , 可获取推荐歌单 + +**可选参数 :** `limit`: 取出数量 , 默认为 30 (不支持 offset) + +**接口地址 :** `/personalized` + +**调用例子 :** `/personalized?limit=1` + +### [推荐新音乐](https://neteasecloudmusicapi.vercel.app/#/?id=推荐新音乐) + +说明 : 调用此接口 , 可获取推荐新音乐 + +**可选参数 :** `limit`: 取出数量 , 默认为 10 (不支持 offset) + +**接口地址 :** `/personalized/newsong` + +**调用例子 :** `/personalized/newsong` + +### [推荐电台](https://neteasecloudmusicapi.vercel.app/#/?id=推荐电台) + +说明 : 调用此接口 , 可获取推荐电台 + +**接口地址 :** `/personalized/djprogram` + +**调用例子 :** `/personalized/djprogram` + +### [推荐节目](https://neteasecloudmusicapi.vercel.app/#/?id=推荐节目) + +说明 : 调用此接口 , 可获取推荐电台 + +**接口地址 :** `/program/recommend` + +**调用例子 :** `/program/recommend` + +### [独家放送(入口列表)](https://neteasecloudmusicapi.vercel.app/#/?id=独家放送入口列表) + +说明 : 调用此接口 , 可获取独家放送 + +**接口地址 :** `/personalized/privatecontent` + +**调用例子 :** `/personalized/privatecontent` + +### [独家放送列表](https://neteasecloudmusicapi.vercel.app/#/?id=独家放送列表) + +说明 : 调用此接口 , 可获取独家放送列表 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 60 + +`offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*60, 其中 60 为 limit 的值 , 默认为 0 + +**接口地址 :** `/personalized/privatecontent/list` + +**调用例子 :** `/personalized/privatecontent/list?limit=1&offset=2` + +### [mv 排行](https://neteasecloudmusicapi.vercel.app/#/?id=mv-排行) + +说明 : 调用此接口 , 可获取 mv 排行 + +**可选参数 :** `limit`: 取出数量 , 默认为 30 + +`area`: 地区,可选值为内地,港台,欧美,日本,韩国,不填则为全部 + +`offset`: 偏移数量 , 用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认 为 0 + +**接口地址 :** `/top/mv` + +**调用例子 :** `/top/mv?limit=10` + +### [获取 mv 数据](https://neteasecloudmusicapi.vercel.app/#/?id=获取-mv-数据) + +说明 : 调用此接口 , 传入 mvid ( 在搜索音乐的时候传 type=1004 获得 ) , 可获取对应 MV 数据 , 数据包含 mv 名字 , 歌手 , 发布时间 , mv 视频地址等数据 , 其中 mv 视频 网易做了防盗链处理 , 可能不能直接播放 , 需要播放的话需要调用 ' mv 地址' 接口 + +**必选参数 :** `mvid`: mv 的 id + +**接口地址 :** `/mv/detail` + +**调用例子 :** `/mv/detail?mvid=5436712` + +返回数据如下图 : + +![mv 数据](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/mv.png) + +### [获取 mv 点赞转发评论数数据](https://neteasecloudmusicapi.vercel.app/#/?id=获取-mv-点赞转发评论数数据) + +说明 : 调用此接口 , 传入 mvid ( 在搜索音乐的时候传 type=1004 获得 ) , 可获取对应 MV 点赞转发评论数数据 + +**必选参数 :** `mvid`: mv 的 id + +**接口地址 :** `/mv/detail/info` + +**调用例子 :** `/mv/detail/info?mvid=5436712` + +### [mv 地址](https://neteasecloudmusicapi.vercel.app/#/?id=mv-地址) + +说明 : 调用此接口 , 传入 mv id,可获取 mv 播放地址 + +**必选参数 :** `id`: mv id + +**可选参数 :** `r`: 分辨率,默认 1080,可从 `/mv/detail` 接口获取分辨率列表 + +**接口地址 :** `/mv/url` + +**调用例子 :** + +``` +/mv/url?id=5436712` `/mv/url?id=10896407&r=1080 +``` + +### [获取视频标签列表](https://neteasecloudmusicapi.vercel.app/#/?id=获取视频标签列表) + +说明 : 调用此接口 , 可获取视频标签列表 + +**接口地址 :** `/video/group/list` + +**调用例子 :** `/video/group/list` + +### [获取视频分类列表](https://neteasecloudmusicapi.vercel.app/#/?id=获取视频分类列表) + +说明 : 调用此接口 , 可获取视频分类列表 + +**接口地址 :** `/video/category/list` + +**调用例子 :** `/video/category/list` + +### [获取视频标签/分类下的视频](https://neteasecloudmusicapi.vercel.app/#/?id=获取视频标签分类下的视频) + +说明 : 调用此接口 , 传入标签/分类`id`,可获取到相关的视频,分页参数只能传入 offset + +**必选参数 :** `id`: videoGroup 的 id + +**可选参数 :** `offset`: 默认 0 + +**接口地址 :** `/video/group` + +**调用例子 :** `/video/group?id=9104` + +### [获取全部视频列表](https://neteasecloudmusicapi.vercel.app/#/?id=获取全部视频列表) + +说明 : 调用此接口,可获取视频分类列表,分页参数只能传入 offset + +**可选参数 :** `offset`: 默认 0 + +**接口地址 :** `/video/timeline/all` + +**调用例子 :** `/video/timeline/all` + +### [获取推荐视频](https://neteasecloudmusicapi.vercel.app/#/?id=获取推荐视频) + +说明 : 调用此接口, 可获取推荐视频,分页参数只能传入 offset + +**可选参数 :** `offset`: 默认 0 + +**接口地址 :** `/video/timeline/recommend` + +**调用例子 :** `/video/timeline/recommend?offset=10` + +### [相关视频](https://neteasecloudmusicapi.vercel.app/#/?id=相关视频) + +说明 : 调用此接口 , 可获取相关视频 + +**必选参数 :** `id`: 视频 的 id + +**接口地址 :** `/related/allvideo` + +**调用例子 :** `/related/allvideo?id=89ADDE33C0AAE8EC14B99F6750DB954D` + +### [视频详情](https://neteasecloudmusicapi.vercel.app/#/?id=视频详情) + +说明 : 调用此接口 , 可获取视频详情 + +**必选参数 :** `id`: 视频 的 id + +**接口地址 :** `/video/detail` + +**调用例子 :** `/video/detail?id=89ADDE33C0AAE8EC14B99F6750DB954D` + +### [获取视频点赞转发评论数数据](https://neteasecloudmusicapi.vercel.app/#/?id=获取视频点赞转发评论数数据) + +说明 : 调用此接口 , 传入 vid ( 视频 id ) , 可获取对应视频点赞转发评论数数据 **必选参数 :** `vid`: 视频 id + +**接口地址 :** `/video/detail/info` + +**调用例子 :** `/video/detail/info?vid=89ADDE33C0AAE8EC14B99F6750DB954D` + +### [获取视频播放地址](https://neteasecloudmusicapi.vercel.app/#/?id=获取视频播放地址) + +说明 : 调用此接口 , 传入视频 id,可获取视频播放地址 + +**必选参数 :** `id`: 视频 的 id + +**接口地址 :** `/video/url` + +**调用例子 :** `/video/url?id=89ADDE33C0AAE8EC14B99F6750DB954D` + +### [所有榜单](https://neteasecloudmusicapi.vercel.app/#/?id=所有榜单) + +说明 : 调用此接口,可获取所有榜单 **接口地址 :** `/toplist` + +**调用例子 :** `/toplist` + +### [排行榜详情](https://neteasecloudmusicapi.vercel.app/#/?id=排行榜详情) + +说明: 请使用[歌单详情](https://neteasecloudmusicapi.vercel.app/#/?id=获取歌单详情)接口,传入排行榜 id 获取排行榜详情数据(排行榜也是歌单的一种) + +~~说明 : 调用此接口 , 传入榜单 id, 可获取不同排行榜数据(v3.34.0 之后不再支持 idx 参数)~~ + +~~**必选参数 :** `id`: 榜单 id,通过所有榜单接口获取~~ + +~~**接口地址 :** `/top/list`~~ + +~~**调用例子 :** `/top/list?id=2809577409`~~ + +### [所有榜单内容摘要](https://neteasecloudmusicapi.vercel.app/#/?id=所有榜单内容摘要) + +说明 : 调用此接口,可获取所有榜单内容摘要 + +**接口地址 :** `/toplist/detail` + +**调用例子 :** `/toplist/detail` + +### [歌手榜](https://neteasecloudmusicapi.vercel.app/#/?id=歌手榜) + +说明 : 调用此接口 , 可获取排行榜中的歌手榜 + +**可选参数 :** + +``` +type : 地区 +1: 华语 +2: 欧美 +3: 韩国 +4: 日本 +``` + +**接口地址 :** `/toplist/artist` + +**调用例子 :** `/toplist/artist` + +### [云盘](https://neteasecloudmusicapi.vercel.app/#/?id=云盘) + +说明 : 登录后调用此接口 , 可获取云盘数据 , 获取的数据没有对应 url, 需要再调用一 次 `/song/url` 获取 url + +**可选参数 :** + +`limit` : 返回数量 , 默认为 200 + +`offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*200, 其中 200 为 limit 的值 , 默认为 0 + +**接口地址 :** `/user/cloud` + +**调用例子 :** `/user/cloud` + +### [云盘数据详情](https://neteasecloudmusicapi.vercel.app/#/?id=云盘数据详情) + +说明 : 登录后调用此接口 , 传入云盘歌曲 id,可获取云盘数据详情 + +**必选参数 :** `id`: 歌曲 id,可多个,用逗号隔开 + +**接口地址 :** `/user/cloud/detail` + +**调用例子 :** `/user/cloud/detail?id=5374627` + +### [云盘歌曲删除](https://neteasecloudmusicapi.vercel.app/#/?id=云盘歌曲删除) + +说明 : 登录后调用此接口 , 可删除云盘歌曲 + +**必选参数 :** `id`: 歌曲 id,可多个,用逗号隔开 + +**接口地址 :** `/user/cloud/del` + +**调用例子 :** `/user/cloud/del` + +### [云盘上传](https://neteasecloudmusicapi.vercel.app/#/?id=云盘上传) + +说明 : 登录后调用此接口,使用`'Content-Type': 'multipart/form-data'`上传 mp3 formData(name 为'songFile'),可上传歌曲到云盘 + +参考: https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/public/cloud.html + +访问地址: http://localhost:3000/cloud.html) + +支持命令行调用,参考 module_example 目录下`song_upload.js` + +**接口地址 :** `/cloud` + +**调用例子 :** `/cloud` + +### [云盘歌曲信息匹配纠正](https://neteasecloudmusicapi.vercel.app/#/?id=云盘歌曲信息匹配纠正) + +说明 : 登录后调用此接口,可对云盘歌曲信息匹配纠正,如需取消匹配,asid 需要传 0 + +**必选参数 :** +`uid`: 用户 id + +`sid`: 云盘的歌曲 id + +`asid`: 要匹配的歌曲 id + +**接口地址 :** `/cloud/match` + +**调用例子 :** `/cloud/match?uid=32953014&sid=aaa&asid=bbb` `/cloud/match?uid=32953014&sid=bbb&asid=0` + +### [电台 banner](https://neteasecloudmusicapi.vercel.app/#/?id=电台-banner) + +说明 : 调用此接口,可获取电台 banner + +**接口地址 :** `/dj/banner` + +**调用例子 :** `/dj/banner` + +### [电台个性推荐](https://neteasecloudmusicapi.vercel.app/#/?id=电台个性推荐) + +说明 : 调用此接口,可获取电台个性推荐列表 **可选参数 :** + +`limit` : 返回数量,默认为 6,总条数最多 6 条 + +**接口地址 :** `/dj/personalize/recommend` + +**调用例子 :** `/dj/personalize/recommend?limit=5` + +### [电台订阅者列表](https://neteasecloudmusicapi.vercel.app/#/?id=电台订阅者列表) + +说明 : 调用此接口,可获取电台订阅者列表 **必选参数 :** `id`: 电台 id + +**可选参数 :** `time` : 分页参数,默认-1,传入上一次返回结果的 time,将会返回下一页的数据 + +`limit` : 返回数量,默认为 20 + +**接口地址 :** `/dj/subscriber` + +**调用例子 :** `/dj/subscriber?id=335425050` , `/dj/subscriber?id=335425050&time=1602761825390` + +### [用户电台](https://neteasecloudmusicapi.vercel.app/#/?id=用户电台) + +说明 : 调用此接口, 传入用户 id 可获取用户创建的电台 + +**必选参数 :** `uid`: 用户 id + +**接口地址 :** `/user/audio` + +**调用例子 :** `/user/audio?uid=32953014` + +### [热门电台](https://neteasecloudmusicapi.vercel.app/#/?id=热门电台) + +说明 : 调用此接口,可获取热门电台 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +``` +offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 **接口地址 :** `/dj/hot +``` + +**调用例子 :** `/dj/hot` + +### [电台 - 节目榜](https://neteasecloudmusicapi.vercel.app/#/?id=电台-节目榜) + +说明 : 登录后调用此接口 , 可获得电台节目榜 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 100 + +`offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*100, 其中 100 为 limit 的值 , 默认为 0 + +**接口地址 :** `/dj/program/toplist` + +**调用例子 :** `/dj/program/toplist?limit=1` + +### [电台 - 付费精品](https://neteasecloudmusicapi.vercel.app/#/?id=电台-付费精品) + +说明 : 调用此接口,可获取付费精品电台 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 100 (不支持 offset) + +**接口地址 :** `/dj/toplist/pay` + +**调用例子 :** `/dj/toplist/pay?limit=30` + +### [电台 - 24 小时节目榜](https://neteasecloudmusicapi.vercel.app/#/?id=电台-24-小时节目榜) + +说明 : 调用此接口,可获取 24 小时节目榜 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 100 (不支持 offset) + +**接口地址 :** `/dj/program/toplist/hours` + +**调用例子 :** `/dj/program/toplist/hours?limit=1` + +### [电台 - 24 小时主播榜](https://neteasecloudmusicapi.vercel.app/#/?id=电台-24-小时主播榜) + +说明 : 调用此接口,可获取 24 小时主播榜 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 100 (不支持 offset) + +**接口地址 :** `/dj/toplist/hours` + +**调用例子 :** `/dj/toplist/hours?limit=30` + +### [电台 - 主播新人榜](https://neteasecloudmusicapi.vercel.app/#/?id=电台-主播新人榜) + +说明 : 调用此接口,可获取主播新人榜 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 100 (不支持 offset) + +**接口地址 :** `/dj/toplist/newcomer` + +**调用例子 :** `/dj/toplist/newcomer?limit=30` + +### [电台 - 最热主播榜](https://neteasecloudmusicapi.vercel.app/#/?id=电台-最热主播榜) + +说明 : 调用此接口,可获取最热主播榜 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 100 (不支持 offset) + +**接口地址 :** `/dj/toplist/popular` + +**调用例子 :** `/dj/toplist/popular?limit=30` + +### [电台 - 新晋电台榜/热门电台榜](https://neteasecloudmusicapi.vercel.app/#/?id=电台-新晋电台榜热门电台榜) + +说明 : 登录后调用此接口 , 可获得新晋电台榜/热门电台榜 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 100 + +`offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*100, 其中 100 为 limit 的值 , 默认为 0 + +`type`: 榜单类型, `new` 为新晋电台榜,`hot`为热门电台榜 + +**接口地址 :** `/dj/toplist` + +**调用例子 :** `/dj/toplist?type=hot` `/dj/toplist?type=new&limit=1` + +### [电台 - 类别热门电台](https://neteasecloudmusicapi.vercel.app/#/?id=电台-类别热门电台) + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +`offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 + +`cateId`: 类别 id,可通过 `/dj/category/recommend` 接口获取 + +**接口地址 :** `/dj/radio/hot` + +**调用例子 :** `/dj/radio/hot?cateId=2001`(创作|翻唱) `/dj/radio/hot?cateId=10002` (3D|电子) + +### [电台 - 推荐](https://neteasecloudmusicapi.vercel.app/#/?id=电台-推荐) + +说明 : 登录后调用此接口 , 可获得推荐电台 + +**接口地址 :** `/dj/recommend` + +**调用例子 :** `/dj/recommend` + +### [电台 - 分类](https://neteasecloudmusicapi.vercel.app/#/?id=电台-分类) + +说明 : 登录后调用此接口 , 可获得电台类型 + +**接口地址 :** `/dj/catelist` + +**调用例子 :** `/dj/catelist` + +### [电台 - 分类推荐](https://neteasecloudmusicapi.vercel.app/#/?id=电台-分类推荐) + +说明 : 登录后调用此接口 , 传入分类,可获得对应类型电台列表 + +**必选参数 :** `type`: 电台类型 , 数字 , 可通过`/dj/catelist`获取 , 对应关系为 id 对应 此接口的 type, name 对应类型 + +**接口地址 :** `/dj/recommend/type` + +**调用例子 :** `/dj/recommend/type?type=1`(明星做主播) `/dj/recommend/type?type=2001` (创作|翻唱) + +### [电台 - 订阅](https://neteasecloudmusicapi.vercel.app/#/?id=电台-订阅) + +说明 : 登录后调用此接口 , 传入`rid`, 可订阅 dj,dj 的 `rid` 可通过搜索指定 type='1009' 获取其 id, 如`/search?keywords= 代码时间 &type=1009` + +**必选参数 :** `rid`: 电台 的 id + +**接口地址 :** `/dj/sub` + +**调用例子 :** `/dj/sub?rid=336355127&t=1` ( 对应关注 ' 代码时间 ') `/dj/sub?rid=336355127&t=0` ( 对应取消关注 ' 代码时间 ') + +### [电台的订阅列表](https://neteasecloudmusicapi.vercel.app/#/?id=电台的订阅列表) + +说明 : 登录后调用此接口 , 可获取订阅的电台列表 + +**接口地址 :** `/dj/sublist` + +**调用例子 :** `/dj/sublist` + +### [电台 - 付费精选](https://neteasecloudmusicapi.vercel.app/#/?id=电台-付费精选) + +说明 : 可以获取付费精选的电台列表 , 传入 `limit` 和 `offset` 可以进行分页 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +`offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 + +**接口地址 :** `/dj/paygift` + +**调用例子 :** `/dj/paygift?limit=10&offset=20` + +### [电台 - 非热门类型](https://neteasecloudmusicapi.vercel.app/#/?id=电台-非热门类型) + +说明 : 登录后调用此接口, 可获得电台非热门类型 + +**接口地址 :** `/dj/category/excludehot` + +**调用例子 :** `/dj/category/excludehot` + +### [电台 - 推荐类型](https://neteasecloudmusicapi.vercel.app/#/?id=电台-推荐类型) + +说明 : 登录后调用此接口, 可获得电台推荐类型 + +**接口地址 :** `/dj/category/recommend` + +**调用例子 :** `/dj/category/recommend` + +### [电台 - 今日优选](https://neteasecloudmusicapi.vercel.app/#/?id=电台-今日优选) + +说明 : 登录后调用此接口, 可获得电台今日优选 + +**接口地址 :** `/dj/today/perfered` + +**调用例子 :** `/dj/today/perfered` + +### [电台 - 详情](https://neteasecloudmusicapi.vercel.app/#/?id=电台-详情) + +说明 : 登录后调用此接口 , 传入`rid`, 可获得对应电台的详情介绍 + +**必选参数 :** `rid`: 电台 的 id + +**接口地址 :** `/dj/detail` + +**调用例子 :** `/dj/detail?rid=336355127` ( 对应 ' 代码时间 ' 的详情介绍 ) + +### [电台 - 节目](https://neteasecloudmusicapi.vercel.app/#/?id=电台-节目) + +说明 : 登录后调用此接口 , 传入`rid`, 可查看对应电台的电台节目以及对应的 id, 需要 注意的是这个接口返回的 mp3Url 已经无效 , 都为 null, 但是通过调用 `/song/url` 这 个接口 , 传入节目 id 仍然能获取到节目音频 , 如 `/song/url?id=478446370` 获取代 码时间的一个节目的音频 + +**必选参数 :** `rid`: 电台 的 id + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +`offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 + +`asc` : 排序方式,默认为 `false` (新 => 老 ) 设置 `true` 可改为 老 => 新 + +**接口地址 :** `/dj/program` + +**调用例子 :** `/dj/program?rid=336355127&limit=40` ( 对应 ' 代码时间 ' 的节目列表 ) + +### [电台 - 节目详情](https://neteasecloudmusicapi.vercel.app/#/?id=电台-节目详情) + +说明 : 调用此接口传入电台节目 id,可获得电台节目详情 + +**必选参数 :** `id`: 电台节目 的 id + +**接口地址 :** `/dj/program/detail` + +**调用例子 :** `/dj/program/detail?id=1367665101` + +### [通知 - 私信](https://neteasecloudmusicapi.vercel.app/#/?id=通知-私信) + +说明 : 登录后调用此接口 ,可获取私信 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +`offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 + +**接口地址 :** `/msg/private` + +**调用例子 :** `/msg/private?limit=3` + +### [发送私信](https://neteasecloudmusicapi.vercel.app/#/?id=发送私信) + +说明 : 登录后调用此接口 , 传入用户 id 和要发送的信息, 可以发送私信,返回内容为历史私信,包含带歌单的私信信息(注:不能发送私信给自己) + +**必选参数 :** + +`user_ids` : 用户 id,多个需用逗号隔开 + +`msg` : 要发送的信息 + +**接口地址 :** `/send/text` + +**调用例子 :** `/send/text?user_ids=32953014&msg=test`,`/send/text?user_ids=32953014,475625142&msg=test` + +### [发送私信(带歌曲)](https://neteasecloudmusicapi.vercel.app/#/?id=发送私信带歌曲) + +说明 : 登录后调用此接口 , 传入用户 id 和要发送的信息,音乐 id, 可以发送音乐私信,返回内容为历史私信 + +**必选参数 :** + +`user_ids` : 用户 id,多个需用逗号隔开 + +`id` : 要发送音乐的 id + +`msg` : 要发送的信息 + +**接口地址 :** `/send/song` + +**调用例子 :** `/send/song?user_ids=1&id=351318&msg=测试` + +### [发送私信(带专辑)](https://neteasecloudmusicapi.vercel.app/#/?id=发送私信带专辑) + +说明 : 登录后调用此接口 , 传入用户 id 和要发送的信息,专辑 id, 可以发送专辑私信,返回内容为消息 id + +**必选参数 :** + +`user_ids` : 用户 id,多个需用逗号隔开 + +`id` : 要发送专辑的 id + +`msg` : 要发送的信息 + +**接口地址 :** `/send/album` + +**调用例子 :** `/send/album?user_ids=1&id=351318&msg=测试` + +### [发送私信(带歌单)](https://neteasecloudmusicapi.vercel.app/#/?id=发送私信带歌单) + +说明 : 登录后调用此接口 , 传入用户 id 和要发送的信息和歌单 id, 可以发送带歌单的私信(注:不能发送重复的歌单) + +**必选参数 :** + +`user_ids` : 用户 id,多个需用逗号隔开 + +`msg` : 要发送的信息 + +**接口地址 :** `/send/playlist` + +**调用例子 :** `/send/playlist?msg=test&user_ids=475625142&playlist=705123491`,`/send/playlist?msg=test2&user_ids=475625142,32953014&playlist=705123493` + +### [最近联系人](https://neteasecloudmusicapi.vercel.app/#/?id=最近联系人) + +说明 : 登录后调用此接口 ,可获取最接近联系人 + +**接口地址 :** `/msg/recentcontact` + +**调用例子 :** `/msg/recentcontact` + +### [私信内容](https://neteasecloudmusicapi.vercel.app/#/?id=私信内容) + +说明 : 登录后调用此接口 , 可获取私信内容 + +**必选参数 :** `uid` : 用户 id + +**可选参数 :** `limit` : 返回数量 , 默认为 30 + +`before` : 分页参数,取上一页最后一项的 `time` 获取下一页数据 + +**接口地址 :** `/msg/private/history` + +**调用例子 :** `/msg/private/history?uid=9003` (云音乐小秘书) + +### [通知 - 评论](https://neteasecloudmusicapi.vercel.app/#/?id=通知-评论) + +说明 : 登录后调用此接口 ,可获取评论 + +**必选参数 :** `uid`: 用户 的 id,只能和登录账号的 id 一致 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +`before` : 分页参数,取上一页最后一个歌单的 `updateTime` 获取下一页数据 + +**接口地址 :** `/msg/comments` + +**调用例子 :** `/msg/comments?uid=32953014` + +### [通知 - @我](https://neteasecloudmusicapi.vercel.app/#/?id=通知-我) + +说明 : 登录后调用此接口 ,可获取@我数据 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +`offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 + +**接口地址 :** `/msg/forwards` + +**调用例子 :** `/msg/forwards?limit=3` + +### [通知 - 通知](https://neteasecloudmusicapi.vercel.app/#/?id=通知-通知) + +说明 : 登录后调用此接口 ,可获取通知 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +`lasttime` : 返回数据的 `time` ,默认-1,传入上一次返回结果的 time,将会返回下一页的数据 + +**接口地址 :** `/msg/notices` + +**调用例子 :** `/msg/notices?limit=3` + +### [设置](https://neteasecloudmusicapi.vercel.app/#/?id=设置) + +说明 : 登录后调用此接口 ,可获取用户设置 + +**接口地址 :** `/setting` + +**调用例子 :** `/setting` + +### [数字专辑-新碟上架](https://neteasecloudmusicapi.vercel.app/#/?id=数字专辑-新碟上架) + +说明 : 调用此接口 ,可获取数字专辑-新碟上架 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +``` +offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 +**接口地址 :** `/album/list +``` + +**调用例子 :** `/album/list?limit=10` + +### [数字专辑&数字单曲-榜单](https://neteasecloudmusicapi.vercel.app/#/?id=数字专辑amp数字单曲-榜单) + +说明 : 调用此接口 ,可获取数字专辑&数字单曲-榜单 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +`offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 + +`albumType` : 为数字专辑,1 为数字单曲 + +`type` : daily:日榜,week:周榜,year:年榜,total:总榜 + +**接口地址 :** `/album_songsaleboard` + +**调用例子 :** `/album/songsaleboard?type=year&year=2020&albumType=0` + +### [数字专辑-语种风格馆](https://neteasecloudmusicapi.vercel.app/#/?id=数字专辑-语种风格馆) + +说明 : 调用此接口 ,可获取语种风格馆数字专辑列表 + +**可选参数 :** + +`limit` : 返回数量 , 默认为 30 + +`offset` : 偏移数量,用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 + +`area` 地区 Z_H:华语,E_A:欧美,KR:韩国,JP:日本 + +**接口地址 :** `/album/list/style` + +**调用例子 :** `/album/list/style?area=Z_H&offset=2` + +### [数字专辑详情](https://neteasecloudmusicapi.vercel.app/#/?id=数字专辑详情) + +说明 : 调用此接口 ,传入数字专辑 id 可获取数字专辑详情(和歌单详情有差异) + +**接口地址 :** `/album/detail` + +**调用例子 :** `/album/detail?id=84547195` + +### [我的数字专辑](https://neteasecloudmusicapi.vercel.app/#/?id=我的数字专辑) + +说明 : 登录后调用此接口 ,可获取我的数字专辑 + +**接口地址 :** `/digitalAlbum/purchased` + +**调用例子 :** `/digitalAlbum/purchased?limit=10` + +### [购买数字专辑](https://neteasecloudmusicapi.vercel.app/#/?id=购买数字专辑) + +说明 : 登录后调用此接口 ,可获取购买数字专辑的地址,把地址生成二维码后,可扫描购买专辑 + +**必选参数 :** + +`id` : 专辑的 id + +`payment` : 支付方式, 0 为支付宝 3 为微信 + +`quantity` : 购买的数量 + +**接口地址 :** `/digitalAlbum/ordering` + +**调用例子 :** `/digitalAlbum/ordering?id=86286082&payment=3&quantity=1` + +### [音乐日历](https://neteasecloudmusicapi.vercel.app/#/?id=音乐日历) + +说明 : 登录后调用此接口,传入开始和结束时间,可获取音乐日历 + +**接口地址 :** `/calendar` + +**调用例子 :** `/calendar?startTime=1606752000000&endTime=1609430399999` + +### [云贝](https://neteasecloudmusicapi.vercel.app/#/?id=云贝) + +说明 : 登录后调用此接口可获取云贝签到信息(连续签到天数,第二天全部可获得的云贝) + +**接口地址 :** `/yunbei` + +**调用例子 :** `/yunbei` + +### [云贝今日签到信息](https://neteasecloudmusicapi.vercel.app/#/?id=云贝今日签到信息) + +说明 : 登录后调用此接口可获取云贝今日签到信息(今日签到获取的云贝数) + +**接口地址 :** `/yunbei/today` + +**调用例子 :** `/yunbei/today` + +### [云贝签到](https://neteasecloudmusicapi.vercel.app/#/?id=云贝签到) + +说明 : 登录后调用此接口可进行云贝签到 + +**接口地址 :** `/yunbei/sign` + +**调用例子 :** `/yunbei/sign` + +### [云贝账户信息](https://neteasecloudmusicapi.vercel.app/#/?id=云贝账户信息) + +说明 :登录后调用此接口可获取云贝账户信息(账户云贝数) + +**接口地址 :** `/yunbei/info` + +**调用例子 :** `/yunbei/info` + +### [云贝所有任务](https://neteasecloudmusicapi.vercel.app/#/?id=云贝所有任务) + +说明 :登录后调用此接口可获取云贝所有任务 + +**接口地址 :** `/yunbei/tasks` + +**调用例子 :** `/yunbei/tasks` + +### [云贝 todo 任务](https://neteasecloudmusicapi.vercel.app/#/?id=云贝-todo-任务) + +说明 :登录后调用此接口可获取云贝 todo 任务 + +**接口地址 :** `/yunbei/tasks/todo` + +**调用例子 :** `/yunbei/tasks/todo` + +### [云贝完成任务](https://neteasecloudmusicapi.vercel.app/#/?id=云贝完成任务) + +**必选参数 :** + +`userTaskId` : 任务 id + +**可选参数 :** + +`depositCode`: 任务 depositCode + +**接口地址 :** `/yunbei/task/finish` + +**调用例子 :** `/yunbei/task/finish?userTaskId=5146243240&depositCode=0` + +### [云贝收入](https://neteasecloudmusicapi.vercel.app/#/?id=云贝收入) + +说明 :登录后调用此接口可获取云贝收入 + +**可选参数 :** `limit`: 取出评论数量 , 默认为 10 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*10, 其中 10 为 limit 的值 + +**接口地址 :** `/yunbei/tasks/receipt` + +**调用例子 :** `/yunbei/tasks/receipt?limit=1` + +### [云贝支出](https://neteasecloudmusicapi.vercel.app/#/?id=云贝支出) + +说明 :登录后调用此接口可获取云贝支出 + +**可选参数 :** `limit`: 取出评论数量 , 默认为 10 + +``` +offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*10, 其中 10 为 limit 的值 +**接口地址 :** `/yunbei/tasks/expense +``` + +**调用例子 :** `/yunbei/tasks/expense?limit=1` + +### [关注歌手新歌](https://neteasecloudmusicapi.vercel.app/#/?id=关注歌手新歌) + +说明 :登录后调用此接口可获取关注歌手新歌 + +**可选参数 :** `limit`: 取出评论数量 , 默认为 20 + +`before`: 上一页数据返回的 publishTime 的数据 + +**接口地址 :** `/artist/new/song` + +**调用例子 :** `/artist/new/song?limit=1` `/artist/new/song?limit=1&before=1602777625000` + +### [关注歌手新 MV](https://neteasecloudmusicapi.vercel.app/#/?id=关注歌手新-mv) + +说明 :登录后调用此接口可获取关注歌手新 MV + +**可选参数 :** `limit`: 取出评论数量 , 默认为 20 + +`before`: 上一页数据返回的 publishTime 的数据 + +**接口地址 :** `/artist/new/mv` + +**调用例子 :** `/artist/new/mv?limit=1` `/artist/new/mv?limit=1&before=1602777625000` + +### [一起听状态](https://neteasecloudmusicapi.vercel.app/#/?id=一起听状态) + +说明 :登录后调用此接口可获取一起听状态 + +**接口地址 :** `/listen/together/status` + +**调用例子 :** `/listen/together/status` + +### [batch 批量请求接口](https://neteasecloudmusicapi.vercel.app/#/?id=batch-批量请求接口) + +说明 : 登录后调用此接口 ,传入接口和对应原始参数(原始参数非文档里写的参数,需参考源码),可批量请求接口 + +**接口地址 :** `/batch` + +**调用例子 :** 使用 GET 方式:`/batch?/api/v2/banner/get={"clientType":"pc"}` 使用 POST 方式传入参数:`{ "/api/v2/banner/get": {"clientType":"pc"} }` + +### [云贝推歌](https://neteasecloudmusicapi.vercel.app/#/?id=云贝推歌) + +说明 : 登录后调用此接口 , 传入歌曲 id, 可以进行云贝推歌 + +**必选参数 :** `id` : 歌曲 id + +**可选参数 :** `reason` : 推歌理由 + +`yunbeiNum`: 云贝数量,默认10 + +**接口地址 :** `/yunbei/rcmd/song` + +**调用例子 :** `/yunbei/rcmd/song?id=65528` `/yunbei/rcmd/song?id=65528&reason=人间好声音推荐给你听` + +### [云贝推歌历史记录](https://neteasecloudmusicapi.vercel.app/#/?id=云贝推歌历史记录) + +说明 : 登录后调用此接口 , 可以获得云贝推歌历史记录 + +**可选参数 :** `size` : 返回数量 , 默认为 20 + +`cursor` : 返回数据的 cursor, 默认为 '' , 传入上一次返回结果的 cursor,将会返回下一页的数据 + +**接口地址 :** `/yunbei/rcmd/song/history` + +**调用例子 :** `/yunbei/rcmd/song/history?size=10` + +### [已购单曲](https://neteasecloudmusicapi.vercel.app/#/?id=已购单曲) + +说明 :登录后调用此接口可获取已购买的单曲 + +**可选参数 :** `limit`: 取出评论数量 , 默认为 20 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*10, 其中 10 为 limit 的值 + +**接口地址 :** `/song/purchased` + +**调用例子 :** `/song/purchased?limit=10` + +### [获取 mlog 播放地址](https://neteasecloudmusicapi.vercel.app/#/?id=获取-mlog-播放地址) + +说明 : 调用此接口 , 传入 mlog id, 可获取 mlog 播放地址 + +**必选参数 :** `id` : mlog id + +**可选参数 :** `res`: 分辨率 , 默认为 1080 + +**接口地址 :** `/mlog/url` + +**调用例子 :** `/mlog/url?id=a1qOVPTWKS1ZrK8` + +### [将 mlog id 转为视频 id](https://neteasecloudmusicapi.vercel.app/#/?id=将-mlog-id-转为视频-id) + +说明 : 调用此接口 , 传入 mlog id, 可获取 video id,然后通过`video/url` 获取播放地址 + +**必选参数 :** `id` : mlog id + +**接口地址 :** `/mlog/to/video` + +**调用例子 :** `/mlog/to/video?id=a1qOVPTWKS1ZrK8` + +### [vip 成长值](https://neteasecloudmusicapi.vercel.app/#/?id=vip-成长值) + +说明 : 登陆后调用此接口 , 可获取当前会员成长值 + +**接口地址 :** `/vip/growthpoint` + +**调用例子 :** `/vip/growthpoint` + +### [vip 成长值获取记录](https://neteasecloudmusicapi.vercel.app/#/?id=vip-成长值获取记录) + +说明 :登录后调用此接口可获取会员成长值领取记录 + +**可选参数 :** `limit`: 取出评论数量 , 默认为 20 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*10, 其中 10 为 limit 的值 + +**接口地址 :** `/vip/growthpoint/details` + +**调用例子 :** `/vip/growthpoint/details?limit=10` + +### [vip 任务](https://neteasecloudmusicapi.vercel.app/#/?id=vip-任务) + +说明 : 登陆后调用此接口 , 可获取会员任务 + +**接口地址 :** `/vip/tasks` + +**调用例子 :** `/vip/tasks` + +### [领取 vip 成长值](https://neteasecloudmusicapi.vercel.app/#/?id=领取-vip-成长值) + +说明 : 登陆后调用此接口 , 可获取已完成的会员任务的成长值奖励 + +**必选参数 :** `ids` : 通过`/vip/tasks`获取到的`unGetIds` + +**接口地址 :** `/vip/growthpoint/get` + +**调用例子 :** `/vip/growthpoint/get?ids=7043206830_7` `/vip/growthpoint/get?ids=8613118351_1,8607552957_1` + +### [歌手粉丝](https://neteasecloudmusicapi.vercel.app/#/?id=歌手粉丝) + +说明 : 调用此接口 , 传入歌手 id, 可获取歌手粉丝 **必选参数 :** `id` : 歌手 id + +**接口地址 :** `/artist/fans` + +**调用例子 :** `/artist/fans?id=2116&limit=10&offset=0` + +### [歌手粉丝数量](https://neteasecloudmusicapi.vercel.app/#/?id=歌手粉丝数量) + +说明 : 调用此接口 , 传入歌手 id, 可获取歌手粉丝数量 + +**必选参数 :** `id` : 歌手 id + +**可选参数 :** `limit`: 取出粉丝数量 , 默认为 20 + +`offset`: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*10, 其中 10 为 limit 的值 + +**接口地址 :** `/artist/follow/count` + +**调用例子 :** `/artist/follow/count?id=2116` + +### [数字专辑详情](https://neteasecloudmusicapi.vercel.app/#/?id=数字专辑详情-1) + +说明 : 调用此接口 , 传入专辑 id, 可获取数字专辑信息 + +**必选参数 :** `id` : 专辑 id + +**接口地址 :** `/digitalAlbum/detail` + +**调用例子 :** `/digitalAlbum/detail?id=120605500` + +### [数字专辑销量](https://neteasecloudmusicapi.vercel.app/#/?id=数字专辑销量) + +说明 : 调用此接口 , 传入专辑 id, 可获取数字专辑销量 + +**必选参数 :** `ids` : 专辑 id, 支持多个,用`,`隔开 + +**接口地址 :** `/digitalAlbum/sales` + +**调用例子 :** `/digitalAlbum/sales?ids=120605500` `/digitalAlbum/sales?ids=120605500,125080528` + +### [音乐人数据概况](https://neteasecloudmusicapi.vercel.app/#/?id=音乐人数据概况) + +说明 : 音乐人登录后调用此接口 , 可获取统计数据概况 + +**接口地址 :** `/musician/data/overview` + +**调用例子 :** `/musician/data/overview` + +### [音乐人播放趋势](https://neteasecloudmusicapi.vercel.app/#/?id=音乐人播放趋势) + +说明 : 音乐人登录后调用此接口 , 可获取歌曲播放趋势 + +**必选参数 :** `startTime` : 开始时间 + +`endTime` : 结束时间 + +**接口地址 :** `/musician/play/trend` + +**调用例子 :** `/musician/play/trend?startTime=2021-05-24&endTime=2021-05-30` + +### [音乐人任务](https://neteasecloudmusicapi.vercel.app/#/?id=音乐人任务) + +说明 : 音乐人登录后调用此接口 , 可获取音乐人任务。返回的数据中`status`字段为任务状态,0 表示任务未开始,10 表示任务正在进行中,20 表示任务完成,但未领取云豆,100 表示任务完成,并且已经领取了相应的云豆(貌似只能获取到做过的任务了) + +**接口地址 :** `/musician/tasks` + +**调用例子 :** `/musician/tasks` + +### [音乐人任务(新)](https://neteasecloudmusicapi.vercel.app/#/?id=音乐人任务新) + +说明 : 音乐人登录后调用此接口 , 可获取音乐人任务。返回的数据中`status`字段为任务状态,0 表示任务未开始,10 表示任务正在进行中,20 表示任务完成,但未领取云豆,100 表示任务完成,并且已经领取了相应的云豆 + +**接口地址 :** `/musician/tasks/new` + +**调用例子 :** `/musician/tasks/new` + +### [账号云豆数](https://neteasecloudmusicapi.vercel.app/#/?id=账号云豆数) + +说明 : 音乐人登录后调用此接口 , 可获取账号云豆数 + +**接口地址 :** `/musician/cloudbean` + +**调用例子 :** `/musician/cloudbean` + +### [领取云豆](https://neteasecloudmusicapi.vercel.app/#/?id=领取云豆) + +说明 : 音乐人登录后调用此接口 , 可领取已完成的音乐人任务的云豆奖励 + +**必选参数 :** `id` : 任务 id,通过`/musician/tasks`获取到的`userMissionId`即为任务 id + +`period` : 通过`/musician/tasks`获取 + +**接口地址 :** `/musician/cloudbean/obtain` + +**调用例子 :** `/musician/cloudbean/obtain?id=7036416928&period=1` + +### [获取 VIP 信息](https://neteasecloudmusicapi.vercel.app/#/?id=获取-vip-信息) + +说明: 登录后调用此接口,可获取当前 VIP 信息。 + +**接口地址 :** `/vip/info` + +**调用例子 :** `/vip/info` + +### [音乐人签到](https://neteasecloudmusicapi.vercel.app/#/?id=音乐人签到) + +说明: 音乐人登录后调用此接口,可以完成“登录音乐人中心”任务,然后通过`/musician/cloudbean/obtain`接口可以领取相应的云豆。 + +**接口地址 :** `/musician/sign` + +**调用例子 :** `/musician/sign` + +### [歌曲相关视频](https://neteasecloudmusicapi.vercel.app/#/?id=歌曲相关视频) + +说明: 可以调用此接口获取歌曲相关视频 (区别于 MV), 有些歌曲没有 MV 但是有用户上传的与此歌曲相关的 Mlog。 此功能仅在 网易云音乐 APP 上存在。 + +请注意:此接口偶尔会在相关视频后返回不相关视频,请合理使用。 + +**必选参数 :** `songid` : 歌曲 ID + +**可选参数 :** `mvid` : 如果定义,此 mvid 对应的 MV 将会作为第一个返回。 `limit` : 取出的 Mlog 数量, 不包含第一个 mvid + +**接口地址 :** `/mlog/music/rcmd` + +### [公开隐私歌单](https://neteasecloudmusicapi.vercel.app/#/?id=公开隐私歌单) + +说明: 可以调用此接口将当前用户的隐私歌单公开。 + +**必选参数 :** `id` : 歌单 ID + +**接口地址 :** `/playlist/privacy` + +### [获取客户端歌曲下载 url](https://neteasecloudmusicapi.vercel.app/#/?id=获取客户端歌曲下载-url) + +说明 : 使用 `/song/url` 接口获取的是歌曲试听 url, 但存在部分歌曲在非 VIP 账号上可以下载无损音质而不能试听无损音质, 使用此接口可使非 VIP 账号获取这些歌曲的无损音频 + +**必选参数 :** `id` : 音乐 id (仅支持单首歌曲) + +**可选参数 :** `br` : 码率, 默认设置了 999000 即最大码率, 如果要 320k 则可设置为 320000, 其他类推 + +**接口地址 :** `/song/download/url` + +### [获取歌手视频](https://neteasecloudmusicapi.vercel.app/#/?id=获取歌手视频) + +说明 : 调用此接口 , 传入歌手 id, 可获得歌手视频 + +**必选参数 :** `id` : 歌手 id + +**可选参数 :** `size` : 返回数量 , 默认为 10 + +`cursor` : 返回数据的 cursor, 默认为 0 , 传入上一次返回结果的 cursor,将会返回下一页的数据 + +`order` : 排序方法, 0 表示按时间排序, 1 表示按热度排序, 默认为 0 + +**接口地址 :** `/artist/video` + +**调用例子 :** `/artist/video?id=2116` + +### [最近播放-歌曲](https://neteasecloudmusicapi.vercel.app/#/?id=最近播放-歌曲) + +说明 : 调用此接口 , 可获得最近播放-歌曲 + +**可选参数 :** `limit` : 返回数量 , 默认为 100 + +**接口地址 :** `/record/recent/song` + +**调用例子 :** `/record/recent/song?limit=1` + +### [最近播放-视频](https://neteasecloudmusicapi.vercel.app/#/?id=最近播放-视频) + +说明 : 调用此接口 , 可获得最近播放-视频 + +**可选参数 :** `limit` : 返回数量 , 默认为 100 + +**接口地址 :** `/record/recent/video` + +**调用例子 :** `/record/recent/video?limit=1` + +### [最近播放-声音](https://neteasecloudmusicapi.vercel.app/#/?id=最近播放-声音) + +说明 : 调用此接口 , 可获得最近播放-声音 + +**可选参数 :** `limit` : 返回数量 , 默认为 100 + +**接口地址 :** `/record/recent/voice` + +**调用例子 :** `/record/recent/voice?limit=1` + +### [最近播放-歌单](https://neteasecloudmusicapi.vercel.app/#/?id=最近播放-歌单) + +说明 : 调用此接口 , 可获得最近播放-歌单 + +**可选参数 :** `limit` : 返回数量 , 默认为 100 + +**接口地址 :** `/record/recent/playlist` + +**调用例子 :** `/record/recent/playlist?limit=1` + +### [最近播放-专辑](https://neteasecloudmusicapi.vercel.app/#/?id=最近播放-专辑) + +说明 : 调用此接口 , 可获得最近播放-专辑 + +**可选参数 :** `limit` : 返回数量 , 默认为 100 + +**接口地址 :** `/record/recent/album` + +**调用例子 :** `/record/recent/album?limit=1` + +### [最近播放-播客](https://neteasecloudmusicapi.vercel.app/#/?id=最近播放-播客) + +说明 : 调用此接口 , 可获得最近播放-播客 + +**可选参数 :** `limit` : 返回数量 , 默认为 100 + +**接口地址 :** `/record/recent/dj` + +**调用例子 :** `/record/recent/dj?limit=1` + +### [签到进度](https://neteasecloudmusicapi.vercel.app/#/?id=签到进度) + +说明 : 调用此接口 , 可获得签到进度 + +**可选参数 :** `moduleId` : 模块 id,默认为 '1207signin-1207signin' + +**接口地址 :** `/signin/progress` + +**调用例子 :** `/signin/progress?moduleId=1207signin-1207signin` + +### [内部版本接口](https://neteasecloudmusicapi.vercel.app/#/?id=内部版本接口) + +说明 : 调用此接口 , 可获得内部版本号(从package.json读取) + +**接口地址 :** `/inner/version` + +**调用例子 :** `/inner/version` + +### [黑胶时光机](https://neteasecloudmusicapi.vercel.app/#/?id=黑胶时光机) + +说明 : 调用此接口 , 可获得黑胶时光机数据 + +**可选参数 :** `startTime` : 开始时间 `endTime` : 结束时间 `limit` : 返回数量 , 默认为 60 + +**接口地址 :** `/vip/timemachine` + +**调用例子 :** `/vip/timemachine` `/vip/timemachine?startTime=1638288000000&endTime=1640966399999&limit=10`(2021年12月) `/vip/timemachine?startTime=1609430400&endTime=1640966399999&limit=60`(2021年) \ No newline at end of file diff --git a/docs/front-end/04-ES6/17-promise.md b/docs/front-end/04-ES6/17-promise.md index 639f9e48..e6234559 100644 --- a/docs/front-end/04-ES6/17-promise.md +++ b/docs/front-end/04-ES6/17-promise.md @@ -430,7 +430,7 @@ Promise.allsettled() 返回一个 promise 对象, 状态一直都是成功(除 ```javascript 1. 参数是可遍历对象,返回值一定是个成功状态的 promise 对象,所有的参数的成员都完成,返回值状态才改变, PromiseResult是一个数组,数组中每个成员与参数每个成员按照顺序对应 -2. 数组的每个成员状态如果成功 PromiseResult[元素]是{status value}, 如果对应的是失败的 {status,reason} +2. 返回值是一个数组,数组的每个成员是一个对象,对象的结构由{status:'',value:''}组成,成员状态如果成功 PromiseResult[元素]是{status value}, 如果成员的状态是失败则:PromiseResult[元素]是{status,reason} 3. 如果参数不是可遍历对象,返回失败状态的 promise 对象 ``` @@ -537,7 +537,7 @@ async 函数返回一个 Promise 对象, Promise 对象的状态取决于 asyn 1. 情况一,没有reutrn, async函数返回的Promise对象改为成功状态,PromiseResult是undefined 2. 情况二:return 非Promise类型的对象或原始类型数据,async函数返回的Promise对象改为成功状态,PromiseResult 是 return 的值 3. 情况三:return Promise对象, async函数返回的Promise对象就是 return 的 Promise对象 -4. 情况四:抛出异常, async函数返回的Promise对象,状态改为失败,PromiseResult是错误对象 +4. 情况四:抛出异常, async函数返回的Promise对象,状态改为失败,PromiseResult是错误对象 ``` ## await 表达式 @@ -553,10 +553,51 @@ async 函数返回一个 Promise 对象, Promise 对象的状态取决于 asyn ```javascript 1. await 右侧的表达式是 非Promsie, 右侧表达式的值就是 await 表达式的值 -2. await 右侧的表达式是成功状态 Promise 对象,状态改变之后,await 表达式才能取到值,值是 Promise 对象的 PromiseResult -3. await 右侧的表达式是失败状态的 Promise 对象, 抛出异常, await 表达式取不到值 +2. await 右侧的表达式是成功状态 Promise 对象,状态改变之后,await 表达式才能取到值,值是 Promise 对象的PromiseResult +3. await 右侧的表达式是失败状态的 Promise 对象, 抛出异常, await 表达式取不到值,中断链式调用 +4. await 相当于then链式调用,上一个不完成(状态不改变),下一个不开始,要的就是等待。 +5. await 后边的语句就相当于在promise对象的then的回调中。 ``` +```javascript + + async function fn1() { + console.log(1); + await fn2(); + console.log(2); // 相当于在promise对象的then的回调里 微任务,立即进入异步队列中等待,下一轮执行。 + } + + async function fn2() { + console.log(3); + } + + console.log(4); + + setTimeout(function () { + console.log(5); + }, 0) + + fn1(); + + new Promise(function (resolve) { + console.log(6); + resolve(); + }).then(function () { + console.log(7); + }); + + console.log(8); + + +``` + + + ### ③ await 处理 rejected 状态的 Promise 对象 ```javascript @@ -603,8 +644,11 @@ async 与 await 实现链式调用 1. JS 中用来存储待执行回调函数的队列包含2个不同特定的列队 -2. 宏列队:用来保存待执行的宏任务(回调),比如:定时器回调、DOM事件回调、ajax回调。 -3. 微列队:用来保存待执行的微任务(回调),比如:Promise 的回调、MutationObserver 的回调。 +2. 宏队列:用来保存待执行的宏任务(回调),比如:定时器回调、DOM事件回调、ajax回调。 +3. 微队列:用来保存待执行的微任务(回调),比如:Promise 的回调、MutationObserver 的回调。 4. JS 执行时会区别这2个队列: - (1) JS 引擎首先必须先执行所有的初始化同步任务代码。 - - (2) 每次准备取出第一个宏任务执行前, 都要将所有的微任务一个一个取出来执行。 \ No newline at end of file + - (2) 每次准备取出第一个宏任务执行前, 都要将所有的微任务一个一个取出来执行。 + +![image-20240506142439784](000-images/17-promise/image-20240506142439784.png) + diff --git "a/docs/front-end/04-ES6/18-promise\350\207\252\345\256\232\344\271\211.md" "b/docs/front-end/04-ES6/18-promise\350\207\252\345\256\232\344\271\211.md" new file mode 100644 index 00000000..77840f51 --- /dev/null +++ "b/docs/front-end/04-ES6/18-promise\350\207\252\345\256\232\344\271\211.md" @@ -0,0 +1,1471 @@ +# 自定义 Promise + +## 1 基本结构搭建 + +```JavaScript +实例的方法:(设置实例的原型上) +then() +catch() +finally() + +类本身的方法: +resolve() +reject() +all() +race() +allSettled + +console的方法 +console.log() +console.dir() +``` + +```js +(window => { + class Promise { + + /** + * 构造器方法,实例化的时候自动执行 + */ + constructor() { + + } + + /** + * 给实例传递成功和失败的回调函数,该方法会添加到实例的原型上 + */ + then() { + + } + + /** + * 给实例传递失败的回调函数,该方法会添加到实例的原型上 + */ + catch() { + + } + + + /** + * 根据参数返回新的Promise实例,该方法添加到类本身(静态方法) + */ + static resolve() { + + } + + /** + * 返回新的失败状态的Promise实例,该方法添加到类本身(静态方法) + */ + static reject() { + + } + + /** + * 当传入的所有Promise实例都完成才返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static all() { + + } + + /** + * 传入的多个Promise实例只要一个先完成就返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static race() { + + } + + + } + + window.Promise = Promise; +})(window || global); +``` + + + +## 2 实例化传入执行器函数 + +```js +// 实例化 Promise +const p1 = new Promise((resolve, reject) => { + console.log(resolve); + console.log(reject); +}); +``` + +```js +(window => { + class Promise { + + /** + * 构造器方法,实例化的时候自动执行 + * @param {Function} exector 执行器函数,实例化的时候自动执行 + */ + constructor(exector) { + // 执行该函数,可将实例状态更改为成功 + const changeResolved = () => { + + }; + + // 执行该函数,可将实例状态更改为成功 + const changeRejected = () => { + + }; + + // 调用执行器函数 + exector(changeResolved, changeRejected); + } + + /** + * 给实例传递成功和失败的回调函数,该方法会添加到实例的原型上 + */ + then() { + + } + + /** + * 给实例传递失败的回调函数,该方法会添加到实例的原型上 + */ + catch() { + + } + + + /** + * 根据参数返回新的Promise实例,该方法添加到类本身(静态方法) + */ + static resolve() { + + } + + /** + * 返回新的失败状态的Promise实例,该方法添加到类本身(静态方法) + */ + static reject() { + + } + + /** + * 当传入的所有Promise实例都完成才返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static all() { + + } + + /** + * 传入的多个Promise实例只要一个先完成就返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static race() { + + } + + + } + + window.Promise = Promise; +})(window || global); +``` + + + + + +## 3 更该状态的三种方式 + +```javascript +1. 执行器函数中调用第一个参数,修改为成功状态 +2. 执行器函数中调用第二个参数,修改为失败状态 +3. 执行器函数中有异常,修改为失败状态,result就是错误对象 +``` + +```javascript +执行器函数 : + (resolve, reject) => { + console.log(resolve); + console.log(reject); + } +``` + + + +```js +(window => { + class Promise { + // 设置私有属性,记录实例的状态和结果 + #state = 'pendding'; + #result; + + /** + * 构造器方法,实例化的时候自动执行 + * @param {Function} exector 执行器函数,实例化的时候自动执行 + */ + constructor(exector) { + // 执行该函数,可将实例状态更改为成功 + const changeResolved = value => { + // 修改状态和结果 + this.#state = 'fulfilled'; + this.#result = value; + }; + + // 执行该函数,可将实例状态更改为成功 + const changeRejected = reason => { + // 修改状态和结果 + this.#state = 'rejected'; + this.#result = reason; + }; + + // 调用执行器函数, 如果执行器函数中有异常,修改状态为失败 + try { + exector(changeResolved, changeRejected); + } catch (error) { + // 修改状态和结果 + this.#state = 'rejected'; + this.#result = error; + } + } + + /** + * 给实例传递成功和失败的回调函数,该方法会添加到实例的原型上 + */ + then() { + + } + + /** + * 给实例传递失败的回调函数,该方法会添加到实例的原型上 + */ + catch() { + + } + + + /** + * 根据参数返回新的Promise实例,该方法添加到类本身(静态方法) + */ + static resolve() { + + } + + /** + * 返回新的失败状态的Promise实例,该方法添加到类本身(静态方法) + */ + static reject() { + + } + + /** + * 当传入的所有Promise实例都完成才返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static all() { + + } + + /** + * 传入的多个Promise实例只要一个先完成就返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static race() { + + } + + + } + + window.Promise = Promise; +})(window || global); +``` + + + + + +## 4 状态只能更改一次 + +```js +(window => { + class Promise { + // 设置私有属性,记录实例的状态和结果 + #state = 'pendding'; + #result; + + /** + * 构造器方法,实例化的时候自动执行 + * @param {Function} exector 执行器函数,实例化的时候自动执行 + */ + constructor(exector) { + // 执行该函数,可将实例状态更改为成功 + const changeResolved = value => { + // 如果状态已经更改,结束该函数 + if (this.#state !== 'pendding') { + return; + } + // 修改状态和结果 + this.#state = 'fulfilled'; + this.#result = value; + }; + + // 执行该函数,可将实例状态更改为成功 + const changeRejected = reason => { + // 如果状态已经更改,结束该函数 + if (this.#state !== 'pendding') { + return; + } + // 修改状态和结果 + this.#state = 'rejected'; + this.#result = reason; + }; + + // 调用执行器函数, 如果执行器函数中有异常,修改状态为失败 + try { + exector(changeResolved, changeRejected); + } catch (error) { + // 更改为失败状态,错误对象作为结果 + changeRejected(error); + } + } + + /** + * 给实例传递成功和失败的回调函数,该方法会添加到实例的原型上 + */ + then() { + + } + + /** + * 给实例传递失败的回调函数,该方法会添加到实例的原型上 + */ + catch() { + + } + + + /** + * 根据参数返回新的Promise实例,该方法添加到类本身(静态方法) + */ + static resolve() { + + } + + /** + * 返回新的失败状态的Promise实例,该方法添加到类本身(静态方法) + */ + static reject() { + + } + + /** + * 当传入的所有Promise实例都完成才返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static all() { + + } + + /** + * 传入的多个Promise实例只要一个先完成就返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static race() { + + } + + + } + + window.Promise = Promise; +})(window || global); +``` + + + +## 5 实现 then 方法:传入回调并异步执行 + +```js +1. then() 负责传入两个回调函数 +2. then() 的内部根据状态执行两个参数(传入的两个回调)的一个,要异步执行 +3. then() 执行的 时机1 回调传入的时候,状态已经发生改变 + 时机2 回调传入的时候,状态未发生改变,在回调中先存下来,到执行的时候再执行 +``` + +```js +(window => { + class Promise { + // 设置私有属性,记录实例的状态和结果 + #state = 'pendding'; + #result; + + /** + * 构造器方法,实例化的时候自动执行 + * @param {Function} exector 执行器函数,实例化的时候自动执行 + */ + constructor(exector) { + // 执行该函数,可将实例状态更改为成功 + const changeResolved = value => { + // 如果状态已经更改,结束该函数 + if (this.#state !== 'pendding') { + return; + } + // 修改状态和结果 + this.#state = 'fulfilled'; + this.#result = value; + }; + + // 执行该函数,可将实例状态更改为成功 + const changeRejected = reason => { + // 如果状态已经更改,结束该函数 + if (this.#state !== 'pendding') { + return; + } + // 修改状态和结果 + this.#state = 'rejected'; + this.#result = reason; + }; + + // 调用执行器函数, 如果执行器函数中有异常,修改状态为失败 + try { + exector(changeResolved, changeRejected); + } catch (error) { + // 更改为失败状态,错误对象作为结果 + changeRejected(error); + } + } + + /** + * 给实例传递成功和失败的回调函数,该方法会添加到实例的原型上 + */ + then(onResolved, onRejected) { + if (this.#state === 'fulfilled') { // 当传入回调函数是,实例的状态已经改为成功 + setTimeout(() => { + onResolved(this.#result); + }); + } else if (this.#state === 'rejected') { // 当传入回调函数是,实例的状态已经改为失败 + setTimeout(() => { + onRejected(this.#result); + }) + } + } + + /** + * 给实例传递失败的回调函数,该方法会添加到实例的原型上 + */ + catch() { + + } + + + /** + * 根据参数返回新的Promise实例,该方法添加到类本身(静态方法) + */ + static resolve() { + + } + + /** + * 返回新的失败状态的Promise实例,该方法添加到类本身(静态方法) + */ + static reject() { + + } + + /** + * 当传入的所有Promise实例都完成才返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static all() { + + } + + /** + * 传入的多个Promise实例只要一个先完成就返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static race() { + + } + + + } + + window.Promise = Promise; +})(window || global); +``` + +**传入调用过程1** + +执行器函数 传给class类中的构造器exector作为形参 + +![image-20240506170947017](000-images/18-promise自定义/image-20240506170947017.png) + +**传入调用过程2** + +构造器函数调用 传来的执行器函数,并且使用两个函数作为参数,(一个成功的函数,一个失败的函数) + +![image-20240506171354717](000-images/18-promise自定义/image-20240506171354717.png) + +**传入调用过程3** + +执行器函数 调用成功的函数设置成功状态 + +![image-20240506173012063](000-images/18-promise自定义/image-20240506173012063.png) + + + +## 6 实现 then 方法:状态改变才能执行回调 + +```javascript +1. 调用 then() 可以传入两个回调函数 +2. 如果调用 then 的时候状态已经改变,根据状态选择其中一个回调函数,执行调用 +3. 如果调用 then 的时候状态还未改变,将两个回调函数存下来,当执行改变状态函数的时候,再调用当初存下来的回调 +``` + +```js +(window => { + class Promise { + // 设置私有属性,记录实例的状态和结果 + #state = 'pendding'; + #result; + // 设置私有属性,保存then传入的回调函数 + #callbackObj = {}; + + /** + * 构造器方法,实例化的时候自动执行 + * @param {Function} exector 执行器函数,实例化的时候自动执行 + */ + constructor(exector) { + // 执行该函数,可将实例状态更改为成功 + const changeResolved = value => { + // 如果状态已经更改,结束该函数 + if (this.#state !== 'pendding') { + return; + } + // 修改状态和结果 + this.#state = 'fulfilled'; + this.#result = value; + // 如果这个时候 then() 已经将成功的回调传入,直接调用 + this.#callbackObj.onResolved?.(value); + // if (this.#callbackObj.onResolved) { + // this.#callbackObj.onResolved(); + // } + }; + + // 执行该函数,可将实例状态更改为成功 + const changeRejected = reason => { + // 如果状态已经更改,结束该函数 + if (this.#state !== 'pendding') { + return; + } + // 修改状态和结果 + this.#state = 'rejected'; + this.#result = reason; + // 如果这个时候 then() 已经将失败的回调传入,直接调用 + this.#callbackObj.onRejected?.(reason); + }; + + // 调用执行器函数, 如果执行器函数中有异常,修改状态为失败 + try { + exector(changeResolved, changeRejected); + } catch (error) { + // 更改为失败状态,错误对象作为结果 + changeRejected(error); + } + } + + /** + * 给实例传递成功和失败的回调函数,该方法会添加到实例的原型上 + */ + then(onResolved, onRejected) { + if (this.#state === 'fulfilled') { // 当传入回调函数时,实例的状态已经改为成功 + setTimeout(() => { + onResolved(this.#result); + }); + } else if (this.#state === 'rejected') { // 当传入回调函数时,实例的状态已经改为失败 + setTimeout(() => { + onRejected(this.#result); + }) + } else { // 当传入回调函数时,状态还未改变 + // 将两个回调函数保存到私有属性中 + this.#callbackObj = { + onResolved, + onRejected + } + } + } + + /** + * 给实例传递失败的回调函数,该方法会添加到实例的原型上 + */ + catch() { + + } + + + /** + * 根据参数返回新的Promise实例,该方法添加到类本身(静态方法) + */ + static resolve() { + + } + + /** + * 返回新的失败状态的Promise实例,该方法添加到类本身(静态方法) + */ + static reject() { + + } + + /** + * 当传入的所有Promise实例都完成才返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static all() { + + } + + /** + * 传入的多个Promise实例只要一个先完成就返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static race() { + + } + + + } + + window.Promise = Promise; +})(window || global); +``` + + + + + +## 7 实现 then 方法:可以设置多个回调 + +```js + // 实例化 Promise +const p1 = new Promise((resolve, reject) => { + // 修改为失败状态 + setTimeout(() => { + reject('Error'); + }, 2000) +}); + + +// 调用then() 方法,传入回调函数 +p1.then(val => { + console.log('成功1!', val); +}, reason => { + console.log('失败1!', reason); +}); + +p1.then(val => { + console.log('成功2!', val); +}, reason => { + console.log('失败2!', reason); +}); + +p1.then(val => { + console.log('成功3!', val); +}, reason => { + console.log('失败3!', reason); +}); + +``` + +```js +(window => { + class Promise { + // 设置私有属性,记录实例的状态和结果 + #state = 'pendding'; + #result; + // 设置私有属性,保存 then() 传入的回调函数 + #callbackList = []; + + /** + * 构造器方法,实例化的时候自动执行 + * @param {Function} exector 执行器函数,实例化的时候自动执行 + */ + constructor(exector) { + // 执行该函数,可将实例状态更改为成功 + const changeResolved = value => { + // 如果状态已经更改,结束该函数 + if (this.#state !== 'pendding') { + return; + } + // 修改状态和结果 + this.#state = 'fulfilled'; + this.#result = value; + // 遍历回调函数列表 + this.#callbackList.forEach(callback => { + callback.onResolved(value); + }); + + }; + + // 执行该函数,可将实例状态更改为成功 + const changeRejected = reason => { + // 如果状态已经更改,结束该函数 + if (this.#state !== 'pendding') { + return; + } + // 修改状态和结果 + this.#state = 'rejected'; + this.#result = reason; + // 遍历回调函数列表 + this.#callbackList.forEach(callback => { + callback.onRejected(reason); + }); + }; + + // 调用执行器函数, 如果执行器函数中有异常,修改状态为失败 + try { + exector(changeResolved, changeRejected); + } catch (error) { + // 更改为失败状态,错误对象作为结果 + changeRejected(error); + } + } + + /** + * 给实例传递成功和失败的回调函数,该方法会添加到实例的原型上 + */ + then(onResolved, onRejected) { + if (this.#state === 'fulfilled') { // 当传入回调函数时,实例的状态已经改为成功 + setTimeout(() => { + onResolved(this.#result); + }); + } else if (this.#state === 'rejected') { // 当传入回调函数时,实例的状态已经改为失败 + setTimeout(() => { + onRejected(this.#result); + }) + } else { // 当传入回调函数时,状态还未改变 + // 将两个回调函数保存到私有属性中 + this.#callbackList.push({ + onResolved, + onRejected + }); + } + } + + /** + * 给实例传递失败的回调函数,该方法会添加到实例的原型上 + */ + catch() { + + } + + + /** + * 根据参数返回新的Promise实例,该方法添加到类本身(静态方法) + */ + static resolve() { + + } + + /** + * 返回新的失败状态的Promise实例,该方法添加到类本身(静态方法) + */ + static reject() { + + } + + /** + * 当传入的所有Promise实例都完成才返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static all() { + + } + + /** + * 传入的多个Promise实例只要一个先完成就返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static race() { + + } + + + } + + window.Promise = Promise; +})(window || global); +``` + + + + + +## 8 实现 then 方法:返回新的 Promise 对象 实现链式调用 + +``` +1. then() 返回一个新的 Promsie 实例 +2. 返回的 Promsie 实例的状态,等到传入的回调函数执行过后才该 +``` + +```js +(window => { + class Promise { + // 设置私有属性,记录实例的状态和结果 + #state = 'pendding'; + #result; + // 设置私有属性,保存 then() 传入的回调函数 + #callbackList = []; + + /** + * 构造器方法,实例化的时候自动执行 + * @param {Function} exector 执行器函数,实例化的时候自动执行 + */ + constructor(exector) { + // 执行该函数,可将实例状态更改为成功 + const changeResolved = value => { + // 如果状态已经更改,结束该函数 + if (this.#state !== 'pendding') { + return; + } + // 修改状态和结果 + this.#state = 'fulfilled'; + this.#result = value; + // 遍历回调函数列表 + this.#callbackList.forEach(callback => { + callback.onResolved(value); + }); + + }; + + // 执行该函数,可将实例状态更改为成功 + const changeRejected = reason => { + // 如果状态已经更改,结束该函数 + if (this.#state !== 'pendding') { + return; + } + // 修改状态和结果 + this.#state = 'rejected'; + this.#result = reason; + // 遍历回调函数列表 + this.#callbackList.forEach(callback => { + callback.onRejected(reason); + }); + }; + + // 调用执行器函数, 如果执行器函数中有异常,修改状态为失败 + try { + exector(changeResolved, changeRejected); + } catch (error) { + // 更改为失败状态,错误对象作为结果 + changeRejected(error); + } + } + + /** + * 给实例传递成功和失败的回调函数,该方法会添加到实例的原型上 + */ + then(onResolved, onRejected) { + // 返回 Promise 对象 + return new Promise((resolve, reject) => { + if (this.#state === 'fulfilled') { // 当传入回调函数时,实例的状态已经改为成功 + setTimeout(() => { + try { + // 执行 then() 传入的回调函数并获取到返回值 + const res = onResolved(this.#result); + // 判断返回值res是否是Promise的实例 + if (res instanceof Promise) { + // then()返回值的状态与res一致 情况三 + res.then(resolve, reject); + + // res.then(value => { + // resolve(value); + // }, reason => { + // reject(reason); + // }) + } else { + // 改为成功状态,将返回值作为结果 情况一 情况二 + resolve(res); + } + } catch (error) { + // 如果调用 then() 传入的回调函数的时候出现异常,改为失败状态 情况四 + reject(error); + } + }); + } else if (this.#state === 'rejected') { // 当传入回调函数时,实例的状态已经改为失败 + setTimeout(() => { + try { + // 调用 then() 传入的回调函数并得到返回值 + const res = onRejected(this.#result); + // 判断返回值的类型 + if (res instanceof Promise) { + // 情况三 then()返回值的状态与res的状态一致 + res.then(resolve, reject); + } else { + // 情况一 情况二: 设置为成功状态 + resolve(res); + } + } catch (error) { + // 情况四:调用传入的回调函数时出现异常 + reject(error); + } + }) + } else { // 当传入回调函数时,状态还未改变 + // 将两个回调函数保存到私有属性中 + this.#callbackList.push({ + onResolved, + onRejected + }); + } + }) + } + + /** + * 给实例传递失败的回调函数,该方法会添加到实例的原型上 + */ + catch() { + + } + + + /** + * 根据参数返回新的Promise实例,该方法添加到类本身(静态方法) + */ + static resolve() { + + } + + /** + * 返回新的失败状态的Promise实例,该方法添加到类本身(静态方法) + */ + static reject() { + + } + + /** + * 当传入的所有Promise实例都完成才返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static all() { + + } + + /** + * 传入的多个Promise实例只要一个先完成就返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static race() { + + } + + + } + + window.Promise = Promise; +})(window || global); +``` + +then方法链式调用过程。 + +then方法返回一个新的Promise对象,新对象在实例化中执行器 + +![image-20240507105406241](000-images/18-promise自定义/image-20240507105406241.png) + +## 9 实现 then 方法: 进一步封装 + +``` +1. then 执行时候,三种情况,处理逻辑,进一步封装成了 handler() 函数 +2. 已经实现链式调用、调用中断 +``` + +```js +(window => { + class Promise { + // 设置私有属性,记录实例的状态和结果 + #state = 'pendding'; + #result; + // 设置私有属性,保存 then() 传入的回调函数 + #callbackList = []; + + /** + * 构造器方法,实例化的时候自动执行 + * @param {Function} exector 执行器函数,实例化的时候自动执行 + */ + constructor(exector) { + // 执行该函数,可将实例状态更改为成功 + const changeResolved = value => { + // 如果状态已经更改,结束该函数 + if (this.#state !== 'pendding') { + return; + } + // 修改状态和结果 + this.#state = 'fulfilled'; + this.#result = value; + // 遍历回调函数列表 + this.#callbackList.forEach(callback => { + callback.onResolved(value); + }); + + }; + + // 执行该函数,可将实例状态更改为成功 + const changeRejected = reason => { + // 如果状态已经更改,结束该函数 + if (this.#state !== 'pendding') { + return; + } + // 修改状态和结果 + this.#state = 'rejected'; + this.#result = reason; + // 遍历回调函数列表 + this.#callbackList.forEach(callback => { + callback.onRejected(reason); + }); + }; + + // 调用执行器函数, 如果执行器函数中有异常,修改状态为失败 + try { + exector(changeResolved, changeRejected); + } catch (error) { + // 更改为失败状态,错误对象作为结果 + changeRejected(error); + } + } + + /** + * 给实例传递成功和失败的回调函数,该方法会添加到实例的原型上 + */ + then(onResolved, onRejected) { + // 返回 Promise 对象 + return new Promise((resolve, reject) => { + + // 封装函数 专门用于执行传入 then() 的回调 + const handler = cb => { + try { + // 执行 then() 传入的回调函数并获取到返回值 + const res = cb(this.#result); + // 判断返回值res是否是Promise的实例 + if (res instanceof Promise) { + // then()返回值的状态与res一致 情况三 + res.then(resolve, reject); + } else { + // 改为成功状态,将返回值作为结果 情况一 情况二 + resolve(res); + } + } catch (error) { + // 如果调用 then() 传入的回调函数的时候出现异常,改为失败状态 情况四 + reject(error); + } + }; + + // 当传入回调函数时,实例的状态已经改为成功 + if (this.#state === 'fulfilled') { + setTimeout(() => { + handler(onResolved); + }); + + // 当传入回调函数时,实例的状态已经改为失败 + } else if (this.#state === 'rejected') { + setTimeout(() => { + handler(onRejected); + }) + + // 当传入回调函数时,状态还未改变 + } else { + // 将两个回调函数保存到私有属性中 + this.#callbackList.push({ + onResolved: () => { + handler(onResolved); + }, + onRejected: () => { + handler(onRejected); + } + }); + } + }) + } + + /** + * 给实例传递失败的回调函数,该方法会添加到实例的原型上 + */ + catch() { + + } + + + /** + * 根据参数返回新的Promise实例,该方法添加到类本身(静态方法) + */ + static resolve() { + + } + + /** + * 返回新的失败状态的Promise实例,该方法添加到类本身(静态方法) + */ + static reject() { + + } + + /** + * 当传入的所有Promise实例都完成才返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static all() { + + } + + /** + * 传入的多个Promise实例只要一个先完成就返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static race() { + + } + + + } + + window.Promise = Promise; +})(window || global); +``` + + + +## 10 实现 then 方法: 参数默认值 + +``` +1. then() 方法如果没有正确传参数(传入两个回调函数), 没传参或传入的不是函数, 将promsie的状态和结果向下传递 +2. 实现真正的异常穿透 +``` + +```js +(window => { + class Promise { + // 设置私有属性,记录实例的状态和结果 + #state = 'pendding'; + #result; + // 设置私有属性,保存 then() 传入的回调函数 + #callbackList = []; + + /** + * 构造器方法,实例化的时候自动执行 + * @param {Function} exector 执行器函数,实例化的时候自动执行 + */ + constructor(exector) { + // 执行该函数,可将实例状态更改为成功 + const changeResolved = value => { + // 如果状态已经更改,结束该函数 + if (this.#state !== 'pendding') { + return; + } + // 修改状态和结果 + this.#state = 'fulfilled'; + this.#result = value; + // 遍历回调函数列表 + this.#callbackList.forEach(callback => { + callback.onResolved(); + }); + + }; + + // 执行该函数,可将实例状态更改为成功 + const changeRejected = reason => { + // 如果状态已经更改,结束该函数 + if (this.#state !== 'pendding') { + return; + } + // 修改状态和结果 + this.#state = 'rejected'; + this.#result = reason; + // 遍历回调函数列表 + this.#callbackList.forEach(callback => { + callback.onRejected(); + }); + }; + + // 调用执行器函数, 如果执行器函数中有异常,修改状态为失败 + try { + exector(changeResolved, changeRejected); + } catch (error) { + // 更改为失败状态,错误对象作为结果 + changeRejected(error); + } + } + + /** + * 给实例传递成功和失败的回调函数,该方法会添加到实例的原型上 + */ + then(onResolved, onRejected) { + // 如果传入的参数不是函数 给参数设置默认值 + if (typeof onResolved !== 'function') { + onResolved = value => value; + } + + if (typeof onRejected !== 'function') { + onRejected = reason => { + throw reason; + } + } + + // 返回 Promise 对象 + return new Promise((resolve, reject) => { + + // 封装函数 专门用于执行传入 then() 的回调 + const handler = cb => { + try { + // 执行 then() 传入的回调函数并获取到返回值 + const res = cb(this.#result); + // 判断返回值res是否是Promise的实例 + if (res instanceof Promise) { + // then()返回值的状态与res一致 情况三 + res.then(resolve, reject); + } else { + // 改为成功状态,将返回值作为结果 情况一 情况二 + resolve(res); + } + } catch (error) { + // 如果调用 then() 传入的回调函数的时候出现异常,改为失败状态 情况四 + reject(error); + } + }; + + // 当传入回调函数时,实例的状态已经改为成功 + if (this.#state === 'fulfilled') { + setTimeout(() => { + handler(onResolved); + }); + + // 当传入回调函数时,实例的状态已经改为失败 + } else if (this.#state === 'rejected') { + setTimeout(() => { + handler(onRejected); + }) + + // 当传入回调函数时,状态还未改变 + } else { + // 将两个回调函数保存到私有属性中 + this.#callbackList.push({ + onResolved: () => { + handler(onResolved); + }, + onRejected: () => { + handler(onRejected); + } + }); + } + }) + } + + /** + * 给实例传递失败的回调函数,该方法会添加到实例的原型上 + */ + catch() { + + } + + + /** + * 根据参数返回新的Promise实例,该方法添加到类本身(静态方法) + */ + static resolve() { + + } + + /** + * 返回新的失败状态的Promise实例,该方法添加到类本身(静态方法) + */ + static reject() { + + } + + /** + * 当传入的所有Promise实例都完成才返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static all() { + + } + + /** + * 传入的多个Promise实例只要一个先完成就返回一个Promise实例,该方法添加到类本身(静态方法) + */ + static race() { + + } + + + } + + window.Promise = Promise; +})(window || global); +``` + + + +## 11 实现 catch 方法 + +``` +catch 只传入失败状态的回调,相当于 then(undefined, 回调函数) +``` + +```js +(window => { + class Promise { + + /** + * 给实例传递失败的回调函数,该方法会添加到实例的原型上 + * @param {Function} onRejected 实例状态失败执行的回调 + */ + catch(onRejected) { + return this.then(undefined, onRejected); + } + + } + + window.Promise = Promise; +})(window || global); +``` + + + + + +## 12 实现 Promise.resolve() 方法 + +``` +情况一:没有参数,返回成功状态Promise实例,result是undefined +情况一:参数是非Promise,返回成功状态Promise实例,result是参数 +情况三:参数是Promise实例,参数就是返回值 +情况四:参数是thenable对象,返回Promise实例,状态由thenable对象中的then方法决定 +``` + +```js +(window => { + class Promise { + + /** + * 根据参数返回新的Promise实例,该方法添加到类本身(静态方法) + * @param {Mixed} value 该参数影响返回的Promise + */ + static resolve(value) { + if (value instanceof Promise) { + // 情况三 参数就是Promise对象 + return value; + } else if (typeof value?.then === 'function') { + // 情况四 将resolve, reject传递给 value.then方法,由该 thenable 对象决定改为什么状态 + return new Promise((resolve, reject) => { + setTimeout(() => { + value.then(resolve, reject); + }) + }); + } else { + // 情况一 情况二 返回成功状态的Promise对象 value作为result + return new Promise((resolve, reject) => { + resolve(value); + }) + } + } + + } + + window.Promise = Promise; +})(window || global); +``` + + + +## 13 实现 Promise.reject() 方法 + +```js +(window => { + class Promise { + /** + * 返回新的失败状态的Promise实例,该方法添加到类本身(静态方法) + * @param {Mixed} value 该参数作为返回值的result + */ + static reject(value) { + return new Promise((resolve, reject) => { + reject(value); + }); + } + } + + window.Promise = Promise; +})(window || global); +``` + + + + + +## 14 实现 Promise.all() 方法 + +``` +1 参数是可遍历对象 + 1.1 所有成员都是成功状态,返回的promise也是成功状态,reuslt 是数组,包含每个成员的result + 1.2 有一个成员失败,返回的promise也是失败,result是第一个失败成员的result +2 参数不是可遍历对象 + 返回失败状态的promise +``` + +```js +(window => { + class Promise { + /** + * 当传入的所有Promise实例都完成才返回一个Promise实例,该方法添加到类本身(静态方法) + * @param {Iterable} items 里面的成员都是Promise对象,不是Promise也会用Promise.resolve()变为Promise对象 + * @return {Promise} 所有成员都成功状态成功 + */ + static all(items) { + return new Promise((resolve, reject) => { + if (typeof items[Symbol.iterator] === 'function') { + // 将参数 items 转为数组 + const itemsArr = Array.from(items); + // 记录每个成员成功之后的结果 + const resArr = Array(itemsArr.length); + // 遍历所有成员 + itemsArr.forEach((item, index) => { + const p = Promise.resolve(item); // 处理每个成员 + p + .then(res => { + resArr[index] = res; + // 如果resArr填充满了,说明所有的成员都完成了 + if ((resArr.filter(()=>true)).length === itemsArr.length) { + resolve(resArr); + } + }) + .catch(reason => { + reject(reason); + }); + }) + } else { + // 说明参数items不是可遍历对象 + reject('argument must is a iterable'); + } + }) + } + } + + window.Promise = Promise; +})(window || global); +``` + + + +## 15 实现 Promise.race() 方法 + +``` +1. 传入可遍历对象,一个完成,就最终完成 +2. 参数不是可遍历对象,返回失败状态的promise +``` + +```js +(window => { + class Promise { + /** + * 传入的多个Promise实例只要一个先完成就返回一个Promise实例,该方法添加到类本身(静态方法) + * @param {Iterable} items 里面的成员都是Promise对象,不是Promise也会用Promise.resolve()变为Promise对象 + * @return {Promsie} + */ + static race(items) { + return new Promise((resolve, reject) => { + if (typeof items[Symbol.iterator] === 'function') { + // 遍历 items + for (let item of items) { + const p = Promise.resolve(item); + p.then(resolve, reject) + } + } else { + reject('argument must is a iterable'); + } + }); + } + } + + window.Promise = Promise; +})(window || global); +``` +