网易云音乐爬虫(一)

通常要爬一个网站,第一步是确定要爬的字段,然后抓包分析各个接口。我需要的数据在这几处:

  • https://music.163.com/weapi/song/enhance/player/url
  • https://music.163.com/weapi/v3/song/detail
  • https://music.163.com/weapi/song/lyric

第一个包含歌曲的MP3文件链接,第二个包含歌曲名、歌手、专辑等歌曲的详情信息,第三个包含歌曲的歌词。

这三个接口的共同特征是post提交的data参数中都包括params和encSecKey

显然,这两个字符串是经过JS加密的,那么现在要做的就是逆向JS

打开Chrome的开发者工具,进入Sources,然后Ctrl+Shift+F全局搜索,试着找找encSecKey这个参数名。很幸运,post接口的data参数毫无隐藏。

e5j.data = k5p.cB6v({
    params: bUS9J.encText,
    encSecKey: bUS9J.encSecKey
})

然后对这个地方的前面几行JS代码打上断点慢慢调试,找出这个bUS9J的来源。简单看了下,params和encSecKey用的应该分别是AES和RSA算法。说到加密算法,今天在看阮一峰老师之前写的关于比特币和区块链的文章提到比特币里用到的非对称算法,虽然他没细说,但我查了一下,是ECC算法(椭圆曲线加密),让我增长了不少见识,感兴趣的朋友可以去了解一下。

这里的JS加密的关键在于下面这句代码的asrsea函数,i5n是要进行加密的字符串(不同的接口字符串格式不同),包含了歌曲的id信息;后面是用于加密的key或者iv之类的,其实可以写死。

var bUS9J = window.asrsea(JSON.stringify(i5n), bra0x(["流泪", "强"]), bra0x(Sn1x.md), bra0x(["爱心", "女孩", "惊恐", "大笑"]));

针对asrsea函数,通过调试慢慢将涉及加密的JS代码拎出来,写进JS文件。调试的过程这里就不细讲了,其实也不好讲。因为这部分可能更多的是靠经验跟直觉,比如应该在哪打断点,哪个变量比较关键。

然后要在Python中执行JS代码。通常我是采用pyexecjs调nodejs环境来执行,并返回需要的值。但是这里我考虑到一个问题,由于我后续会用Scrapy框架来写爬虫,这种稍微有点耗时的计算型任务如果直接写进Scrapy,无论是写到中间件还是spider,只能是同步的。针对这一点,我的改进方式是选一台多核服务器,单独维护一个HTTP服务负责执行JS代码。由于开多线程或多进程去调nodejs,就会产生多个nodejs进程,这样可以在爬虫过程中很好地实现多核并行计算。当然,如果没有多核服务器或者不苛求性能,完全没必要这么折腾。

解决了接口的加密,剩下的就没什么好说的了,带上该有的headers、data什么的发起请求就完事了。然而后来我仔细查了该网站的JS源码之后才发现,网易居然还提供了好多暴露的api接口,毫无加密措施,可以直接传歌曲或者歌手或者专辑的id参数得到响应的数据。所以,上面提到的最后统统都没用上,但还是值得记录的。

后面我准备分享的是在写Scrapy+Redis分布式时的一些点。包括一些基础的配置,Download和Spider中间件的写法,扩展的写法等。最近也有在研究Scrapy的源码,这两天可能还会单独写篇文章记录一下。

点赞 分享

发表评论

共有 0 条评论