最近更新频率慢了,这不是因为CK3发售了嘛,一个字就是“肝”。今天来看一下网易云音乐两个加密参数paramsencSecKey,顺便抓取一波某歌单的粉丝,有入库哦,使用mysql存储,觉得有帮助的别忘了关注一下公众号啊,完整的JS代码都已整理好,请关注知识图谱与大数据公众号,找到本文点击文末阅读更多获取。我的文章一般都有完整代码,创作不易啊,大家请多关注啊,当然不关注想白票也无所谓。

目标

网易云音乐只需要解密paramsencSecKey就可以开始快乐的抓取了,当然你没有足够的代理IP的话,还是要慢点爬,废话不多说,直接开整。

请求

老规矩,先看看我们要抓的页面样子:



查看网络请求:



从名字上就可以快速定位是哪个请求,是POST请求,那看看它提交了哪些参数吧,FormData如下:



提交的参数即前面提过的paramsencSecKey,是加密过的,看看返回的内容的格式:



ok,基本的东西我们都已经知道,可以进入下一步了找到解密两个参数了。

分析

调试前我们得先找到这两个值的位置,那就搜索呗,先定位JS文件再定位代码位置。怎么搜索应该都知道的吧,搜paramsencSecKey均可,搜出来多个结果不确定是哪个文件的话可以每个点进去再搜索一下关键参数,以此确定是否是目标文件,这里我直接标记了正确文件,大家点击进去即可。



进入JS文件后,同样搜索关键参数paramsencSecKey



找到了encSecKey的位置,把这几行代码抠出来分析一下:

         var bVZ8R = window.asrsea(JSON.stringify(i0x), bqN0x(["流泪", "强"]), bqN0x(Wx5C.md), bqN0x(["爱心", "女孩", "惊恐", "大笑"]));
e0x.data = j0x.cs1x({
params: bVZ8R.encText,
encSecKey: bVZ8R.encSecKey
})

粗略看,paramsencSecKey来自bVZ8R.encTextbVZ8R.encSecKey,而bVZ8Rwindow.asrsea的结果,window.asrsea有四个参数,JSON.stringify(i0x), bqN0x(["流泪", "强"]), bqN0x(Wx5C.md), bqN0x(["爱心", "女孩", "惊恐", "大笑"],先看后面三个参数,从它们固定的值可以大胆推测这三个值也是固定的。之所以说都是固定的,看看Wx5C.md



Wx5C.md是一个固定好的数组,而bqN0x(["流泪", "强"])bqN0x(["爱心", "女孩", "惊恐", "大笑"]这结果肯定也是不会变的,如下图,测试了一下:



大概弄清楚了这几个参数,剩下的就是搞明白window.asrsea的具体实现方式,还有i0x是什么样的,进入调试环节。

调试

window.asrsea打上断点,我的代码位置是13133行,点击粉丝列表下一页就会激活断点,在激活断点的同时我们也能一睹i0x的芳容,在控制台中输入i0x

limit、offset、total、userId这些其实都是可知的,而csrf_token的产生可以看这里,细心的童靴应该早就发现了:

           }
i0x["csrf_token"] = v0x.gP3x("__csrf"); ## csrf_token在这里产生
X0x = X0x.replace("api", "weapi");
e0x.method = "post";
delete e0x.query;
var bVZ8R = window.asrsea(JSON.stringify(i0x), bqN0x(["流泪", "强"]), bqN0x(Wx5C.md), bqN0x(["爱心", "女孩", "惊恐", "大笑"]));

我点进v0x.gP3x函数看了看:



从代码中可以看出csrf_token来自于Cookie中的__csrf:



那这个值就可以在请求网页的时候从cookie中获取到,继续调试window.asrsea吧。一路点击下一步,进入函数中。



跳到一个d(d,e,f,g)函数里,稍微往下一看,发现window.asrsea就等于这个d函数,哦了,那就调试这个d函数就行:

    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
}

进入a函数:



大概看出来a函数是产生随机数的,继续运行,进入b函数:



熟悉的AES加密,继续运行进入c函数:



又是熟悉的RSA加密,网易可真谨慎,各种加密。到这里总的框架已经调试完了,剩下的无非就是抠JS代码了。

python运行

这次不是单单运行了结果哦,还带上了爬取与入库:

获取paramsencSecKey

    def get_enc(self,a):
with open('..//js//wangyiyun.js', encoding='utf-8') as f:
wangyiyun = f.read()
js = execjs.compile(wangyiyun)
logid = js.call('get_pwd', a)
print(logid)
return logid

抓取

    def get_fans(self):
resp = self.get_home_page()
print(resp.cookies)
print(resp.status_code)
time.sleep(6)
limit = 20
for i in range(1,110):
print("第{}页".format(i+1))
offset = limit*i
a = {"userId": "46991111", "offset": str(offset), "total": "false", "limit": str(limit), "csrf_token": ""}
print(a)
logid = self.get_enc(a)
data = {
"params":logid["encText"],
"encSecKey":logid["encSecKey"],
}
print(data)
fans_url = "https://music.163.com/weapi/user/getfolloweds?csrf_token="
resp = self.session.post(url=fans_url,data=data,headers=self.headers)
followed = json.loads(resp.text)
followed_list = []
for foll in followed["followeds"]:
foll_dict = {}
foll_dict["short_name"] = foll.get("py","") #缩写
foll_dict["userId"] = foll.get("userId","") #用户ID
foll_dict["nickname"] = foll.get("nickname","") #昵称
foll_dict["vipType"] = foll.get("vipType","") # vip
foll_dict["eventCount"] = foll.get("eventCount","")#动态
foll_dict["vipRights"] = str(foll.get("vipRights","")) #VIP权益
foll_dict["gender"] = foll.get("gender","") #性别
foll_dict["avatarUrl"] = foll.get("avatarUrl","") #头像
foll_dict["followed"] = foll.get("followed","")
foll_dict["followeds"] = foll.get("followeds","") #粉丝
foll_dict["follows"] = foll.get("follows","") #关注
foll_dict["playlistCount"] = foll.get("playlistCount","") #歌单
foll_dict["mutual"] = foll.get("mutual","") #
foll_dict["expertTags"] = str(foll.get("expertTags",""))
foll_dict["experts"] = str(foll.get("experts",""))
print(foll_dict)
followed_list.append(foll_dict)
self.mysql.insert("music",followed_list)
tm = random.randint(10,30)
time.sleep(tm)

这里要注意一下,要抓取指定的页面你还得先访问这个页面,不能直接请求"https://music.163.com/weapi/user/getfolloweds?csrf_token=这个链接,因为它根本就没有带关于哪个页面的信息。

请求指定网页

    def get_home_page(self):
url = "https://music.163.com/#/user/home?id=1737833656"
resp = self.session.get(url)
return resp

表结构

    @property
def create_table_sql(self):
create_table = """
CREATE TABLE IF NOT EXISTS music (
short_name varchar(30) ,
userId varchar(100) NOT NULL,
nickname varchar(30),
vipType varchar(30) ,
eventCount varchar(200),
vipRights varchar(900),
gender varchar(900),
avatarUrl varchar(200),
followed varchar(30),
followeds varchar(30),
follows varchar(30),
playlistCount varchar(30),
mutual varchar(30),
expertTags varchar(30),
experts varchar(30),
PRIMARY KEY (userId)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"""
return create_table

入库

 def insert(self,table,data_list):
if len(data_list) > 0:
data_list = [{k: v
for k, v in data.items() if v is not None}
for data in data_list] keys = ", ".join(data_list[0].keys())
values = ", ".join(["%s"] * len(data_list[0]))
sql = """INSERT INTO {table}({keys}) VALUES ({values}) ON
DUPLICATE KEY UPDATE""".format(table=table,
keys=keys,
values=values)
update = ",".join([
" {key} = values({key})".format(key=key)
for key in data_list[0]
])
sql += update
print(sql)
self.connect()
try:
ret = self.cursor.executemany(sql, [tuple(data.values()) for data in data_list])
self.conn.commit()
except Exception as e:
self.conn.rollback()
print("Error: ", e)
traceback.print_exc()
finally:
self.close()

过程

结束

快乐的时光过得真快,到这里就结束了,抓取过程与入库大家可以作为一个参考。完整的JS代码都已整理好,请关注知识图谱与大数据公众号,找到本文点击文末阅读更多获取,创作不易,请多关注,当然不关注也无所谓。

这个网易云JS解密,老网抑云看了都直呼内行的更多相关文章

  1. Web前端:博客美化:四、网易云音乐单曲播放器

    1.页面定制CSS代码 /*3.音乐播放器*/ .content-wrap { overflow-y: scroll; -webkit-overflow-scrolling: touch; } /* ...

  2. 来自网易云的黑科技,带尖角的div......

    今天在网易云的网页版听歌,话说Steve Vai的曲子永远是这么让人揣摩不透,不过我还时更喜欢老Joe,咦,跑题了··· 大家可以看到评论输入框和回复框,上面都有个小尖角,实现的方式有很多,我一般是用 ...

  3. 爬虫实战(二) 用Python爬取网易云歌单

    最近,博主喜欢上了听歌,但是又苦于找不到好音乐,于是就打算到网易云的歌单中逛逛 本着 "用技术改变生活" 的想法,于是便想着写一个爬虫爬取网易云的歌单,并按播放量自动进行排序 这篇 ...

  4. 用其他音乐源帮帮网易云,Ubuntu听歌利器

    镜像文章 1.用其他音乐源帮帮网易云,Android听歌利器 2.用其他音乐源帮帮网易云,Windows听歌利器 众所周知,国内只有网易云推出了Linux的客户端,在Listen 1并不十分好用的基础 ...

  5. ubuntu16.04 安装网易云音乐

    最爱的播放器 网易云音乐 哈哈,刚刚折腾了双系统,立马开始了软件安装. 网易云音乐从官网下载对应的 64 位版本,我下载的是 netease-cloud-music_1.0.0_amd64_ubunt ...

  6. 解决Windows x86网易云音乐不能将音乐下载到SD卡的BUG

    由于我个人最常用的电脑是Surface pro4 256G版本,装了不少生产力空间还挺吃紧的,音乐之类的必然都存单独的SD卡里.用UWP版本的网易云音乐倒是没问题,最近问题来了,UWP版本的网易云音乐 ...

  7. KEUC首次落地中国,网易云深度剖析Kubernetes优化与实践

    本文由  网易云发布. 10 月 15 日,聚焦 Kubernetes 中国行业应用与技术落地的首届中国 Kubernetes 用户大会(KEUC)在杭州成功举办.本次大会吸引了来自全球各地的技术精英 ...

  8. 网易云基于 Kubernetes 的深度定制化实践

    本文由  网易云发布. 2017 年,Kubernetes 超越 Mesos 和 Docker Swarm成为最受欢迎的容器编排技术.网易云从 2015 下半年开始向 Kubernetes 社区贡献代 ...

  9. 网易云易盾与A10 Networks达成战略合作 携手打造抗DDoS攻击的解决方案

    欢迎访问网易云社区,了解更多网易技术产品运营经验. 2018年9月,网易云易盾宣布,与智能和自动化网络安全解决方案提供商A10 Networks结成战略合作伙伴关系.双方将在抗DDoS攻击领域展开深入 ...

随机推荐

  1. 编程体系结构(01):Java编程基础

    一.数据类型 1.基础类型 整型:byte .short .int .long 浮点型:float.double 字节型:char 2.包装类型 Byte,Short,Integer,Long Flo ...

  2. 知识点干货——CSS动画

    CSS动画 (transition.animation) //2D动画 transform:translate(); /*偏移*/ transform:rotate(); /*旋转角度*/ trans ...

  3. leetcode刷题-53最大子序和

    题目 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 思路 动态规划:求整个数组的连续子数组的最大和,可以求出每个位置的连续子数组的最大和,返回 ...

  4. ES ElasticSearch 7.x 下动态扩大索引的shard数量

    ES ElasticSearch 7.x 下动态扩大索引的shard数量 背景 在老版本的ES(例如2.3版本)中, index的shard数量定好后,就不能再修改,除非重建数据才能实现. 从ES6. ...

  5. 【API进阶之路】用API打造一条自动化内容生产流水线

    摘要:搞定了内容审核之后,我又把抓取工具.内容审核API.文本摘要生成API串联在一起,从抓到审再到编,建立了一条自动化的内容生产流水线,编辑团队只需要做优质内容的推荐就可以了. 上周,运营部将官网上 ...

  6. 2020重新出发,NOSQL,MongoDB分布式集群架构

    MongoDB分布式集群架构 看到这里相信你已经掌握了 MongoDB 的大部分基本知识,现在在单机环境下操作 MongoDB 已经不存在问题,但是单机环境只适合学习和开发测试,在实际的生产环境中,M ...

  7. [业界方案]用Jaeger来学习分布式追踪系统Opentracing

    [业界方案]用Jaeger来学习分布式追踪系统Opentracing 目录 [业界方案]用Jaeger来学习分布式追踪系统Opentracing 0x00 摘要 0x01 缘由 & 问题 1. ...

  8. 如何编写一个简单的Linux驱动(二)——设备操作集file_operations

    前期知识 如何编写一个简单的Linux驱动(一)--驱动的基本框架 前言 在上一篇文章中,我们学习了驱动的基本框架.这一章,我们会在上一章代码的基础上,继续对驱动的框架进行完善.要下载上一篇文章的全部 ...

  9. UI中table写表格

  10. k8s控制器资源

    k8s控制器资源   Pod pod在之前说过,pod是kubernetes集群中是最小的调度单元,pod中可以运行多个容器,而node又可以包含多个pod,关系如下图: 在对pod的用法进行说明之前 ...