url:https://www.aqistudy.cn/apinew/aqistudyapi.php
请求url
Request URL: https://www.aqistudy.cn/apinew/aqistudyapi.php
请求方式
Request Method: POST
动态变化的参数
d: tdgHOYxwKdDSgYXe+RLPzYCgLvrddahasI5XXklB4gVLYqab+XRPpMD/oSqnJ/aEmFwzVEUhLnPzRy03+X1BIzLvxQKwu4A3YsqR3OemYgNnHqPdBwvJlbxia99YeK+xVtm/KUfxgICnZHiin/ojfqe1ZJXPHKDaOqwKab2iJt6YQRF4WQWYusdfEXhDolRtLCUy8ht8s821u5VxPcU+NezPIcU8U830QPCeWGAkKrHcsmuUaEHoRLJjnqpMnaid8OfacV5HCUeVhK3Uhju9Sr+bGsXveRwJFs5t307AlxFmwOBzCa6T6fmAQK9+1KoOfUz8EtNUEQkMB1LQBarJd9qsFKpe6TnoLFJ9G6xud+YIs8GecqTX4Pf2urDJLQ3LLfmLqMo7H/7LwYcq2BxyJiGqG2Xpp5wdr9L+oCZisZ9yKEBuYIprEM6A9PMUKADaw5ZESt11e9YX/xbkKPbnaw==
返回的加密的响应数据
f9VXvMyFOzW7AzFWZjMa3oW5basBySGVYXbOpPoS6/W7Dh2wAk4bbiAr7xpyn/meJ/Hem3nHWnk4WtHFwrhKIyDSu2SUsVB5a/jusoqnpmDCxqr9YxCavi6qiilWtiVa49+C70wNGkoQqdo5w3hB/g==
请求得到的数据是一组加密数据,但是web前台展示的是一组明文数据,原因是前台将响应回来的密文数据进行了解密
注:在该网站的相关数据包中是存在这解密方法,我们只需要将其解密方法获取,就可对密文数据进行解密
没有发现ajax代码的实现
发现函数内部调用了另外的两个函数getAQIData();
getWeatherData();
那么ajax代码的实现一定是在上诉两个函数内部
有价值的信息: type==“HOUR” 查询时间是以小时为单位
进入getAQIData();getWeatherData();函数内部找寻ajax代码实现
- 在网站后台,关键的重要的js函数的实现为了保密,一般会对这些js函数代码进行混淆(加密),所以我们需要对js混淆的代码进行反混淆,将js加密的函数进行解密
js混淆暴力破解https://www.bm8.com.cn/jsConfusion/
function getServerData(method, object, callback, period) {
const key = hex_md5(method + JSON.stringify(object));
const data = getDataFromLocalStorage(key, period);
if (!data) {
var param = getParam(method, object);
$.ajax({
url: '../apinew/aqistudyapi.php', #请求url
data: {
d: param #加密且动态变化的请求参数
},
type: "post",#请求方式
#data请求到的加密的响应数据
success: function (data) {
data = decodeData(data);#将data这个加密的响应数据进行解密
obj = JSON.parse(data);
if (obj.success) {
if (period > 0) {
obj.result.time = new Date().getTime();
localStorageUtil.save(key, obj.result)
}
callback(obj.result)
} else {
console.log(obj.errcode, obj.errmsg)
}
}
})
} else {
callback(data)
}
}
我们需要借助于 PyExecJS 库来实现模拟JavaScript代码执行获取动态加密的请求参数,然后再将加密的响应数据带入decodeData进行解密即可!
pip install PyExecJS
对其进行环境安装。https://jingyan.baidu.com/article/e4511cf38c05092b845eaf9b.html
- 2.在jsCode.js文件中添加一个自定义函数getPostParamCode,该函数是为了获取且返回post请求的动态加密参数:
function getPostParamCode(method, city, type, startTime, endTime){
var param = {
};
param.city = city;
param.type = type;
param.startTime = startTime;
param.endTime = endTime;
return getParam(method, param);
}
- 在py源文件中可以基于PyExecJS模拟执行jsCode.js中定义好的自定义函数,获取动态加密参数:
import execjs
import requests
url = "https://www.aqistudy.cn/apinew/aqistudyapi.php"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"
}
#实例化一个对象
node = execjs.get()
# Params
method = 'GETCITYWEATHER'
city = '北京'
type = 'HOUR'
start_time = '2020-08-27 00:00:00'
end_time = '2020-08-28 23:00:00'
# Compile javascript
file = 'jsCode.js' #代加载编译的js源文件
ctx = node.compile(open(file, encoding='utf-8').read())#加载编译的js源文件中的js代码
# Get params
js = 'getPostParamCode("{0}", "{1}", "{2}", "{3}", "{4}")'.format(method, city, type, start_time, end_time)
params = ctx.eval(js)# eval表示执行指定js函数
print(params)#返回的是加密变化的请求参数
import execjs
import requests
url = "https://www.aqistudy.cn/apinew/aqistudyapi.php"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"
}
#实例化一个对象
node = execjs.get()
# Params
method = 'GETCITYWEATHER'
city = '北京'
type = 'HOUR'
start_time = '2020-08-27 00:00:00'
end_time = '2020-08-28 23:00:00'
# Compile javascript
file = 'jsCode.js' #代加载编译的js源文件
ctx = node.compile(open(file, encoding='utf-8').read())#加载编译的js源文件中的js代码
# Get params
js = 'getPostParamCode("{0}", "{1}", "{2}", "{3}", "{4}")'.format(method, city, type, start_time, end_time)
params = ctx.eval(js)# eval表示执行指定js函数
print(params)
data = {
"d":params
}
page_text = requests.post(url=url,headers=headers,data=data).text
print(page_text)# 返回的是加密的响应数据
import execjs
import requests
url = "https://www.aqistudy.cn/apinew/aqistudyapi.php"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"
}
#实例化一个对象
node = execjs.get()
# Params
method = 'GETCITYWEATHER'
city = '北京'
type = 'HOUR'
start_time = '2020-08-27 00:00:00'
end_time = '2020-08-28 23:00:00'
# Compile javascript
file = 'jsCode.js' #代加载编译的js源文件
ctx = node.compile(open(file, encoding='utf-8').read())#加载编译的js源文件中的js代码
# Get params
js = 'getPostParamCode("{0}", "{1}", "{2}", "{3}", "{4}")'.format(method, city, type, start_time, end_time)
params = ctx.eval(js)# eval表示执行指定js函数
print(params)
data = {
"d":params
}
page_text = requests.post(url=url,headers=headers,data=data).text
print(page_text)# 返回的是加密的响应数据
# 对加密的响应数据进行解密
js = 'decodeData("{0}")'.format(page_text)
decrypted_data = ctx.eval(js)
print(decrypted_data) #解密后的真实数据
完美结束