2020.05.31更新:发现自己以前好菜啊……(
慢慢来吧……
摘要:
想利用爬虫实现半夜自动抢图书馆座位的功能,这样晚上就可以多睡一会了……
但是提交申请时发现有一个参数很诡异……
下面就是研究这个参数的生成方式,过程很奇葩
主要还是因为我是新手研究过程曲折但是很有趣,因此记录一下
如果你是大佬或者懒得往下慢慢看,那我直接告诉你结论好了——就是网站自己的js代码没有生成这个参数,这个参数只能是jQuery本身在提交GET请求时额外添加的,后来发现这参数其实就是时间戳……
登陆已经解决,是一个POST,抓对包之后几乎没什么门槛
提交预约申请使用了Ajax异步技术,因此只需要模拟js脚本提交GET请求即可
抓包分析看到"act":"set_resv"
,&act=set_resv
在源码VM310
中搜索set_resv
,看到第537行有对于fRsv()
的调用
pro.j.rsv.fRsv("set_resv", $("form:first", dlg), function () {
if (uni_calendar_dft_opt.submitSuc) {
uni_calendar_dft_opt.submitSuc(dlg, obj);
}
else {
var msg = '申请提交成功,是否跳转查看预约信息?';
if (parseInt(obj.minUser) > 1) {
msg += "<br/><br/><div style='font-weight:bold;'>" + uni.translate("注意!生效后需至少") + "<span style='color:red;font-size:bold;'>" + obj.minUser + "</span>" + uni.translate("人刷卡,否则将记为违约!") + "</div>";
}
uni.confirm(msg, function () {
$("#user_center").trigger("click");
}, function () {
uni.reload();
});
$(".group_id", dlg).val("");
$(".group_name", dlg).html("小组未创建");
dlg.dialog("close");
}
//btn.removeAttr("disabled");
}, function (rlt) {
uni.msgBox(pro.translate(rlt.msg));
//btn.removeAttr("disabled");
}, function () {
uni.msgBox(uni.translate("异步连接出现异常!"));
//btn.removeAttr("disabled");
});
其中传入的实参有一个就是我们的”set_resv”
,另外还有一个实参是一个回调函数,用于申请成功后更新页面信息(弹窗),这就是Ajax提交申请的流程。
因此猜测fRsv()
完成了对于url
的生成和提交
在pro.js
中1056行找到了fRsv()
的原型
fRsv: function (act, $f, suc, fail, err) {
pro.j.fGetS(this.p, act, $f, suc, fail, err);
},
它又调用了fGetS
: (:179)
//get方式 form提交 拓展方法
fGetS: function (url, act, $f, suc, fail, err) {
var data = {};
data.act = act;
data.$f = $f;
uni.j.fGet(url, data, function (rlt) {
pro.ckV(rlt, suc, fail);
}, err);
},
注意url
与this.p
对应,因此分析p很关键,因为我们很关心url
中的一个诡异的参数_
,一旦知道了这个参数就🆗了
类内的p出现在792行
pro.j.rsv = {
//路径
p: pro.dir + "ajax/reserve.aspx",
...
果然见到了我们想要的ajax/reserve.aspx
但是线索有断了,因为p在之后就没有变化过了……
因此p内没有这个参数……
再次将焦点转向fRsv()
,看看它如何被调用的
pro.j.rsv.fRsv("set_resv", $("form:first", dlg), function () {/* 成功之后的提示*/},function (rlt) {uni.msgBox(pro.translate(rlt.msg));}, function () {uni.msgBox(uni.translate("异步连接出现异常!"));});
与原型对比分析
act | “set_resv” |
---|---|
$f | $(“form:first”, dlg) |
suc | function () {/* 成功之后的提示*/} |
fail | function (rlt) {uni.msgBox(pro.translate(rlt.msg));} |
err | function () {uni.msgBox(uni.translate(“异步连接出现异常!”));} |
猜测$f
是关键
$("form:first", dlg)
是jQuery的多项选择器,匹配出来应该是在dlg中的第一个form
再看看调用
// pro.j.fGetS(this.p, act, $f, suc, fail, err);
fGets("http://******/ClientWeb/ajax/reserve.aspx", "set_resv", $f, suc, fail, err)
// http://******/ClientWeb/pro/ajax/reserve.aspx?dialogid=&dev_id=685&lab_id=&kind_id=&room_id=&type=dev&prop=&test_id=&term=&number=&test_name=&start=2019-03-30+18%3A00&end=2019-03-30+20%3A00&start_time=1800&end_time=2000&up_file=&memo=&act=set_resv&_=1553927422652
$f
应该对应的就是我们的申请表,也就是抓到的GET请求中的绝大多数参数的来源
果然在页面中找到了它
完全吻合
看来WebForm就是这个Form+act(“set_resv”)+那个诡异的参数_
……
然鹅_
还是不知道如何生成的……
因此又猜测生成这个参数的位置就在于fGets()
fGetS: function (url, act, $f, suc, fail, err) {
var data = {};
data.act = act;
data.$f = $f;
uni.j.fGet(url, data, function (rlt) {
pro.ckV(rlt, suc, fail);
}, err);
},
果然它将act的参数以及form中的参数合并成了data,并传给fGet()
其中调用到的ckV()
位于pro.js
的114行
//检查返回值
ckV: function (rlt, suc, fail) {
if (rlt == undefined) {
uni.msgBox("返回了空值!", null, null, "error");
return false;
}
else {
if (rlt.ret == 0) {
if (fail == undefined) { uni.msgBox(rlt.msg, null, null, "warning"); uni.log.set("msg", rlt.msg + "/" + rlt.act); }
else fail(rlt);
}
else if (rlt.ret > 0) {
if (suc == undefined) { uni.msgBox(rlt.msg, null, null, "success"); uni.log.set("msg", rlt.msg + "/" + rlt.act); }
else suc(rlt);
}
else if (rlt.ret == -1) {//登录超时
uni.msgBox(rlt.msg, "", function () { location.reload(); }, "warning");
uni.log.set("msg", rlt.msg + "/" + rlt.act);
}
return true;
}
}
估摸着这个函数主要是用于处理服务器返回信息用的,先搁在一边……
回到网页源码,找到了uni
的出处uni.lib
//-------------------------------------------------------------------jquery第三方 插件-----------------------------------
//异步上传
第三方插件可还行……
果然找到fGet()
//get方式 form提交(data.act 操作命令 data.$f 表单Jquery对象)
fGet: function (url, data, suc, err) {
var e = err || this._ajaxErr;
this._get(url, data, suc, e, 2);
},
进一步找到_get()
//基础ajax方法 get方式 flag=1 js对象转url参数 flag=2 form提交 flag=3 uri编码
_get: function (url, data, suc, err, flag, type) {
var d = data;
if (flag === 1) {
d = uni.obj2Url(data);
}
else if (flag === 2) {
d = $(data.$f).serialize() + "&act=" + data.act;
}
else if (flag === 3) {
d = encodeURI(data);
}
if (d != null && d != "") {
if (d.length > 2000) {//当参数超出url长度限制,转post方式
this.post(url, uni.url2Obj(d), suc, err);
return;
}
else {
url = url + "?" + d;
}
}
var len = this.history.length;
if (len > 0) {
var last = this.history[len - 1];
if (last.act == url && last.ajax_state == "sending") {
return;//重复提交 丢弃
}
}
var sta = { ajax_state: "sending", act: url };
this.history.push(sta);
$.ajax({
type: "GET",
cache: false,
timeout: 150000,
buf: data,
url: url,
dataType: type || "json",
success: suc,
error: err,
beforeSend: function () {
uni.j.swit++;
uni.showWait();
},
complete: function () {
uni.j.swit--;
if (uni.j.swit == 0) uni.hideWait();
sta.ajax_state = "complete";
}
});
},
看了一遍,貌似url并没有发生改变,说明_
不是这一步加上去的……
哭了老哥加油
回归本质,把网页html源码下载下来本地分析……
还是没有找到_
……
回到chrome进行调试
意外发现第三方插件确实没有生成_
,上面的f
中的网址最后没有该参数!
emmm,看来只能是jQuery搞的鬼,可是这代码被混淆了……
突然发现
typora也有这个标记……
原来是时间戳……
破案了!
果然还是缺乏经验,不过这一通操作算是积累了不少阅读js源码的经验……