JS逆向之某网站爬虫大赛第一题详解
字数 973 2025-08-15 21:33:22
JS逆向之某网站爬虫大赛第一题详解
0. 概述
本教程详细解析某网站爬虫大赛第一题的JS逆向过程。该题目要求抓取5页机票价格并计算平均值,主要涉及前端JS混淆和加密技术。
1. 题目分析
1.1 题目要求
- 目标URL: http://match.yuanrenxue.com/match/1
- 任务: 抓取5页机票价格数据并计算平均值
- 关键点: 请求参数m的生成逻辑
1.2 初步观察
- 通过浏览器调试工具发现存在debug断点,可通过"Never pause here"跳过
- 数据通过XHR请求获取,格式为JSON
- 每次请求page相同但m参数会变化
- m参数可重放,有效期约1分钟
- 需要设置User-Agent为"yuanrenxue.project"
2. 参数m的分析
2.1 m参数结构
m参数由两部分组成,中间用中文"丨"分隔:
- 第一部分: 类似MD5的哈希值
- 第二部分: 类似时间戳的值
2.2 定位关键代码
两种定位方法:
- 全局搜索中文"丨"符号
- 通过request call stack定位
3. 代码调试
3.1 关键函数分析
function oo0O0(mw) {
window.b = '';
for (var i = 0, len = window.a.length; i < len; i++) {
window.b += String[document.e + document.g](window.a[i][document.f + document.h]() - i - window.c)
}
var U = ['W5r5W6VdIHZcT8kU', 'WQ8CWRaxWQirAW=='];
var J = function(o, E) {
// ...省略解密函数...
};
eval(atob(window['b'])[J('0x0', ']dQW')](J('0x1', 'GTu!'), '\x27' + mw + '\x27'));
return ''
}
3.2 关键变量获取
需要获取以下变量:
window.a: 长字符串,包含各种Unicode字符document.e: "fromC"document.f: "charCo"document.g: "harCode"document.h: "deAt"
3.3 window.b分析
window.b是一个Base64编码的字符串,解码后得到MD5相关函数定义:
var hexcase=0;
var b64pad="";
var chrsz=16;
function hex_md5(a){return binl2hex(core_md5(str2binl(a),a.length*chrsz))}
// ...其他MD5相关函数...
window.f = hex_md5(mwqqppz)
3.4 参数生成逻辑
最终m参数的生成逻辑:
var timestamp = Date.parse(new Date());
var m = hex_md5(timestamp.toString()) + '丨' + timestamp/1000;
4. Python实现
4.1 使用execjs调用JS代码
import requests
import execjs
jscode = """
// 完整的MD5实现代码
var timestamp = (Date.parse(new Date())).toString();
mm=hex_md5(timestamp)
"""
ctx = execjs.compile(jscode)
4.2 请求实现
sum = 0
count = 0
for i in range(1,6):
timestamp = int(ctx.eval('timestamp'))
m = ctx.eval("mm") + '丨' + str(timestamp // 1000)
args = {
'page':i,
'm': m
}
datas = requests.get('http://match.yuanrenxue.com/api/match/1?',
params=args,
headers={'User-Agent':'yuanrenxue.project'}).json()
# 处理数据...
5. 关键点总结
- 参数结构: m参数由MD5哈希和时间戳组成,用"丨"分隔
- MD5实现: 网站使用自定义修改的MD5算法,不能使用标准库
- 时间戳处理: 使用
Date.parse(new Date())获取毫秒时间戳 - 请求头: 必须设置User-Agent为"yuanrenxue.project"
- 调试技巧: 需要逐步提取JS中的关键变量和函数
6. 完整解决方案
import requests
import execjs
# 完整的JS代码(包含MD5实现)
jscode = """
// 这里放入完整的MD5实现代码
var timestamp = (Date.parse(new Date())).toString();
mm=hex_md5(timestamp)
"""
ctx = execjs.compile(jscode)
sum = 0
count = 0
for page in range(1, 6):
# 生成m参数
timestamp = int(ctx.eval('timestamp'))
m = ctx.eval("mm") + '丨' + str(timestamp // 1000)
# 构造请求
params = {'page': page, 'm': m}
headers = {'User-Agent': 'yuanrenxue.project'}
# 发送请求
response = requests.get(
'http://match.yuanrenxue.com/api/match/1',
params=params,
headers=headers
).json()
# 处理数据
for item in response['data']:
value = item['value']
sum += value
count += 1
# 计算平均值
average = sum / count
print(f"Average value: {average}")
通过以上步骤,可以成功获取5页机票价格数据并计算平均值。关键是要正确解析JS加密逻辑并实现相应的参数生成算法。