Python反反爬之JS混淆---回溯
# 写在前面Python反反爬系列
1.
2.
3. [访问逻辑---推心置腹]
4.
[解题代码Github](https://github.com/Java-S12138/yuanrenxue_python_spider)
[个人博客](https://syjun.vip)
## 题目
![]
题目网站,[点我去刷题]
**采集全部5页的彩票数据,计算全部中奖的总金额(包含一、二、三等奖)**
## 分析网页
老规矩,我们还是首先打开刷题网站,接着打开谷歌调试工具
查看【XHR】里面的内容
![]
可以发现通过Ajax的方式,返回了一串数据
对比网页的数字,不难发现,这些返回的数据,是页面的三等奖金额
但是,这道题让我们求的是一等奖,二等奖,三等奖的总金额
做了几道猿人学的题目,我们可以猜测,总金额可能会通过JS代码生成
这个问题,我们先留着,继续分析一下返回数据的这个URL
![]
通过观察,我们可以发现,URL中带了两个参数,一个【 m 】的加密参数,还有一个【 q 】的参数,【 q 】的参数值与时间戳类似
**所以说,要想正常访问,肯定要先算出【 m 】和【 q 】的值**
## m 和 q的值,从何而来
我们知道上面提到的请求是通过Ajax请求返回的,这里可以分享给大家一个小技巧
在谷歌浏览器的调试工具中,我们可以通过下图的方式,直接进入到AJax的代码部分
![]
![]
![]
来到这个页面,Ajax上面定义的一个数组,引起了我的注意,我们将它扣下来
```javascript
var list = {
"page": window.page,
"m": r(t, window.o),
"q": window.i += window.o + '-' + t + "|",
};
```
看到这段代码,我相信大家已经大概明白了 m 和 q的值,从何而来
- **page**:页码,因为我们请求的第一页,所以在URL中省略了,但是从第二页开始page就会出现
- **m**:通过调用**r**函数,并传入,【t】和【window.o】参数,得到一串加密后的密文
- **q**:通过 += 的方式,可以累加得到一串字符串
我们截取一段 【q】的值分析一下,window.i和window.o已经 t 是什么
> q: 1-1610261917000|
通过对比我们可以发现
1. window.i就是这串值
2. window.o是1
3. t就是时间戳
但是,这个 += 符号有什么用呢?
我们多次请求一下第二页和第三页,你就明白啦
> q: 1-1610261917000|2-1610264287000|3-1610264288000|
这是我请求第一页,第二页,第三页后,【q】的值
这个时候,可能就有小伙伴会说,window.o就是页码的值
但是,当我在第三页回到第一页的时候,【q】的值是这样的
> q: 1-1610261917000|2-1610264287000|3-1610264288000|4-1610264345000|
所以说,window.o的值其实很简单,并不是页码的值,而是点击页面发起Ajax请求的次数罢了
----------
明白了【t】和【window.o】的含义,我们就明白了通过调用**r**函数传入的参数是什么了
现在我们知道了【q】值的生成过程,而【m】只知道一部分,所以我们的下一步就是寻找**r**函数
## 寻找**r**函数
我们在**r**函数出现的哪一行代码,打一个断点
![]
接着按CTRL+R,刷新一下页面
我们会发现代码卡在了769这一行,我们点击右上角的箭头继续往下运行
![]
这个时候,代码就卡在了**r**函数这一行,我们点击右上角如下图的这个按钮,就可以进入到包含**r**函数的JS文件中,这也是题目所提到的 【 **回溯** 】
![]
![]
就是这么简单,我们很顺利的找到了**r**函数,接着我们将代码扣下来分析一下
## 分析r函数
```javascript
function r(param1, param2) {
if (window.o >= 6) {
alert('不要戳这么多下,人家好痛嘛~');
location.reload();
}
return z(param1, param2);
}
```
代码中,出现了一个if判断, 而判断中的内容就是,如果**Ajax请求**(也就是点击页面中页码的次数,当然首次进入页面是默认发起了一次请求的)**大于或者等于6次**的话,页面就会出现**如下图的弹窗**,紧接着执行**location.reload()函数**,而这个函数,我们在前面的题目中也碰到过,就是刷新整个页面,**window.o的值也会重置为1**
![]
接着将传入的参数,二次传递给**z**函数并执行
我们来看一下**z**函数中的代码
```javascript
function z(pwd, time) {
var n = _n("jsencrypt");
var g = (new n);
var r = g.encode(pwd, time);
return r;
}
```
这段代码的注意内容是:
- 实例化了jsencrypt对象
- 使用jsencrypt中的encode方法,进行了加密,并且返回,也就是【m】的值
jsencrypt就是一个基于rsa加解密的js库,反正就是一段操作,返回一段密文,感兴趣的同学可以自行百度,我这里就不展开讲了
我们就可以通过运行这个JS文件,从而得出m的值
到这里,相信大家已经明白了m 和 q的值,都是怎样产生的了
但是,在包含**r**函数的JS文件中,是有混淆过的代码的
大致浏览一下文件中的代码你就会发现这样三处混淆代码
![]
![]
![]
**所以说, 要想通过JS文件得出m的值,就需要先将混淆的代码翻译过来**
## 翻译混淆过的代码
通常像这种混淆过的代码,如果不是一个函数的话,我们是可以通过谷歌调试工具中的Console,运行出结果的
比如说这段混淆代码,其实就是JS中的一些运算
```javascript
[][(![] + [])[!+[] + !![] + !![]] + ([] + {})[+!![]] + (!![] + [])[+!![]] + (!![] + [])[+[]]][([] + {})[!+[] + !![] + !![] + !![] + !![]] + ([] + {})[+!![]] + ([][[]] + [])[+!![]] + (![] + [])[!+[] + !![] + !![]] + (!![] + [])[+[]] + (!![] + [])[+!![]] + ([][[]] + [])[+[]] + ([] + {})[!+[] + !![] + !![] + !![] + !![]] + (!![] + [])[+[]] + ([] + {})[+!![]] + (!![] + [])[+!![]]]((+!![] + []) + (!+[] + !![] + !![] + !![] + !![] + []) + (!+[] + !![] + !![] + !![] + !![] + !![] + !![] + []) + (+!![] + []) + (!+[] + !![] + !![] + !![] + !![] + []) + (+[] + []) + (!+[] + !![] + !![] + !![] + !![] + !![] + !![] + []) + (+[] + []))(!+[] + !![] + !![] + !![] + !![] + !![] + !![]) == ([][(![] + [])[!+[] + !![] + !![]] + ([] + {})[+!![]] + (!![] + [])[+!![]] + (!![] + [])[+[]]][([] + {})[!+[] + !![] + !![] + !![] + !![]] + ([] + {})[+!![]] + ([][[]] + [])[+!![]] + (![] + [])[!+[] + !![] + !![]] + (!![] + [])[+[]] + (!![] + [])[+!![]] + ([][[]] + [])[+[]] + ([] + {})[!+[] + !![] + !![] + !![] + !![]] + (!![] + [])[+[]] + ([] + {})[+!![]] + (!![] + [])[+!![]]]((+!![] + []) + (!+[] + !![] + !![] + !![] + !![] + !![] + []) + (!+[] + !![] + !![] + !![] + !![] + !![] + !![] + []) + (!+[] + !![] + !![] + !![] + !![] + !![] + !![] + []) + (!+[] + !![] + !![] + !![] + !![] + !![] + !![] + []) + (!+[] + !![] + []) + (+!![] + []) + (!+[] + !![] + !![] + !![] + !![] + []))(!+[] + !![] + !![] + !![] + !![] + !![]) & [][(![] + [])[!+[] + !![] + !![]] + ([] + {})[+!![]] + (!![] + [])[+!![]] + (!![] + [])[+[]]][([] + {})[!+[] + !![] + !![] + !![] + !![]] + ([] + {})[+!![]] + ([][[]] + [])[+!![]] + (![] + [])[!+[] + !![] + !![]] + (!![] + [])[+[]] + (!![] + [])[+!![]] + ([][[]] + [])[+[]] + ([] + {})[!+[] + !![] + !![] + !![] + !![]] + (!![] + [])[+[]] + ([] + {})[+!![]] + (!![] + [])[+!![]]]((+[] + []) + [][(![] + [])[!+[] + !![] + !![]] + ([] + {})[+!![]] + (!![] + [])[+!![]] + (!![] + [])[+[]]][([] + {})[!+[] + !![] + !![] + !![] + !![]] + ([] + {})[+!![]] + ([][[]] + [])[+!![]] + (![] + [])[!+[] + !![] + !![]] + (!![] + [])[+[]] + (!![] + [])[+!![]] + ([][[]] + [])[+[]] + ([] + {})[!+[] + !![] + !![] + !![] + !![]] + (!![] + [])[+[]] + ([] + {})[+!![]] + (!![] + [])[+!![]]]((!![] + [])[+!![]] + ([][[]] + [])[!+[] + !![] + !![]] + (!![] + [])[+[]] + ([][[]] + [])[+[]] + (!![] + [])[+!![]] + ([][[]] + [])[+!![]] + ([] + {})[!+[] + !![] + !![] + !![] + !![] + !![] + !![]] + ([][[]] + [])[+[]] + ([][[]] + [])[+!![]] + ([][[]] + [])[!+[] + !![] + !![]] + (![] + [])[!+[] + !![] + !![]] + ([] + {})[!+[] + !![] + !![] + !![] + !![]] + (+{} + [])[+!![]] + ([] + [][(![] + [])[!+[] + !![] + !![]] + ([] + {})[+!![]] + (!![] + [])[+!![]] + (!![] + [])[+[]]][([] + {})[!+[] + !![] + !![] + !![] + !![]] + ([] + {})[+!![]] + ([][[]] + [])[+!![]] + (![] + [])[!+[] + !![] + !![]] + (!![] + [])[+[]] + (!![] + [])[+!![]] + ([][[]] + [])[+[]] + ([] + {})[!+[] + !![] + !![] + !![] + !![]] + (!![] + [])[+[]] + ([] + {})[+!![]] + (!![] + [])[+!![]]]((!![] + [])[+!![]] + ([][[]] + [])[!+[] + !![] + !![]] + (!![] + [])[+[]] + ([][[]] + [])[+[]] + (!![] + [])[+!![]] + ([][[]] + [])[+!![]] + ([] + {})[!+[] + !![] + !![] + !![] + !![] + !![] + !![]] + (![] + [])[!+[] + !![]] + ([] + {})[+!![]] + ([] + {})[!+[] + !![] + !![] + !![] + !![]] + (+{} + [])[+!![]] + (!![] + [])[+[]] + ([][[]] + [])[!+[] + !![] + !![] + !![] + !![]] + ([] + {})[+!![]] + ([][[]] + [])[+!![]])(+!![]))[!+[] + !![] + !![]] + ([][[]] + [])[!+[] + !![] + !![]])(!+[] + !![] + !![] + !![] + !![])([][(![] + [])[!+[] + !![] + !![]] + ([] + {})[+!![]] + (!![] + [])[+!![]] + (!![] + [])[+[]]][([] + {})[!+[] + !![] + !![] + !![] + !![]] + ([] + {})[+!![]] + ([][[]] + [])[+!![]] + (![] + [])[!+[] + !![] + !![]] + (!![] + [])[+[]] + (!![] + [])[+!![]] + ([][[]] + [])[+[]] + ([] + {})[!+[] + !![] + !![] + !![] + !![]] + (!![] + [])[+[]] + ([] + {})[+!![]] + (!![] + [])[+!![]]]((!![] + [])[+!![]] + ([][[]] + [])[!+[] + !![] + !![]] + (!![] + [])[+[]] + ([][[]] + [])[+[]] + (!![] + [])[+!![]] + ([][[]] + [])[+!![]] + ([] + {})[!+[] + !![] + !![] + !![] + !![] + !![] + !![]] + ([][[]] + [])[!+[] + !![] + !![]] + (![] + [])[!+[] + !![] + !![]] + ([] + {})[!+[] + !![] + !![] + !![] + !![]] + (+{} + [])[+!![]] + ([] + [][(![] + [])[!+[] + !![] + !![]] + ([] + {})[+!![]] + (!![] + [])[+!![]] + (!![] + [])[+[]]][([] + {})[!+[] + !![] + !![] + !![] + !![]] + ([] + {})[+!![]] + ([][[]] + [])[+!![]] + (![] + [])[!+[] + !![] + !![]] + (!![] + [])[+[]] + (!![] + [])[+!![]] + ([][[]] + [])[+[]] + ([] + {})[!+[] + !![] + !![] + !![] + !![]] + (!![] + [])[+[]] + ([] + {})[+!![]] + (!![] + [])[+!![]]]((!![] + [])[+!![]] + ([][[]] + [])[!+[] + !![] + !![]] + (!![] + [])[+[]] + ([][[]] + [])[+[]] + (!![] + [])[+!![]] + ([][[]] + [])[+!![]] + ([] + {})[!+[] + !![] + !![] + !![] + !![] + !![] + !![]] + (![] + [])[!+[] + !![]] + ([] + {})[+!![]] + ([] + {})[!+[] + !![] + !![] + !![] + !![]] + (+{} + [])[+!![]] + (!![] + [])[+[]] + ([][[]] + [])[!+[] + !![] + !![] + !![] + !![]] + ([] + {})[+!![]] + ([][[]] + [])[+!![]])(+!![]))[!+[] + !![] + !![]] + ([][[]] + [])[!+[] + !![] + !![]])(!+[] + !![] + !![] + !![] + !![] + !![] + !![] + !![])(([] + {})[+[]])[+[]] + (!+[] + !![] + !![] + !![] + !![] + !![] + !![] + []) + (!+[] + !![] + !![] + !![] + !![] + !![] + !![] + !![] + [])) + ([][[]] + [])[!+[] + !![]] + ([][[]] + [])[!+[] + !![] + !![]] + (+{} + [])[+!![]] + ([][[]] + [])[!+[] + !![]] + ([] + {})[!+[] + !![]] + ([][[]] + [])[!+[] + !![] + !![]] + ([][[]] + [])[!+[] + !![] + !![]] + ([][[]] + [])[!+[] + !![] + !![] + !![]] + ([] + {})[!+[] + !![] + !![] + !![] + !![]] + (+{} + [])[+!![]] + ([][[]] + [])[!+[] + !![] + !![] + !![]] + ([][[]] + [])[!+[] + !![] + !![]])(!+[] + !![] + !![]));
```
将这些代码输入到Console中,就可以得出结果
![]
在这道题目的三处混淆中,都可以通过这种方式翻译出来
而第一张图片的混淆,其实很有意思,看着也挺有意思的
它这种属于**JavaScript的表情包加密**,我们可以通过这个网站进行翻译[解密工具]
将需要解密的代码复制过去,然后点击aaencode解密,就可以得到结果【window.o = 1;】
![]
我这里就不放结果的截图,大家可以去试一试
还有一处混淆过的代码,你可以通过Console得出结果,我这里就不再赘述
全部翻译完成后,我们将结果与混淆的代码进行替换,接着道鬼鬼调试工具进行测试验证
## 验证加密结果
我们将处理过的代码粘贴到鬼鬼调试工具中
然后,在前面的地方,加一行代码 var window = this;
因为在代码中,很多地方用到了 window 变量,不声明的话,会报错
![]
在上面的截图中,可以发现我注释了一行代码 //window = {};
这行代码就是将window变为空,上面我也提到了,很多地方都需window,所以要将其注释
接着,我们加载全部代码,传入参数执行**r**函数,可以发现得到了我们想要的结果
![]
到目前为止,我们已经可以通过Python代码得到【m】和【q】的值了,但是还有一个问题我们还没有解决
## 求出中奖总金额
在文章开头,我们还留着一个问题
AJax返回的数据,是页面的三等奖金额
但是,这道题让我们求的是一等奖,二等奖,三等奖的总金额
所以,我们回到Ajax代码中(截取了部分代码)
如果你对Ajax的内容不是很熟悉的话,可以看看我这篇文章
在这篇文章中,我对ajax部分的代码解释得很详细,这里我就不多赘述
```javascript
$.ajax({
url: window.url,
dataType: "json",
async: false,
data: list,
type: "GET",
beforeSend: function (request) {},
success: function (data) {
if (window.page) {}
else {
window.page = 1
}
// 请求成功后返回的数据,也就是页面中三等奖的金额
data = data.data;
let html = '';
let arg = 1;
let puq = `<tr data-week="3"><td>date_twice</td><td>2020-10-date_value</td>caipiaohao<td>total_value</td><td>result_value1</td><td>result_value2</td><td>result_value3</td><td>0</td><td></td></tr>`;
let arr_arg = ;
// 通过循环三等奖的金额,进行一系列的操作,呈现出页面的各种数值
// 我们可以不用详细的去分析,直接看下面的replace部分
$.each(data, function (index, val) {
let caipiao = `<td><span class="rq1">arg1</span><span class="rq1">arg2</span><span class="rq1">arg3</span><span class="rq1">arg4</span><span class="rq1">arg5</span><span class="rq1">arg6</span><span class="rq1">arg7</span></td><td><span class="bq1">arg8</span></td>`;
let arr = ;
for (let c = 1; c <= 8; c++) {
caipiao = caipiao.replace('arg' + c, (Math.floor(((arr_arg << 2) / 5 + c) * c / 3) + 1) + arr)
}
// 这里的代码,主要是将页面的数值进行替换
html += puq.replace('caipiaohao', caipiao)
.replace('date_twice', arg * window.page + 2020097)
.replace('date_value', '0' + window.page)
.replace('result_value3', val.value)
// total_value 指的就是页面中的 总销售额字段
// val.value 指的就是 三等奖金额
// 也就是说,总销售额,就是三等奖的金额乘以24
.replace('total_value', val.value * 24)
// result_value2 二等奖
.replace('result_value2', val.value * 8)
// result_value1 一等奖
.replace('result_value1', val.value * 15);
arg += 1
});
$('.resbbp').text('').append(html)
}
```
通过上述代码的注释,我们可以知道,每一行的总销售额,也就是我们所求的总金额,其实就是三等奖的金额乘以24
所以,我们就可以获取每页的三等奖金额总和,最后乘以24就可以得出这道题目的答案 ::aru:pouting::
## 解出答案
在写Python代码之前,我们还需要完成最后一个步骤
![]
我们知道想要正常请求URL拿到数据,需要三个参数(page,m,q)
而前面我们翻译完成的JS文件,返回的结果只有m的值,而没有返回时间戳
所以,我们只需要将**z**函数改下一下即可
```javascript
// 修改前
function z(pwd, time) {
var n = _n("jsencrypt");
var g = (new n);
var r = g.encode(pwd, time);
return r;
}
// 修改后
function z(pwd, time) {
var n = _n("jsencrypt");
var g = (new n);
var r = g.encode(pwd, time);
var answer_arr =
return answer_arr;
}
```
现在,我们就可以愉快的写Python代码,爬取数据,解出答案啦
由于JS文件代码太多(2000多行),我就不粘贴出来,[点击我可以进行下载]
```python
# @BY :Java_S
# @Time :2021/1/10 13:36
# @Slogan :够坚定够努力大门自然会有人敲,别怕没人赏识就像三十岁的梵高
import time
import execjs
import requests
def get_cipher(timestamp, page):
# 导入JS,读取需要的js文件
with open(r'JS/js6.js', encoding='utf-8', mode='r') as f:
JsData = f.read()
# 加载js文件,使用call()函数执行,传入需要执行函数即可获取返回值
= execjs.compile(JsData).call('get_cipher', timestamp, page)
limit = f'{page}-' + str(timestamp) + '|'
return cipher, limit
def get_data(page):
cipher, limit = get_cipher(int(time.time()) * 1000, page)
url = 'http://match.yuanrenxue.com/api/match/6'
params = {
'page': page,
'm': cipher,
'q': limit
}
headers = {
'Host': 'match.yuanrenxue.com',
'Referer': 'http://match.yuanrenxue.com/match/6',
'User-Agent': 'yuanrenxue.project',
}
response = requests.get(url=url, headers=headers, params=params)
answer = for i in response.json()['data']]
print(f'第{page}页的三等奖:{answer}')
return answer
if __name__ == '__main__':
total = []
for i in range(1,6):
total += get_data(i)
total = sum(total)*24
print(f'五页中奖的总金额:{total}元')
```
![]
: https://www.52pojie.cn/thread-1337317-1-1.html
: https://www.52pojie.cn/thread-1339239-1-1.html
: https://www.52pojie.cn/thread-1341502-1-1.html
: https://www.52pojie.cn/thread-1346210-1-1.html
: https://syjun.vip/usr/uploads/2021/01/395464943.jpg
: http://match.yuanrenxue.com/match/6
: https://syjun.vip/usr/uploads/2021/01/3189750644.jpg
: https://syjun.vip/usr/uploads/2021/01/2761769185.jpg
: https://syjun.vip/usr/uploads/2021/01/2583982766.jpg
: https://syjun.vip/usr/uploads/2021/01/3763923002.jpg
: https://syjun.vip/usr/uploads/2021/01/3800050568.jpg
: https://syjun.vip/usr/uploads/2021/01/662541004.jpg
: https://syjun.vip/usr/uploads/2021/01/4128124389.jpg
: https://syjun.vip/usr/uploads/2021/01/3142550897.jpg
: https://syjun.vip/usr/uploads/2021/01/1103127448.jpg
: https://syjun.vip/usr/uploads/2021/01/986872791.jpg
: https://syjun.vip/usr/uploads/2021/01/1136954340.jpg
: https://syjun.vip/usr/uploads/2021/01/2274409932.jpg
: https://syjun.vip/usr/uploads/2021/01/1355107401.jpg
: https://syjun.vip/usr/uploads/2021/01/1035339501.jpg
: https://www.qtool.net/decode
: https://syjun.vip/usr/uploads/2021/01/1210912784.jpg
: https://syjun.vip/usr/uploads/2021/01/3094902137.jpg
: https://syjun.vip/usr/uploads/2021/01/859800304.jpg
: https://syjun.vip/archives/281.html
: https://syjun.vip/usr/uploads/2021/01/2761769185.jpg
: https://wwx.lanzoux.com/b01byvclg
: https://syjun.vip/usr/uploads/2021/01/1749758622.jpg 学爬虫的话js要学到什么程度啊? 大神厉害! {:301_973:}好想学啊!我想爬我们学校的题库 netspirit 发表于 2021-1-15 21:24
学爬虫的话js要学到什么程度啊?
至少要看得懂,代码写的什么意思 Java_S 发表于 2021-1-15 22:43
至少要看得懂,代码写的什么意思
需要专门去学前端么? 好兄弟日穿猿人学{:17_1068:} 大佬,有没有碰过无法打开开发者工具的反爬虫机制,“www.vmgirls.com”这个网站你在加载完后会打不开开发者工具,如果想办法打开了这个网页会直接崩溃掉,如果在加载之前就开好开发者工具就会出现断点,直接暂停加载,如果debug的stepover也会不停的循环知道网页崩溃 膜拜大神,学习了!
页:
[1]
2