python爬虫获取网易云音乐评论歌词以及歌曲地址

python爬虫获取网易云音乐评论歌词以及歌曲地址

  • 一.寻找数据接口
  • 二.对负载分析
  • 三.寻找参数加密过程
    • 1.首先找到评论的请求包并找到发起程序
    • 2.寻找js加密的代码
  • 四.扣取js的加密源码
    • 1.加密函数参数分析
      • ①.JSON.stringify(i0x)
      • ②bse6Y(["流泪", "强"])
      • ③bse6Y(Qu1x.md)
      • ④.bse6Y(["爱心", "女孩", "惊恐", "大笑"])
    • 1.加密函数分析
  • 五.在本地环境使用此函数
    • 1.直接将js代码复制并用js环境运行
    • 2.将js代码翻译为python代码
  • 六.python代码

一.寻找数据接口

评论
url:https://music.163.com/weapi/comment/resource/comments/get
在这里插入图片描述

在这里插入图片描述
歌词
url:https://music.163.com/weapi/song/lyric
在这里插入图片描述

在这里插入图片描述

歌曲地址
url:https://music.163.com/weapi/song/enhance/player/url/v1
在这里插入图片描述

二.对负载分析

从三个接口的负载我们可以得出

data={
params:加密数据
encSecKey:加密数据
}

所以我们只需要找出这个两个参数的加密过程就能模拟请求并得到我们想要的数据

三.寻找参数加密过程

因为这三个接口的加密是一样的这里我们用评论的接口来讲解

1.首先找到评论的请求包并找到发起程序

在这里插入图片描述
f12打开调试并且点击网络然后找到对应的包https://music.163.com/weapi/comment/resource/comments/get
点击发起程序

2.寻找js加密的代码

我们先点击发起程序的第一个进入到js文件中找到请求发出的地方也就是
send()函数

先加个断点然后刷新页面(下图)
在这里插入图片描述

在这里插入图片描述


刷新后我们就可以看到调用栈然后从第一个往下点一直找到send()(上图)


在这里插入图片描述
找到send()后我们取消掉前面的断点并给send()打上断点然后再次刷新网页(上图)
在这里插入图片描述

这个url代表的是此次请求发送的url我们评论的url为https://music.163.com/weapi/comment/resource/comments/get所以我们点击上面的小三角放过此次请求直至抓取到我们所需的请求(上图)
在这里插入图片描述
在这里插入图片描述
我们现在就抓取到了评论请求的data数据等信息我们可以看到此时的信息还是加密的所以我们要继续向前找寻找到它未加密的地方(上图)
在这里插入图片描述
data的加密数据在t0x这个调用栈前面是没有的所以我们就能确定数据是在这个调用栈中被加密然后我们ctrl+ F 直接搜索params就定位到了加密的函数

四.扣取js的加密源码

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

根据上一步我们找到的源码我们可以看出
我们所需的两个加密数据 params,encSecKey都是由 bVi6c产生的
bVi6c是由 这个函数生成的所以只需要取出这个函数的加密过程就能模拟出我们的加密数据

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

1.加密函数参数分析

我们先给函数打上断点然后刷新网页
在这里插入图片描述
和上面的步骤一样还是需要点击三角知道找到我们所需的接口

①.JSON.stringify(i0x)

JSON.stringify()
JSON.stringify 是 JavaScript 中的一个全局函数,用于将一个 JavaScript 值(如 JavaScript 对象或数组)转换为 JSON 格式的字符串。这对于将数据保存到文件、在网页之间传递数据、或发送到服务器(例如通过 AJAX 请求)非常有用,因为 JSON 是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。
这个函数的作用就是将i0x转换为json格式
我们点击控制台然后输入i0x就可以得到i0x的值

{"rid": "R_SO_4_28188263","threadId": "R_SO_4_28188263","pageNo": "1","pageSize": "20","cursor": "-1","offset": "0","orderType": "1","csrf_token": "71bfd80a0c48b6dbdef22c1499cd480c"
}

rid与threadId就是歌的id
csrf_token是用户的登录状态
剩下的就是关于评论的参数

使用JSON.stringify()函数将i0x转换后我们就得到了第一个参数

②bse6Y([“流泪”, “强”])

第二个参数我们可以看出他是一个函数的返回值他的参数是[“流泪”, “强”]所以我们认为他的值是固定的
我们只需要在控制台输入bse6Y([“流泪”, “强”])就可以得到第二个参数的值
在这里插入图片描述
bse6Y([“流泪”, “强”])=‘010001’

③bse6Y(Qu1x.md)

首先我们要获取Qu1x.md的值我们直接控制台输入Qu1x.md
在这里插入图片描述

['色', '流感', '这边', '弱', '嘴唇', '亲', '开心', '呲牙', '憨笑', '猫', '皱眉', '幽灵', '蛋糕', '发怒', '大哭', '兔子', '星星', '钟情', '牵手', '公鸡', '爱意', '禁止', '狗', '亲亲', '叉', '礼物', '晕', '呆', '生病', '钻石', '拜', '怒', '示爱', '汗', '小鸡', '痛苦', '撇嘴', '惶恐', '口罩', '吐舌', '心碎', '生气', '可爱', '鬼脸', '跳舞', '男孩', '奸笑', '猪', '圈', '便便', '外星', '圣诞']

所以bse6Y(Qu1x.md)值也是固定的
在这里插入图片描述
在这里插入图片描述

bse6Y(Qu1x.md)=‘00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7’

④.bse6Y([“爱心”, “女孩”, “惊恐”, “大笑”])

和参数二一样他也是一个固定值直接控制台输出

bse6Y(["爱心", "女孩", "惊恐", "大笑"])='0CoJUm6Qyw8W8jud'

1.加密函数分析

window.asrsea(JSON.stringify(i0x), bse6Y(["流泪", "强"]), bse6Y(Qu1x.md), bse6Y(["爱心", "女孩", "惊恐", "大笑"]))

我们已经得到了window.asrsea()的参数现在只有找到此函数的源码就可以模拟加密了
我们直接ctrl+F搜索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,
}();

这就是加密函数

五.在本地环境使用此函数

1.直接将js代码复制并用js环境运行

python如何执行js代码: https://blog.csdn.net/python_9k/article/details/138562809
Node.js安装与配置(详细步骤): https://blog.csdn.net/qq_42006801/article/details/124830995

2.将js代码翻译为python代码

如果读不懂js代码直接复制给ai来使用

这段JavaScript代码定义了一系列函数,用于生成随机字符串、使用AES加密、使用RSA加密,以及组合这些加密步骤来形成最终的加密数据。下面是对这些函数及其作用的详细解释:
1. a(a)
•  功能:生成一个长度为a的随机字符串,字符串由字母(大小写)和数字组成。
•  实现:使用Math.random和Math.floor生成随机索引,从字符集b中选取字符,最终拼接成一个随机字符串。
2. b(a, b)
•  功能:使用AES算法加密字符串a,密钥是b。
•  实现:使用CryptoJS库中的AES加密方法,采用CBC模式,IV(初始化向量)固定为0102030405060708,加密后返回加密字符串的Base64编码。
3. c(a, b, c)
•  功能:使用RSA算法加密字符串a,公钥由b和c组成(b是公钥的指数,c是模数)。
•  实现:使用RSAKeyPair创建一个RSA公钥,然后使用encryptedString方法加密字符串a。
4. d(d, e, f, g)
•  功能:组合AES和RSA加密,首先使用AES加密d,然后对加密后的AES密钥再进行一次AES加密,并使用RSA加密生成的随机字符串i。
•  实现: 
•  生成16位随机字符串i。
•  使用g作为AES密钥加密d。
•  使用i作为新的AES密钥再次加密前一步的输出。
•  使用RSA公钥(e和f)加密i。
•  返回一个对象,包含encText(两次AES加密后的结果)和encSecKey(RSA加密后的结果)。
5. e(a, b, d, e)
•  功能:使用RSA算法加密字符串a加上e,公钥由b和d组成。
•  实现:与c函数相似,但是将a + e作为要加密的字符串。
6. window.asrsea = d
•  功能:将d函数绑定到window对象的asrsea属性上,使其在全局范围内可用。
加密步骤总结
•  首先,生成一个随机字符串i。
•  使用g作为AES密钥加密原始数据d。
•  再次使用i作为AES密钥加密上一步的结果。
•  最后,使用RSA公钥加密i,生成encSecKey。
•  返回一个包含encText(两次AES加密的结果)和encSecKey(RSA加密的结果)的对象。
这种加密策略通常用于网络请求中,尤其是音乐流媒体服务或API接口,以保护数据在传输过程中的安全。

六.python代码

main.py


from Crypto.Cipher import AES
import base64
from Crypto.Util.Padding import pad
import requests
from jiami import Ajimport re
def gdata(decrypt_str):key_str = '0CoJUm6Qyw8W8jud'iv_str = "0102030405060708"a = "ouPO61mhRSoLJEwz"encrypt_str = aes_cbc_encrypt_text(decrypt_str, key_str, iv_str)encrypt_str = aes_cbc_encrypt_text(encrypt_str, a, iv_str)return encrypt_strdef idh():name = input('请输入歌名: ')i1x = {'csrf_token': "",'limit': "8",'s': name}data = i1xaj = Aj(data)url = 'https://music.163.com/weapi/search/suggest/web'res = requests.post(url, data={'params': aj.getparams(data), 'encSecKey': aj.getenseckey()})return str(res.json()["result"]["songs"][0]["id"])def aes_cbc_encrypt_text(decrypt_text: str, key: str, iv: str) -> str:"""加密AES_CBC的明文:param decrypt_text: 明文:param key: 密钥:param iv: 密钥偏移量:return: 密文"""aes2 = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))encrypt_text = aes2.encrypt(pad(decrypt_text.encode('utf-8'), AES.block_size, style='pkcs7'))encrypt_text = str(base64.encodebytes(encrypt_text), encoding='utf-8').replace("\n", "")return encrypt_textidd=idh()
rid='R_SO_4_'+idd# AES_CBC加密模式
decrypt_str = "{\"ids\":\"["+str(idd)+"]\",\"level\":\"standard\",\"encodeType\":\"aac\"}"
decrypt_str2='{\"rid\": \"%s\",\"threadId\": \"%s\",\"pageNo\": \"1\",\"pageSize\": \"20\",\"cursor\": \"-1\",\"offset\": \"0\",\"orderType\": \"1\"}'%(rid,rid)
decrypt_str3='{\"id\":\"%s\",\"lv\": \"-1\",\"tv\":\"-1\"}'%iddparams=gdata(decrypt_str)
params2=gdata(decrypt_str2)
params3=gdata(decrypt_str3)
encSecKey="c13dc213bd5889986ef8a7af39406c640bf77c6a5a34fe86324b648708b3af49919368a2d555771ea5453a605be7bfeaca0860696a9a9889e24a925bfeb56455f7275e534e733eaa5f94392d7b75da0701b8f38a3006bd6cd10cce66d64daa39f6dd12f970421d79b91abc8116012ee4f2dc8c7648c527abc22158b0338a9171"
url='https://music.163.com/weapi/song/enhance/player/url/v1?'
url2='https://music.163.com/weapi/comment/resource/comments/get?'
url3='https://music.163.com/weapi/song/lyric'
data={'params': params,
'encSecKey': encSecKey
}
data2={
'params': params2,
'encSecKey': encSecKey
}
data3={
'params': params3,
'encSecKey': encSecKey
}
res=requests.post(url,data=data)
res2=requests.post(url2,data=data2)
res3=requests.post(url3,data=data3)
print("评论:")
for i in res2.json()["data"]["comments"]:print(i["content"])
#print(res.text)
print('___________________________________________________________________')
print("歌曲url:")
print(res.json()['data'][0]['url'])
print('___________________________________________________________________')
print("歌词:")
txt=res3.json()["lrc"]
list=re.findall(r'\[(.*?)\](.*?)\\n',str(txt),re.S)
for i in list:print(i[1])

jiami.py

from Crypto.Cipher import AES
from base64 import b64encode
import jsonclass Aj:g='0CoJUm6Qyw8W8jud'i="7HCEonr7xwebMhJV"def __init__(self,data):self.data=datadef getenseckey(self):return "774c6922c77e2d39c9ec18d91210752d86517dee1ab731b3f8a41306ef5b92bc5809105f6cd679375d557dbf59746e1ace6b5a8a313efd70d3c645d198e3e509dbb61776926032eaccfa92c6f5921c8672baf3a2fd5d6d08c1a6869200fbb5e3191902026144060d6e58afcd9ef95f8be592fa80a25791c5b51a1264905026cf"def jiamiAES(self,data, key):# data=data.encode("utf-8")iv = '0102030405060708'aes = AES.new(key=key.encode("utf-8"), IV=iv.encode("utf-8"), mode=AES.MODE_CBC)bs = aes.encrypt(data.encode("utf-8"))return str(b64encode(bs), "utf-8")def getparams(self,data):data = json.dumps(data)data = self.to_16(data)t1 = self.jiamiAES(data,self.g)t2 = self.jiamiAES(self.to_16(t1),self.i)return t2def to_16(self,data):pad = 16 - len(data) % 16data += chr(pad) * padreturn data

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/379803.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法日记day 11(KMP算法)

一、KMP算法 基本原理: KMP算法(Knuth-Morris-Pratt算法)是一种用于在一个文本串(字符串)中查找一个模式串(子串)的高效算法。它的主要优点是在匹配过程中避免了回溯(backtracking…

新版网页无插件H.265播放器EasyPlayer.js如何测试demo视频?

H5无插件流媒体播放器EasyPlayer属于一款高效、精炼、稳定且免费的流媒体播放器,可支持多种流媒体协议播放,支持H.264与H.265编码格式,性能稳定、播放流畅;支持WebSocket-FLV、HTTP-FLV,HLS(m3u8&#xff0…

cleanshot Mac 上的截图工具

笔者闲来无事,最近在找一些mac上好用的工具其中一款就是cleanShot。为什么不用原有的mac自带的呢。因为相对来说编辑功能不算全面,不支持长截图。那有没有一款软件支持关于截图的好用工具呢。 所以笔者找了这款。安装包是直接安装就可使用的。请大家点赞…

MATLAB quiver矢量图 设置colorbar

给三维矢量图按照不同高度设置箭头颜色 figure clf X surfaceuz(:,1); Y surfaceuz(:,2); Z surfaceuz(:,3); hold onzcolor jet; % qquiver3(X,Y,Z,X,Y,W) for i 1:length(surfaceuz)quiver3(X(i),Y(i),Z(i),X(i),Y(i), Z(i),...Color,zcolor(floor((Z(i) - -0.1) * 2…

【Linux学习】常用基本指令

🔥个人主页: Forcible Bug Maker 🔥专栏:Linux学习 目录 🌈前言🔥XShell的一些使用查看Linux主机IP使用XShell登录主机XShell下的复制粘贴 🔥Linux下常用基本指令ls指令pwd指令cd指定touch指令…

【JVM基础02】——组成-程序计数器解读

目录 1- 引言:程序计数器1-1 程序计数器是什么?为什么用程序计数器?(What)(Why) 2- 核心:程序计数器的原理(How)2-1 使用 javap 查看程序计数器的作用2-2 多线程下程序计数器原理举例 3- 小结:什…

完美解决ImportError: cannot import name ‘PILLOW_VERSION‘的正确解决方法,亲测有效!!!

完美解决ImportError: cannot import name PILLOW_VERSION’的正确解决方法,亲测有效!!! 亲测有效 完美解决ImportError: cannot import name PILLOW_VERSION的正确解决方法,亲测有效!!&#xf…

专业PDF编辑工具:Acrobat Pro DC 2024.002.20933绿色版,提升你的工作效率!

软件介绍 Adobe Acrobat Pro DC 2024绿色便携版是一款功能强大的PDF编辑和转换软件,由Adobe公司推出。它是Acrobat XI系列的后续产品,提供了全新的用户界面和增强功能。用户可以借助这款软件将纸质文件转换为可编辑的电子文件,便于传输、签署…

pdf提取其中一页怎么操作?提取PDF其中一页的方法

pdf提取其中一页怎么操作?需要从一个PDF文件中提取特定页码的操作通常是在处理文档时常见的需求。这种操作允许用户选择性地获取所需的信息,而不必操作整个文档。通过选择性提取页面,你可以更高效地管理和利用PDF文件的内容,无论是…

通过docker构建基于LNMP的WordPress项目

目录 1.准备nginx 2.准备mysql 3.准备php 4.构建各镜像 5.运行wordpress 1、项目环境: 1.1 (1)公司在实际的生产环境中,需要使用Docker 技术在一台主机上创建LNMP服务并运行Wordpress网站平台。然后对此服务进行相关的性能…

01数据结构 - 顺序表

这里是只讲干货不讲废话的炽念,这个系列的文章是为了我自己以后复习数据结构而写,所以可能会用一种我自己能够听懂的方式来描述,不会像书本上那么枯燥和无聊,且全系列的代码均是可运行的代码,关键地方会给出注释^_^ 全…

大数据面试SQL题-笔记01【运算符、条件查询、语法顺序、表连接】

大数据面试SQL题复习思路一网打尽!(文档见评论区)_哔哩哔哩_bilibiliHive SQL 大厂必考常用窗口函数及相关面试题 大数据面试SQL题-笔记01【运算符、条件查询、语法顺序、表连接】大数据面试SQL题-笔记02【...】 目录 01、力扣网-sql题 1、高频SQL50题&#xff08…

51单片机STC89C52RC——19.1 SG90舵机(伺服电机)

目的/效果 独立按键K1,K2 实现加舵机减角度增减,LCD1602显示舵机转角度数(上电默认90度) 一,STC单片机模块 二,SG90舵机 2.1 简介 舵机只是我们通俗的叫法,它的本质是一个伺服电机&#xf…

VPN以及GRE和MGRE

VPN VPN — 是虚拟专用网络 通俗地说,就是通过虚拟的手段,将两个独立的网络,穿越一个公共网络进行连接,实现点到点专线的效果(可以理解为:一个分公司通过公网和总公司建立点到点的专线连接) 现…

【MQTT(3)】开发一个客户端,QT-Android安卓手机版本

手机版本更加方便 生成安卓库 参考了这个代码 在编译Mosquitto以支持安卓平台时,主要涉及到使用Android NDK(Native Development Kit)进行交叉编译。环境的准备参考之前的博客【QT开发(17)】2023-QT 5.14.2实现Andr…

单链表算法 - 链表的回文结构

链表的回文结构_牛客题霸_牛客网对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为。题目来自【牛客题霸】https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa思路1: /* struct ListNode {int val;st…

字节面试:如何让单机下Netty支持百万长连接?

最近有同学在面试遇到了一道非常有深度的面试题: 如何让单机下Netty支持百万长连接? 当时在群里问小北,我发现我也没有系统化的梳理过这个问题,所以一时也没有回答的特别好。 痛定思痛的我赶紧去各种搜集资料,系统化的…

unity渲染人物模型透明度问题

问题1:有独立的手和衣服的模型,但最终只渲染出来半透明衣服 问题2:透明度贴图是正确的但显示却不正确 这上面两个模型的问题都是因为人物模型是一个完整的,为啥有些地方可以正常显示,有些地方透明度却有问题。 其中…

数据结构小测试:排序算法

目录 1、请简述数据结构八大排序算法的思路。 2、常用排序算法手写 冒泡排序: 选择排序: 快速排序: 归并排序: 堆排序: 3、额外再加一个二分查找吧 1、请简述数据结构八大排序算法的思路。 冒泡排序&#xff…

亚信安全发布2024年第24期《勒索家族和勒索事件监控报告》

本周态势快速感知 本周,勒索软件LockBit涉嫌对美国一家生产乙烯基产品的公司(Homeland Vinyl)进行攻击。LockBit声称他们已窃取了销售、库存、财务交易数据及其他公司记录,并声明将于2024年7月19日公开这些被盗信息。本周全球共监…