最近更新频率慢了,这不是因为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. EventDispatcher

    事件分发类,提供事件注册.移除.触发功能 采用delegate.dictionary实现 支持自定义事件.事件采用字符串方式标识 支持 0,1,2,3,4 等5种不同参数个数的回调函数   // 路由 ...

  2. Unity使用可空类型(Nullable Types)

    译林军 范春彦|2014-04-09 09:46|5407次浏览|Unity(375)0 你怎么确定一个Vector3,int,或float变量是否被分配了一个值?一个方便的方式就是使用可空类型! 有 ...

  3. Fragment的跳转

    1. 设置主Fragment 其它fragment得到它就可以了. 1 val ft = fragmentManager?.beginTransaction() 2 val maiFrgmt = Ma ...

  4. vue学习笔记一

    vue 颠覆式的开发方式 解疑 为什么要学习vue? 降低项目的复杂度 就业需要 vue难不难? 特别简单 相比于React,vue有什么优势? 前端三大框架:Angular.React.Vue Vu ...

  5. 软件架构与设计 百度网盘的pdf电子书籍

    如有版权问题请及时联系小编 软件架构与设计 百度网盘的pdf电子书籍 1:<软件体系结构(PDF)>https://pan.baidu.com/s/1lChfIJt5lc63KO09n5L ...

  6. VMware Workstation Pro15安装路径、修复等问题

    我的VMware Worstation 昨晚报错,无法打开虚拟机,VMware Authorization Services 也无法启动,于是卸载重装,结果仍然无法启动VMware Authoriza ...

  7. 小白也能弄懂的目标检测之YOLO系列 - 第一期

    大家好,上期分享了电脑端几个免费无广告且实用的录屏软件,这期想给大家来讲解YOLO这个算法,从零基础学起,并最终学会YOLOV3的Pytorch实现,并学会自己制作数据集进行模型训练,然后用自己训练好 ...

  8. Agumaster点个按钮后台刷新前台一步步出状态

    --2020年5月4日--

  9. leetcode刷题-89格雷编码

    题目 格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异. 给定一个代表编码总位数的非负整数 n,打印其格雷编码序列.即使有多个不同答案,你也只需要返回其中一种. 格雷编码序列 ...

  10. Apache2.4 下载和安装 - Win10

    Apache安装包已放入百度网盘,链接地址在本文最后 1.下载Windows版本的Apahce安装包 a. 访问官网,进入下载页面 https://www.apachelounge.com (apac ...