Skip to content

网易云音乐API分析 weapi

METO edited this page Aug 16, 2016 · 2 revisions

0. 状态

该第二版 API 为最新版本,返回结构有大幅度变动,交互地址有个特征 weapi

1. 总览

所有交互需要指定两个参数:

key value
referer http://music.163.com
Cookie os=uwp; osver=10.0.10586.318; appver=1.2.1;

下面列出的所有参数均为明文参数,实际提交需要进行加密,详见最下方第 7 条目

2. 搜索

POST http://music.163.com/weapi/cloudsearch/get/web?csrf_token=

明文参数

s: 关键字
limit: 返回数据条数限制
offset: 偏移数量,用于分页
total: true
csrf_token: 非关键操作,值可为空
type: 搜索类型

  • 1 单曲
  • 10 专辑
  • 100 歌手
  • 1000 歌单
  • 1002 用户
  • 1009 电台
  • NULL 推荐(实测失效)

返回数据

object(stdClass)#224 (2) {
  ["result"] => object(stdClass)#223 (2) {
    ["songs"] => array(30) {
      [0] => object(stdClass)#7 (30) {
        ["rtUrls"] => array(0) {
        }
        ["ar"] => array(1) {
          [0] => object(stdClass)#6 (2) {
            ["id"] => int(46487)
            ["name"] => string(5) "Adele"
          }
        }
        ["al"] => object(stdClass)#5 (4) {
          ["id"] => int(3377030)
          ["name"] => string(5) "Hello"
          ["pic_str"] => string(16) "3388694837506899"
          ["pic"] => int(3388694837506899)
        }
        ["st"] => int(0)
        ["cd"] => string(0) ""
        ["no"] => int(1)
        ["ftype"] => int(0)
        ["rtype"] => int(0)
        ["rurl"] => NULL
        ["t"] => int(0)
        ["v"] => int(11)
        ["a"] => NULL
        ["m"] => object(stdClass)#9 (4) {
          ["br"] => int(160000)
          ["fid"] => int(3294136840472685)
          ["size"] => int(5911554)
          ["vd"] => float(-2.95)
        }
        ["pst"] => int(0)
        ["alia"] => array(0) {
        }
        ["pop"] => float(100)
        ["rt"] => NULL
        ["mst"] => int(9)
        ["cp"] => int(390012)
        ["mv"] => int(501053)
        ["cf"] => string(0) ""
        ["dt"] => int(295502)
        ["h"] => object(stdClass)#8 (4) {
          ["br"] => int(320000)
          ["fid"] => int(3294136840472684)
          ["size"] => int(11823063)
          ["vd"] => float(-3.39)
        }
        ["l"] => object(stdClass)#10 (4) {
          ["br"] => int(96000)
          ["fid"] => int(3294136840472686)
          ["size"] => int(3546950)
          ["vd"] => float(-2.97)
        }
        ["crbt"] => NULL
        ["rtUrl"] => NULL
        ["fee"] => int(0)
        ["name"] => string(5) "Hello"
        ["id"] => int(35847388)
        ["privilege"] => object(stdClass)#11 (13) {
          ["id"] => int(35847388)
          ["fee"] => int(0)
          ["payed"] => int(0)
          ["st"] => int(0)
          ["pl"] => int(320000)
          ["dl"] => int(320000)
          ["sp"] => int(7)
          ["cp"] => int(1)
          ["subp"] => int(1)
          ["cs"] => bool(false)
          ["maxbr"] => int(999000)
          ["fl"] => int(320000)
          ["toast"] => bool(false)
        }
      }
      ...
    }
    ["songCount"] => int(9999)
  }
  ["code"] => int(200)
}

3. 专辑

POST http://music.163.com/weapi/v1/album/{album_id}?csrf_token=

参数

album_id: 专辑 ID,在 url 也需要包含
csrf_token: 非关键操作,值可为空

返回数据

object(stdClass)#12 (3) {
  ["songs"] => array(1) {
    [0] => object(stdClass)#7 (30) {
      ["rtUrls"] => array(0) {
      }
      ["ar"] => array(1) {
        [0] => object(stdClass)#6 (2) {
          ["id"] => int(46487)
          ["name"] => string(5) "Adele"
        }
      }
      ["al"] => object(stdClass)#5 (4) {
        ["id"] => int(3377030)
        ["name"] => string(5) "Hello"
        ["pic_str"] => string(16) "3388694837506899"
        ["pic"] => int(3388694837506899)
      }
      ["st"] => int(0)
      ["a"] => NULL
      ["m"] => object(stdClass)#9 (4) {
        ["br"] => int(160000)
        ["fid"] => int(3294136840472685)
        ["size"] => int(5911554)
        ["vd"] => float(-2.95)
      }
      ["no"] => int(1)
      ["v"] => int(11)
      ["t"] => int(0)
      ["cd"] => string(0) ""
      ["fee"] => int(0)
      ["ftype"] => int(0)
      ["rtype"] => int(0)
      ["rurl"] => NULL
      ["pst"] => int(0)
      ["alia"] => array(0) {
      }
      ["pop"] => float(100)
      ["rt"] => NULL
      ["mst"] => int(9)
      ["cp"] => int(390012)
      ["mv"] => int(501053)
      ["cf"] => string(0) ""
      ["dt"] => int(295502)
      ["h"] => object(stdClass)#8 (4) {
        ["br"] => int(320000)
        ["fid"] => int(3294136840472684)
        ["size"] => int(11823063)
        ["vd"] => float(-3.39)
      }
      ["l"] => object(stdClass)#10 (4) {
        ["br"] => int(96000)
        ["fid"] => int(3294136840472686)
        ["size"] => int(3546950)
        ["vd"] => float(-2.97)
      }
      ["crbt"] => NULL
      ["rtUrl"] => NULL
      ["name"] => string(5) "Hello"
      ["id"] => int(35847388)
      ["privilege"] => object(stdClass)#11 (13) {
        ["id"] => int(35847388)
        ["fee"] => int(0)
        ["payed"] => int(0)
        ["st"] => int(0)
        ["pl"] => int(320000)
        ["dl"] => int(320000)
        ["sp"] => int(7)
        ["cp"] => int(1)
        ["subp"] => int(1)
        ["cs"] => bool(false)
        ["maxbr"] => int(999000)
        ["fl"] => int(320000)
        ["toast"] => bool(false)
      }
    }
  }
  ["code"] => int(200)
  ["album"] => object(stdClass)#13 (24) {
    ["songs"] => array(0) {
    }
    ["paid"] => bool(false)
    ["onSale"] => bool(false)
    ["status"] => int(0)
    ["alias"] => array(0) {
    }
    ["picId"] => int(3388694837506899)
    ["company"] => string(13) "XL Recordings"
    ["picUrl"] => string(69) "http://p3.music.126.net/br3IrdCvT7-GjCyUVNONiA==/3388694837506899.jpg"
    ["briefDesc"] => NULL
    ["publishTime"] => int(1445529600007)
    ["artist"] => object(stdClass)#14 (12) {
      ["img1v1Id"] => int(0)
      ["musicSize"] => int(279)
      ["alias"] => array(1) {
        [0] => string(24) "Adele Laurie Blue Adkins"
      }
      ["picId"] => int(3263350518850889)
      ["trans"] => string(9) "阿黛尔"
      ["picUrl"] => string(69) "http://p3.music.126.net/_cSzHw9F-Nkgy9gb2QPI_A==/3263350518850889.jpg"
      ["briefDesc"] => string(0) ""
      ["albumSize"] => int(28)
      ["img1v1Url"] => string(69) "http://p3.music.126.net/6y-UleORITEDbvrOLV0Q8A==/5639395138885805.jpg"
      ["name"] => string(5) "Adele"
      ["id"] => int(46487)
      ["transNames"] => array(1) {
        [0] => string(9) "阿黛尔"
      }
    }
    ["artists"] => array(1) {
      [0] => object(stdClass)#15 (11) {
        ["img1v1Id"] => int(0)
        ["musicSize"] => int(0)
        ["alias"] => array(0) {
        }
        ["picId"] => int(0)
        ["trans"] => string(0) ""
        ["picUrl"] => string(0) ""
        ["briefDesc"] => string(0) ""
        ["albumSize"] => int(0)
        ["img1v1Url"] => string(69) "http://p4.music.126.net/6y-UleORITEDbvrOLV0Q8A==/5639395138885805.jpg"
        ["name"] => string(5) "Adele"
        ["id"] => int(46487)
      }
    }
    ["blurPicUrl"] => string(69) "http://p3.music.126.net/br3IrdCvT7-GjCyUVNONiA==/3388694837506899.jpg"
    ["companyId"] => int(0)
    ["pic"] => int(3388694837506899)
    ["description"] => string(74) "Adele新专辑《25》首发单曲《Hello》于2015年10月23日发行。"
    ["tags"] => string(0) ""
    ["copyrightId"] => int(390012)
    ["commentThreadId"] => string(14) "R_AL_3_3377030"
    ["name"] => string(5) "Hello"
    ["id"] => int(3377030)
    ["type"] => string(9) "EP/Single"
    ["size"] => int(1)
    ["info"] => object(stdClass)#16 (9) {
      ["latestLikedUsers"] => NULL
      ["liked"] => bool(false)
      ["comments"] => NULL
      ["resourceType"] => int(3)
      ["resourceId"] => int(3377030)
      ["shareCount"] => int(413)
      ["commentCount"] => int(990)
      ["threadId"] => string(14) "R_AL_3_3377030"
      ["likedCount"] => int(0)
    }
  }
}

4. 歌单

POST http://music.163.com/weapi/v3/playlist/detail?csrf_token=

参数

id: 歌单 ID
csrf_token: 非关键操作,值可为空

返回数据

object(stdClass)#14 (3) {
  ["playlist"] => object(stdClass)#7 (27) {
    ["subscribers"] => array(0) {
    }
    ["subscribed"] => bool(false)
    ["creator"] => object(stdClass)#6 (24) {
      ["vipType"] => int(0)
      ["backgroundImgId"] => int(3441471400879005)
      ["avatarImgId"] => int(3427177752657109)
      ["userId"] => int(76696522)
      ["remarkName"] => NULL
      ["mutual"] => bool(false)
      ["djStatus"] => int(0)
      ["nickname"] => string(11) "ZAYN-MALIK-"
      ["avatarUrl"] => string(69) "http://p3.music.126.net/YjMiwnpbTMBvW7VEH_sk3Q==/3427177752657109.jpg"
      ["expertTags"] => NULL
      ["accountStatus"] => int(0)
      ["authStatus"] => int(0)
      ["detailDescription"] => string(0) ""
      ["followed"] => bool(false)
      ["province"] => int(1000000)
      ["defaultAvatar"] => bool(false)
      ["gender"] => int(2)
      ["birthday"] => int(1020441600000)
      ["city"] => int(1007700)
      ["backgroundUrl"] => string(69) "http://p1.music.126.net/AzJdp8YtwCvKNCDnQ2Yu4g==/3441471400879005.jpg"
      ["userType"] => int(0)
      ["description"] => string(0) ""
      ["signature"] => string(34) "爱1D,Zayn,Westlife,Shane,Troye..."
      ["authority"] => int(0)
    }
    ["tracks"] => array(1) {
      [0] => object(stdClass)#5 (29) {
        ["rtUrls"] => array(0) {
        }
        ["ar"] => array(1) {
          [0] => object(stdClass)#9 (2) {
            ["id"] => int(46487)
            ["name"] => string(5) "Adele"
          }
        }
        ["al"] => object(stdClass)#8 (4) {
          ["id"] => int(3377030)
          ["name"] => string(5) "Hello"
          ["pic_str"] => string(16) "3388694837506899"
          ["pic"] => int(3388694837506899)
        }
        ["st"] => int(0)
        ["cd"] => string(0) ""
        ["no"] => int(1)
        ["fee"] => int(0)
        ["ftype"] => int(0)
        ["rtype"] => int(0)
        ["rurl"] => NULL
        ["t"] => int(0)
        ["v"] => int(11)
        ["a"] => NULL
        ["m"] => object(stdClass)#10 (4) {
          ["br"] => int(160000)
          ["fid"] => int(3294136840472685)
          ["size"] => int(5911554)
          ["vd"] => float(-2.95)
        }
        ["crbt"] => NULL
        ["rtUrl"] => NULL
        ["pst"] => int(0)
        ["alia"] => array(0) {
        }
        ["pop"] => float(100)
        ["rt"] => NULL
        ["mst"] => int(9)
        ["cp"] => int(390012)
        ["mv"] => int(501053)
        ["cf"] => string(0) ""
        ["dt"] => int(295502)
        ["h"] => object(stdClass)#11 (4) {
          ["br"] => int(320000)
          ["fid"] => int(3294136840472684)
          ["size"] => int(11823063)
          ["vd"] => float(-3.39)
        }
        ["l"] => object(stdClass)#12 (4) {
          ["br"] => int(96000)
          ["fid"] => int(3294136840472686)
          ["size"] => int(3546950)
          ["vd"] => float(-2.97)
        }
        ["name"] => string(5) "Hello"
        ["id"] => int(35847388)
      }
    }
    ["trackIds"] => array(1) {
      [0] => object(stdClass)#13 (2) {
        ["id"] => int(35847388)
        ["v"] => int(11)
      }
    }
    ["cloudTrackCount"] => int(0)
    ["trackNumberUpdateTime"] => int(1446884413425)
    ["adType"] => int(0)
    ["status"] => int(0)
    ["playCount"] => int(10)
    ["updateTime"] => int(1446884413425)
    ["userId"] => int(76696522)
    ["trackCount"] => int(1)
    ["commentThreadId"] => string(16) "A_PL_0_124394335"
    ["coverImgId"] => int(3388694837506899)
    ["specialType"] => int(0)
    ["createTime"] => int(1446884412646)
    ["highQuality"] => bool(false)
    ["subscribedCount"] => int(0)
    ["trackUpdateTime"] => int(1467984278182)
    ["newImported"] => bool(false)
    ["description"] => NULL
    ["tags"] => array(0) {
    }
    ["name"] => string(11) "Hello,Adele"
    ["id"] => int(124394335)
    ["shareCount"] => int(0)
    ["commentCount"] => int(0)
  }
  ["code"] => int(200)
  ["privileges"] => array(1) {
    [0] => object(stdClass)#15 (13) {
      ["id"] => int(35847388)
      ["fee"] => int(0)
      ["payed"] => int(0)
      ["st"] => int(0)
      ["pl"] => int(320000)
      ["dl"] => int(320000)
      ["sp"] => int(7)
      ["cp"] => int(1)
      ["subp"] => int(1)
      ["cs"] => bool(false)
      ["maxbr"] => int(999000)
      ["fl"] => int(320000)
      ["toast"] => bool(false)
    }
  }
}

5. 单曲信息

POST http://music.163.com/weapi/v3/song/detail

参数

c: Json 格式字符串,格式如:[{"id":3377030}]
csrf_token: 非关键操作,值可为空

返回数据

object(stdClass)#11 (2) {
  ["songs"] => array(1) {
    [0] => object(stdClass)#7 (29) {
      ["rtUrls"] => array(0) {
      }
      ["ar"] => array(1) {
        [0] => object(stdClass)#6 (2) {
          ["id"] => int(46487)
          ["name"] => string(5) "Adele"
        }
      }
      ["al"] => object(stdClass)#5 (4) {
        ["id"] => int(3377030)
        ["name"] => string(5) "Hello"
        ["pic_str"] => string(16) "3388694837506899"
        ["pic"] => int(3388694837506899)
      }
      ["st"] => int(0)
      ["ftype"] => int(0)
      ["rtype"] => int(0)
      ["rurl"] => NULL
      ["t"] => int(0)
      ["v"] => int(11)
      ["no"] => int(1)
      ["pst"] => int(0)
      ["alia"] => array(0) {
      }
      ["pop"] => float(100)
      ["rt"] => NULL
      ["mst"] => int(9)
      ["cp"] => int(390012)
      ["mv"] => int(501053)
      ["cf"] => string(0) ""
      ["dt"] => int(295502)
      ["h"] => object(stdClass)#9 (4) {
        ["br"] => int(320000)
        ["fid"] => int(3294136840472684)
        ["size"] => int(11823063)
        ["vd"] => float(-3.39)
      }
      ["l"] => object(stdClass)#8 (4) {
        ["br"] => int(96000)
        ["fid"] => int(3294136840472686)
        ["size"] => int(3546950)
        ["vd"] => float(-2.97)
      }
      ["a"] => NULL
      ["m"] => object(stdClass)#10 (4) {
        ["br"] => int(160000)
        ["fid"] => int(3294136840472685)
        ["size"] => int(5911554)
        ["vd"] => float(-2.95)
      }
      ["fee"] => int(0)
      ["cd"] => string(0) ""
      ["crbt"] => NULL
      ["rtUrl"] => NULL
      ["name"] => string(5) "Hello"
      ["id"] => int(35847388)
    }
  }
  ["code"] => int(200)
}

6. URL 分析

POST http://music.163.com/weapi/song/enhance/player/url?csrf_token=

参数

id: 歌单 ID
br: 比特率,320000
csrf_token: 非关键操作,值可为空

返回数据

object(stdClass)#6 (2) {
  ["data"] => array(1) {
    [0] => object(stdClass)#7 (14) {
      ["id"] => int(35847388)
      ["url"] => string(130) "http://m8.music.126.net/20160711164257/ead9b97be441c8841dec2f624652bc1c/ymusic/a3bc/b02c/b25b/7a1f79bb4c732d4bd2a2ab967c2bb7d1.mp3"
      ["br"] => int(320000)
      ["size"] => int(11823063)
      ["md5"] => string(32) "7a1f79bb4c732d4bd2a2ab967c2bb7d1"
      ["code"] => int(200)
      ["expi"] => int(1200)
      ["type"] => string(3) "mp3"
      ["gain"] => float(-3.38)
      ["fee"] => int(0)
      ["uf"] => NULL
      ["payed"] => int(0)
      ["flag"] => int(0)
      ["canExtend"] => bool(false)
    }
  }
  ["code"] => int(200)
}

URL 特征

http://m8.music.126.net/[expTime]/[token]/ymusic/[key1]/[key2]/[key3]/[MD5].mp3

参数

expTime: 过期时间戳,标识本 URL 只能在过期时间前请求,否则返回 403 token: 随 expTime 变动,为校验码,加密方式尚不清楚 key123: 固定值,随歌曲 md5 而改变,我还没搞明白,求大神们指教 MD5: 该歌曲的 MD5 校验码,小写

7. 加密请求

实际请求的参数应当加密为如下形式:

params: Db3xGrqMzXwQqWAIe7AlqILYssUuypZlUS+6Dr8g//OEK8SPpjsZht2j+/C+UZ/rAh1bsXoFDEZxQUwdVB5oc1nSRRT3gpmRgzmwhR8yBCboIk+Uf8PvV2azs2WQ10zewCEps4IAIW1Dbes4jxGcEh7pmUXurQQcrjf9VjzOp64XwKuzunQbb0JG8CwybMIyHjWAC6osTnopHVkSikLsMggTLCVADoK3s+a75VWaYY0srdCoS3FJq8tvvnVGim6k3TpsFkiII/r5DCm8EyvfLrZcsiB5Kpx96ZjxZXYw4yU=

encSecKey: 8ac3219a491bfde0c81532fb4d6c8cd919cc2613631f11a82a72a1fd02e535eb5fbce3c51e7bb8ad2ba06590c391ddec326aa6d6535f36bcb2dd074cf9601f1e874fbfe96787f341d824ea8f03781713355e745472949cb44d8b4c6ed1c76944e2d684add7e746f8ab6119caa7270dd3373320345d946dfb2647c66ab6ef51e5

其中 params 为 AES 对称加密后的参数,encSecKey 为 RSA 加密后的 AES 密钥。 所有公钥等参数详见代码,这里不列出。

1. 生成 AES 密钥

AES 密钥需要随机,否则服务器会 dump 掉相同密钥的请求(数量多的话)。
密钥的形式为 16 位随机字母或数字,[0-9a-zA-Z]

function createSecretKey($length=16){
    $str='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $r='';
    for($i=0;$i<$length;$i++){
        $r.=$str[rand(0,strlen($str)-1)];
    }
    return $r;
}

2. AES 加密

在上述 API 中,首先将 POST 参数值拼写为如下形式,以搜索 hello 为例:

{"s":"hello","type":"1","limit":"1000","offset":"0","csrf_token":""}

然后对上面的明文进行两次 AES 加密,第一次密钥为 nonce,第二次为第一步生成的密钥。

$data['params']=$this->aes_encode($string,$this->_nonce);
$data['params']=$this->aes_encode($data['params'],$this->_secretKey);

AES 加密的具体算法为:AES-128-CBC,输出格式为 base64
AES 加密时需要指定 iv:0102030405060708

本步骤加密后的结果即为 params

3. RSA 加密

最后对第一步生成的 secretKey 进行 RSA 加密,不过这个加密非常诡异,不是标准的形式。下面引用 darknessomi 的结论

RSA 加密采用非常规填充方式,既不是 PKCS1 也不是 PKCS1_OAEP,网易的做法是直接向前补0
这样加密出来的密文有个特点:加密过程没有随机因素,明文多次加密后得到的密文是相同的
然而,我们常用的 RSA 加密模块均不支持此种加密,所以需要手写一段简单的 RSA 加密
加密过程 convertUtf8toHex(reversedText)^e%N
输入过程中需要对加密字符串进行 hex 格式转码

PHP 中需要使用大数运算类,如果嫌不够清真的话可以自己实现,需要使用快速幂算法加速

function rsa_encode($text){
    $rtext=strrev(utf8_encode($text));
    $keytext=$this->bchexdec($this->strToHex($rtext));
    $a=new Math_BigInteger($keytext);
    $b=new Math_BigInteger($this->bchexdec($this->_pubKey));
    $c=new Math_BigInteger($this->bchexdec($this->_modulus));
    $key=$a->modPow($b, $c)->toHex();
    return str_pad($key,256,'0',STR_PAD_LEFT);
}
function bchexdec($hex){
    $dec=0;
    $len=strlen($hex);
    for($i=0;$i<$len;$i++) {
        $dec=bcadd($dec,bcmul(strval(hexdec($hex[$i])),bcpow('16',strval($len-$i-1))));
    }
    return $dec;
}
function strToHex($str){
    $hex='';
    for($i=0;$i<strlen($str);$i++){
        $hex.=dechex(ord($str[$i]));
    }
    return $hex;
}

本步骤加密后的结果即为 encSecKey

Clone this wiki locally