前言
(所有脚本仅供学习交流使用,请勿用于商业用途和非法用途,如作他用所造成的一切后果和法律责任一概与本人无关,如有侵权请联系我删除)
案例
今天给大家分享一个爬虫学习案例,烯*数据的最新赛道中的数据,话不多说直接上图。
如图所示,我们想要获取最新赛道的名称,数量,最近获投,和最近更新的数据,正常打开f12观察请求参数如图所示。
![](https://i-blog.csdnimg.cn/direct/f45796a7afe14dbda611b5d53cbfa96e.png)
我们可以发现页面用的是动态加载的,向下滑动会有一直有新数据,并且请求负载的payload和sig都进行了加密,参数v是一个定值,加密参数一般在js文件中进行的加密,那么我们如何确定加密函数的位置呢?
寻找加密函数的位置
1. 通过搜索关键字进行查找
常见的加密方式一般是对称加密(AES 加密)和非对称加密(RSA 加密),因此我们
可以搜索encrypt,decrypt,AES,Crypto,RSA,hash,signature,jsencrypt....等常见的关键字。
像本文的案例参数进行了加密,我们还可以自己搜索加密的参数的名称来快速进行定位。(本案例主要用第二种,第一种以后更新)
2. 通过XHR/提取断点
像本文中的案例可以将请求url添加提取断点,每当运行到这个url就会断点在这里,具体操作如下图所示。
添加后刷新一下页面就可以发现神奇的现象。
可以看见在右侧中有f 和 p 刚好对应的是加密的参数,我们直接加断点进行断点调试,向下运行两步具体如下。
我们发现f和p经过了这两行代码就已经加密成功了,那么具体加密操作就是这两行代码,那么我们就开始进行愉快的补环境吧。
复制这两行代码到Visual Studio Code(个人喜欢用这个)中进行补环境,具体怎么配置见:node.js的环境安装。
先解决参数的加密,在控制台打印一下s.payload可以发现是一个字典如下:{ "sort":1,"start":20,"limit": 20}先按照一个常量进行处理直接写死,JSON.stringify函数是将字典变为标准的json格式可以不要,然后就可以发现有用的函数就是Object(u.d)和Object(u.c),我们打印一下看看函数如下。
发现 Object(u.c)其实是e2和e1函数,直接拿到Visual Studio Code中运行,然后缺少什么函数就在控制台打印然后扣下来补上,_keyStr和_p都是定值可以在js代码中找到,具体如下
到此为止参数已经获取到了,咱们回头看一下{ "sort":1,"start":20,"limit": 20}这个字典,其中sort是排序方式默认1为正序不用管,limit为每次返回的20条数据,start为0表示第一页数据,start为20为第二页数据,以此类推。
接下来打开pycharm进行操作,需要在终端安装一下pip install PyExecJS2 ,然后在插件中搜索node.js下载,重启pycharm(我用的专业版2020的)
运行完发现结果也是加密的也就是那个d,具体方法和上面一样,就检验一下你们的学习能力了(偷笑)。上代码了
破解参数代码
const CryptoJS = require('crypto-js');
var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
, _p = "W5D80NFZHAYB8EUI2T649RT2MNRMVE2O";
function e2(e) {
if (null == (e = _u_e(e)))
return null;
for (var t = "", n = 0; n < e.length; n++) {
var r = _p.charCodeAt(n % _p.length);
t += String.fromCharCode(e.charCodeAt(n) ^ r)
}
return t
}
function _u_e(e) {
if (null == e)
return null;
e = e.replace(/\r\n/g, "\n");
for (var t = "", n = 0; n < e.length; n++) {
var r = e.charCodeAt(n);
r < 128 ? t += String.fromCharCode(r) : r > 127 && r < 2048 ? (t += String.fromCharCode(r >> 6 | 192),
t += String.fromCharCode(63 & r | 128)) : (t += String.fromCharCode(r >> 12 | 224),
t += String.fromCharCode(r >> 6 & 63 | 128),
t += String.fromCharCode(63 & r | 128))
}
return t
}
function e1(e) {
if (null == e)
return null;
for (var t, n, r, o, i, a, u, c = "", l = 0; l < e.length; )
o = (t = e.charCodeAt(l++)) >> 2,
i = (3 & t) << 4 | (n = e.charCodeAt(l++)) >> 4,
a = (15 & n) << 2 | (r = e.charCodeAt(l++)) >> 6,
u = 63 & r,
isNaN(n) ? a = u = 64 : isNaN(r) && (u = 64),
c = c + _keyStr.charAt(o) + _keyStr.charAt(i) + _keyStr.charAt(a) + _keyStr.charAt(u);
return c
}
function sig(e) {
return CryptoJS.MD5(e + _p).toString().toUpperCase()
}
function xxxx(hu){
var f = e1(e2(JSON.stringify(hu)))
var p = sig(f);
return [f,p]
}
hu = {
"sort": 2,
"start": 20,
"limit": 20
}
console.log(xxxx(hu));
结果加密代码
function _u_d(e) {
for (var t = "", n = 0, r = 0, o = 0, i = 0; n < e.length; )
(r = e.charCodeAt(n)) < 128 ? (t += String.fromCharCode(r),
n++) : r > 191 && r < 224 ? (o = e.charCodeAt(n + 1),
t += String.fromCharCode((31 & r) << 6 | 63 & o),
n += 2) : (o = e.charCodeAt(n + 1),
i = e.charCodeAt(n + 2),
t += String.fromCharCode((15 & r) << 12 | (63 & o) << 6 | 63 & i),
n += 3);
return t
}
function d1(e) {
var t, n, r, o, i, a, u = "", c = 0;
for (e = e.replace(/[^A-Za-z0-9\+\/\=]/g, ""); c < e.length; )
t = _keyStr.indexOf(e.charAt(c++)) << 2 | (o = _keyStr.indexOf(e.charAt(c++))) >> 4,
n = (15 & o) << 4 | (i = _keyStr.indexOf(e.charAt(c++))) >> 2,
r = (3 & i) << 6 | (a = _keyStr.indexOf(e.charAt(c++))),
u += String.fromCharCode(t),
64 != i && (u += String.fromCharCode(n)),
64 != a && (u += String.fromCharCode(r));
return u
}
function d2(e) {
for (var t = "", n = 0; n < e.length; n++) {
var r = _p.charCodeAt(n % _p.length);
t += String.fromCharCode(e.charCodeAt(n) ^ r)
}
return t = _u_d(t)
}
const CryptoJS = require('crypto-js');
var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
, _p = "W5D80NFZHAYB8EUI2T649RT2MNRMVE2O";
function hanshu(s){
var d = d1(s)
, y = d2(d)
, m = JSON.parse(y);
return m
}
s = '请求到的那一大堆字符串'
console.log(hanshu(s));
python代码
import requests
import json
import execjs
hu = {
"sort": 1,
"start": 20,
"limit": 40
}
with open("烯牛数据.js", "r", encoding="utf-8") as f:
js_code = f.read()
js_evn = execjs.compile(js_code)
result = js_evn.call('xxxx', hu) # execjs.compile用于执行更复杂的js代码
print(result)
headers = {
"accept": "application/json",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"cache-control": "no-cache",
"content-type": "application/json",
"origin": "https://www.xiniudata.com",
"pragma": "no-cache",
"priority": "u=1, i",
"referer": "https://www.xiniudata.com/industry/newest?from=data",
"sec-ch-ua": "\"Not)A;Brand\";v=\"99\", \"Microsoft Edge\";v=\"127\", \"Chromium\";v=\"127\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0"
}
url = "https://www.xiniudata.com/api2/service/x_service/person_industry_list/list_industries_by_sort"
data = {
"payload": result[0],
"sig": result[1],
"v": 1
}
data = json.dumps(data)
response = requests.post(url, headers=headers, data=data)
json_str = json.loads(response.text)
s = json_str['d']
with open("烯牛数据2.js", "r", encoding="utf-8") as f:
js_code1 = f.read()
js_evn1 = execjs.compile(js_code1)
result1 = js_evn1.call('hanshu', s) # execjs.compile用于执行更复杂的js代码
print(result1)
说明
有问题留言,我每天上班必回的哦,给个结果图