爬取网易云音乐个人动态中的视频(Ⅱ): 分析并获取api

回顾和概览

在 爬取网易云音乐个人动态中的视频(Ⅰ) 中简单的分析了一下需要做什么, 现在要做的就是获取网易云的api, 很遗憾, 网易云并没有开放api出来, 但是我们可以对网页进行调试, 尝试从中获得我们需要的信息.


参考

  1. 网易云音乐JS下的AES加密参数-分析
  2. 网易云音乐新登录API分析

为什么已有两篇分析我还要自己再写一篇呢?

原因有二:

  1. 两篇分析对我来说还不足够详细
  2. 看完两篇分析之后, 是我第一次使用断点调试js, 所以想详细记录下来, 当作笔记


开始

从 爬取网易云音乐个人动态中的视频(Ⅰ) 中, 我们发现api(http://music.163.com/weapi/cloudvideo/playurl)中参数有两个 params 和 encSecKey, 加密肯定是通过js驱动的, 所以, 在网易云网页的js上搜索可能会有所发现.

还是在 爬取网易云音乐个人动态中的视频(Ⅰ) 中提到的 视频网页 上进行分析, 可能第一次打开这个网页会出现如下图的情况


刷新一遍, 就有我们需要的core.js文件了: 



分析core.js

点击打开这个core.js, 你会发现js代码都没有缩进, 很难看, 点击一下页面的"{}", Chrome浏览器会对其进行格式化并在新窗口打开这个格式化后的core.js, 如下图

    

搜索字符串"encSecKey", 可以看到有3个匹配, 逐一查看, 在第二个查找结果中发现这和 爬取网易云音乐个人动态中的视频(Ⅰ) 中提到的参数很像


仔细看看encSecKey所在的这个function

(function() {
    var c7f = NEJ.P
      , eq9h = c7f("nej.g")
      , v7o = c7f("nej.j")
      , k7d = c7f("nej.u")
      , Ua2x = c7f("nm.x.ek")
      , l7e = c7f("nm.x");
    if (v7o.bk8c.redefine)
        return;
    window.GEnc = true;
    var brX9O = function(crL1x) {
        var m7f = [];
        k7d.bd7W(crL1x, function(crK1x) {
            m7f.push(Ua2x.emj[crK1x])
        });
        return m7f.join("")
    };
    var crH1x = v7o.bk8c;
    v7o.bk8c = function(Y7R, e7d) {
        var i7b = {}
          , e7d = NEJ.X({}, e7d)
          , lL1x = Y7R.indexOf("?");
        if (window.GEnc && /(^|\.com)\/api/.test(Y7R) && !(e7d.headers && e7d.headers[eq9h.yH5M] == eq9h.Ht7m) && !e7d.noEnc) {
            if (lL1x != -1) {
                i7b = k7d.hf0x(Y7R.substring(lL1x + 1));
                Y7R = Y7R.substring(0, lL1x)
            }
            if (e7d.query) {
                i7b = NEJ.X(i7b, k7d.fJ9A(e7d.query) ? k7d.hf0x(e7d.query) : e7d.query)
            }
            if (e7d.data) {
                i7b = NEJ.X(i7b, k7d.fJ9A(e7d.data) ? k7d.hf0x(e7d.data) : e7d.data)
            }
            i7b["csrf_token"] = v7o.gI0x("__csrf");
            Y7R = Y7R.replace("api", "weapi");
            e7d.method = "post";
            delete e7d.query;
            var bRB5G = window.asrsea(JSON.stringify(i7b), brX9O(["流泪", "强"]), brX9O(Ua2x.md), brX9O(["爱心", "女孩", "惊恐", "大笑"]));
            e7d.data = k7d.cz8r({
                params: bRB5G.encText,
                encSecKey: bRB5G.encSecKey
            })
        }
        crH1x(Y7R, e7d)
    }
    ;
    v7o.bk8c.redefine = true
}
)();

一个关键的语句是

window.asrsea(JSON.stringify(i7b), brX9O(["流泪", "强"]), brX9O(Ua2x.md), brX9O(["爱心", "女孩", "惊恐", "大笑"]));

这个brX90在这可能是一个拼接字符串的作用, 因为这个函数里面有push和join这两个关键字

window.asrsea的定义不在这里面, 搜索"window.asrsea", 如下图


到现在我们可以确定, window.asrsea就是我们需要的东西, 是大boss!

仔细看看window.asrsea所在的函数

!function() {
    function a(a) {
        var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
        for (d = 0; a > d; d += 1)
            e = Math.random() * b.length,
            e = Math.floor(e),
            c += b.charAt(e);
        return c
    }
    function b(a, b) {
        var c = CryptoJS.enc.Utf8.parse(b)
          , d = CryptoJS.enc.Utf8.parse("0102030405060708")
          , e = CryptoJS.enc.Utf8.parse(a)
          , f = CryptoJS.AES.encrypt(e, c, {
            iv: d,
            mode: CryptoJS.mode.CBC
        });
        return f.toString()
    }
    function c(a, b, c) {
        var d, e;
        return setMaxDigits(131),
        d = new RSAKeyPair(b,"",c),
        e = encryptedString(d, a)
    }
    function d(d, e, f, g) {
        var h = {}
          , i = a(16);
        return h.encText = b(d, g),
        h.encText = b(h.encText, i),
        h.encSecKey = c(i, e, f),
        h
    }
    function e(a, b, d, e) {
        var f = {};
        return f.encText = c(a + e, b, d),
        f
    }
    window.asrsea = d,
    window.ecnonasr = e
}();

函数d实际是去调用两个加密函数(AES加密函数b和RSA加密函数c)对传入的参数进行加密, 进行分析, 大致逻辑如下:

  1. 调用函数a生成一个16位随机数i;
  2. 调用函数b, 加密d(后文可知这是四个参数值唯一可变的), 得到encText
  3. 调用函数b, 加密步骤2得到的encText, 得到新的encText
  4. 调用函数c, 得到encSecKey

这样就得到api(http://music.163.com/weapi/cloudvideo/playurl)中所需要的params(encText)和encSecKey(encSecKey)了


断点分析

在上图中的红框处的 var h = {} 也即12828行, 点击行号设置一个断点, 在右侧的Watch窗口新建一个观察, 填入"window.asrsea", 如下图

然后, 刷新页面, 如下图, 我们就获得了window.asrsea中所需的3个固定参数(图中的参数1, 2, 3), 但是图中参数0到底怎样的还需要商榷


看回Network, 如下图, 点击XHR进行一下过滤, 没发现我们需要的东西


现在我们继续执行调试, 可以按F8, 也可以点击下图红框处


看回Source和Network

   

虽然Source中的Watch没怎么变, 但是在这里我们可以确定图中的参数1, 2, 3都是定值. 从Network可以看出第一次的window.asrsea值是给 http://music.163.com/weapi/cdns 所用的.

重复上述过程, 每次都要去Network看看网络请求, 不要点击太快, 不然又要重来一次调试, 可以把每次Source都截图下来, 方便再次查看.

下图是最后一次调试的Network, 到这就要小心了, 不要继续调试了


下图是Source界面, 把鼠标放在图中参数0的位置, 以防看漏了参数


继续调试, 页面正常运行, 看回Network, 如下图


据此, 可以肯定api(http://music.163.com/weapi/cloudvideo/playurl)需要4个参数, 其中后三个参数是定值, 第一个参数由ids, resolution, csrf_token组成

0: {"ids":"[\"5B0AF067CBB42F7789F7B97E13827565\"]","resolution":"720","csrf_token":""}
1: 010001
2: 00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7
3: 0CoJUm6Qyw8W8jud


实现加密

在 网易云音乐新登录API分析 一文中, 作者对加密进行了实现, 作者的最新代码在 encrypt.py 中可查看

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值