小编给大家分享一下网易云音乐热评爬虫中怎么用python实现反编译加密参数,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
发现如下接口包含所要的数据。包含该页最新评论,以及所有热评
再看它评论的参数,着实让人有点懵逼
很多人看见这一串字符,可能简单看下前后接口有没数据就放弃了。好了,不卖关子。这章分析下整个参数的加密过程,实现最终模拟请求拿到数据。
可以看的到,它的参数有两个,一个是params,一个是encSecKey并且都是经过加密的,我们就要分析它在js中的位置(F12打开source搜索encSecKey)
进入js内部,经过断点调试发现这里就是生成最终参数的地方
模拟不同分页请求,观察变化。效果如下图:
对比参数变化,得出参数构成:
csrf_token :始终空字符串
cursor :第一页默认-1;请求下一页时该参数为上一页最后一条评论时间戳(防止数据重复)
offset :移动评论数
orderType :默认1
pageNo :页码
pageSize :默认20
rid : R_SO_4_ + 歌曲ID
threadId : R_SO_4_ + 歌曲ID
自此,我们已经知道整个参数的构成,接下来就看下网易云是如何进行参数加密的
通过断点已经知道,下面这段js代码为我们分析的重点
var bZj0x = window.asrsea(JSON.stringify(i2x), bkk0x(["流泪", "强"]), bkk0x(YS7L.md), bkk0x(["爱心", "女孩", "惊恐", "大笑"])); e2x.data = j2x.cr3x({ params: bZj0x.encText, encSecKey: bZj0x.encSecKey })
只要把bZj0x解出来就ok了,这里主要分析几个函数
断点调制找到i2x返回内容
就是上文分析的整个字典参数
csrf_token: "" cursor: "1610076350235" offset: "40" orderType: "1" pageNo: "2" pageSize: "20" rid: "R_SO_4_1807537867" threadId: "R_SO_4_1807537867"
bkk0x(["流泪", "强"]), bkk0x(YS7L.md), bkk0x(["爱心", "女孩", "惊恐", "大笑"]),都用到了同一个函数,这里就看下bkk0x函数内部实现是怎样的
var bkk0x = function(cJj8b) { var m2x = []; j2x.bf2x(cJj8b, function(cJi8a) { m2x.push(YS7L.emj[cJi8a]) }); return m2x.join("") }
等同于python写法
def get_bq_n1x(keys): m0x = [] for key in keys: m0x.append(emj[key]) return ''.join(m0x)
YS7L.emj是一个固定的字典
YS7L.emj = { "色": "00e0b", "流感": "509f6", "这边": "259df", "弱": "8642d", "嘴唇": "bc356", "亲": "62901", "开心": "477df", "呲牙": "22677", "憨笑": "ec152", "猫": "b5ff6", "皱眉": "8ace6", "幽灵": "15bb7", "蛋糕": "b7251", "发怒": "52b3a", "大哭": "b17a8", "兔子": "76aea", "星星": "8a5aa", "钟情": "76d2e", "牵手": "41762", "公鸡": "9ec4e", "爱意": "e341f", "禁止": "56135", "狗": "fccf6", "亲亲": "95280", "叉": "104e0", "礼物": "312ec", "晕": "bda92", "呆": "557c9", "生病": "38701", "钻石": "14af6", "拜": "c9d05", "怒": "c4f7f", "示爱": "0c368", "汗": "5b7a4", "小鸡": "6bee2", "痛苦": "55932", "撇嘴": "575cc", "惶恐": "e10b4", "口罩": "24d81", "吐舌": "3cfe4", "心碎": "875d3", "生气": "e8204", "可爱": "7b97d", "鬼脸": "def52", "跳舞": "741d5", "男孩": "46b8e", "奸笑": "289dc", "猪": "6935b", "圈": "3ece0", "便便": "462db", "外星": "0a22b", "圣诞": "8e7", "流泪": "01000", "强": "1", "爱心": "0CoJU", "女孩": "m6Qyw", "惊恐": "8W8ju", "大笑": "d" }
YS7L.md是一个固定的数据
YS7L.md = ["色", "流感", "这边", "弱", "嘴唇", "亲", "开心", "呲牙", "憨笑", "猫", "皱眉", "幽灵", "蛋糕", "发怒", "大哭", "兔子", "星星", "钟情", "牵手", "公鸡", "爱意", "禁止", "狗", "亲亲", "叉", "礼物", "晕", "呆", "生病", "钻石", "拜", "怒", "示爱", "汗", "小鸡", "痛苦", "撇嘴", "惶恐", "口罩", "吐舌", "心碎", "生气", "可爱", "鬼脸", "跳舞", "男孩", "奸笑", "猪", "圈", "便便", "外星", "圣诞"]
所以整个window.asrsea的参数都是可以得到的了,下面看下 window.asrsea()查看这个函数执行了什么操作
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.asrsea = d,所以我们要执行的就是d这个函数,主要执行3个操作
a(16),生成16位随机数
进行两次AES加密得到h.encText
通过位移等一系列运算生成h.encSecKey
""" 网易云请求参数反编译工具 :主要断点观察js,改为python实现 """ emj = { "色": "00e0b", "流感": "509f6", "这边": "259df", "弱": "8642d", "嘴唇": "bc356", "亲": "62901", "开心": "477df", "呲牙": "22677", "憨笑": "ec152", "猫": "b5ff6", "皱眉": "8ace6", "幽灵": "15bb7", "蛋糕": "b7251", "发怒": "52b3a", "大哭": "b17a8", "兔子": "76aea", "星星": "8a5aa", "钟情": "76d2e", "牵手": "41762", "公鸡": "9ec4e", "爱意": "e341f", "禁止": "56135", "狗": "fccf6", "亲亲": "95280", "叉": "104e0", "礼物": "312ec", "晕": "bda92", "呆": "557c9", "生病": "38701", "钻石": "14af6", "拜": "c9d05", "怒": "c4f7f", "示爱": "0c368", "汗": "5b7a4", "小鸡": "6bee2", "痛苦": "55932", "撇嘴": "575cc", "惶恐": "e10b4", "口罩": "24d81", "吐舌": "3cfe4", "心碎": "875d3", "生气": "e8204", "可爱": "7b97d", "鬼脸": "def52", "跳舞": "741d5", "男孩": "46b8e", "奸笑": "289dc", "猪": "6935b", "圈": "3ece0", "便便": "462db", "外星": "0a22b", "圣诞": "8e7", "流泪": "01000", "强": "1", "爱心": "0CoJU", "女孩": "m6Qyw", "惊恐": "8W8ju", "大笑": "d" } md = ["色", "流感", "这边", "弱", "嘴唇", "亲", "开心", "呲牙", "憨笑", "猫", "皱眉", "幽灵", "蛋糕", "发怒", "大哭", "兔子", "星星", "钟情", "牵手", "公鸡", "爱意", "禁止", "狗", "亲亲", "叉", "礼物", "晕", "呆", "生病", "钻石", "拜", "怒", "示爱", "汗", "小鸡", "痛苦", "撇嘴", "惶恐", "口罩", "吐舌", "心碎", "生气", "可爱", "鬼脸", "跳舞", "男孩", "奸笑", "猪", "圈", "便便", "外星", "圣诞"] def get_bq_n1x(keys): m0x = [] for key in keys: m0x.append(emj[key]) return ''.join(m0x) def __get_random_str(): """ Returns:16位的随机字符串 """ str_set = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" random_str = "" for i in range(16): index = random.randint(0, len(str_set) - 1) random_str += str_set[index] return random_str arg2 = get_bq_n1x(["流泪", "强"]) arg3 = get_bq_n1x(md) arg4 = get_bq_n1x(["爱心", "女孩", "惊恐", "大笑"]) random_str = __get_random_str() def __aes_encrypt(text, key): """ 获取到ASW加密后的数据 Args: text: 首先CBC加密方法,text必须位16位数据 key: 加密的key Returns:加密后的字符串 """ # 加密或者解密的初始向量(16位) iv = "0102030405060708" # 不是16的倍数则填充 pad = 16 - len(text) % 16 if isinstance(text, str): text = text + pad * chr(pad) else: text = text.deocde("utf-8") + pad * chr(pad) aes = AES.new(key=bytes(key, encoding="utf-8"), mode=2, iv=bytes(iv, encoding="utf-8")) res = aes.encrypt(bytes(text, encoding="utf-8")) res = base64.b64encode(res).decode("utf-8") return res def __get_enc_text(arg1): """ 对称加密后的参数 Args: arg1:加密参数 Returns: """ enc_text = __aes_encrypt(arg1, arg4) enc_text = __aes_encrypt(enc_text, random_str) return enc_text def __get_enc_sec_key(): """ 对称加密密钥 通过查看js代码,获取encSecKey """ # 随机字符串逆序排列 text = random_str[::-1] rs = int(codecs.encode(text.encode('utf-8'), 'hex_codec'), 16) ** int(arg2, 16) % int(arg3, 16) return format(rs, 'x').zfill(256) def linux_encrypt(text): # print(text) return text def get_form_data(text, method=''): """ 反编译生成 请求的form-data参数 Args: text: 跟踪js,自己组装参数 method: 方法 Returns:form-data参数 """ """ """ if method == 'linux': return linux_encrypt(text) text = str(text) return {"params": __get_enc_text(text), "encSecKey": __get_enc_sec_key()}
只要加密过程知道了,其实很多接口都可以模拟请求,此文仅供学习。
最终执行效果如下图:
以上是“网易云音乐热评爬虫中怎么用python实现反编译加密参数”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。