xjtu朋友们手速太快了,只能出此下策(非商用),分享脚本整体逻辑。
首先抓包,抓取移动较大学校app中预定场地的完整http请求包,预定Web网页端貌似不稳定,经常404无法访问,所以只能从app入手了。一层层分析,抽丝剥茧!
1. 直接抓取最后下单POST请求
主要有三个参数:场地信息、滑动验证码信息、Cookie;
1.1 场地信息
order_post_param = {
"stockdetail": {time_id, scenes_id},
"venueReason": "",
"fileUrl": "",
"address": "building_id"
}
主要包含三个参数:
"stockdetail": {time_id, scenes_id}, 里面是具体场地信息, time_id表示时间字段,从早上8点到晚上8点,一共有11个时间段,呈递增变化,比如10.12号下午4点时间场次id是12333,那13号下午4点就是12344,+11就好; scenes_id表示具体的场地信息,每天11个时间段、6个场地,也就是66个id,同样呈递增变化。
"address": "building_id",表示具体的场地楼id,1号巨构是102, 那2和3巨构分别就是103和104,高等博物馆-1估计是其他的。
到此为止基本的订单信息就清楚了。
1.2 滑动验证码信息
order_post_data = {
"param": json.dumps(order_post_param, ensure_ascii=False),
"yzm": yzm,
"json": 'true'
}大撒大撒的撒
下一个参数是滑动验证码信息,每次提交订单,都需要滑动验证码身份验证,然后才能下单成功(多少人像我一样,好不容易打开后有场地,滑动验证码手速慢了,显示已预定,emm),这里其实可以半自动化,脚本把滑动验证码向手机端发出,但也考验手速。
Key=yzm; Value={"bgImageWidth":260,"bgImageHeight":159,"sliderImageWidth":49,"sliderImageHeight":159,"startSlidingTime":"2025-10-29T08:20:59.515Z","entSlidingTime":"2025-10-29T08:21:02.876Z","trackList":[{"x":0,"y":0,"type":"down","t":2299},.{"x":13,"y":2,"type":"move","t":2382},{"x":17,"y":3,"type":"move","t":2398},{"x":20,"y":3,"type":"move","t":2401},
........
{"x":152,"y":51,"type":"move","t":3119},{"x":152,"y":51,"type":"move","t":3152},{"x":152,"y":51,"type":"move","t":3160},{"x":152,"y":51,"type":"move","t":3168},{"x":152,"y":51,"type":"move","t":3177},{"x":152,"y":51,"type":"move","t":3185},{"x":152,"y":51,"type":"up","t":3361}]}synjones7f2ca513bd6540eeb7ab69b3f51120basynjoneshttp://202.117.17.144:8071
这是我抓取到最终post订单请求中的yzm信息,整体就是slider和bg的基本信息(滑动窗口验证页面reponse中自带)、滑动信息、验证id(滑动窗口验证页面reponse中自带)、端口
主要滑动信息,我就不细说破解原理了,流程如下:
a. 计算缺口位置,得到滑动距离len
b. 根据len模拟人工滑动轨迹(x、y、移动方向move、时间t),要注意有抖动,有幅度、无异常值、满足趋势,像人工!
c. 最终按照要求格式打包成yzm就好
1.3 最后是Cookie
到这里,其实已经可以实现脚本抢单了,每天早点登录app,抓取登录的Cookie,然后手动更新参数,就可以了。但这种半自动化还是不方便,因此需要搞定这个Cookie,也是老大难问题。
2. 登陆验证
整体分为两步,登录+cas验证
登录流程就是:
step1:首先拿到登录jwt验证的publicKey
step2:利用上一步拿到的publicKey对用户名和password进行RSA加密
step3:加密后的信息发给login端进行MFA验证
step4:MFA验证通过后才发出真正的POST登录请求,最终得到一个idtoken(后续都会用到)
cas授权验证流程:这里全是302重定向(多层验证),学校貌似会更新授权验证逻辑,这是2025最新版本的
step1:首先利用刚才的idtoken,访问openplatform,会302重定向到第二层cas验证url
step2:访问第二层cas验证,会得到一个cookie,然后302
step3:带着刚才的cookie访问登陆服务器,会再得到一个cookie(TGC),然后302
step4:带着当前两个cookie访问cas回调url, 然后302
step5:再此访问cas验证,会得到一个code参数
step6:带着得到的code参数,访问openplatform,得到最终cas验证的url
step7:最终cas验证,拿到数据访问session的cookie!
到此为止,整个脚本逻辑就清楚了,大致400行code,实现预约功能;
最后在附加一个shell脚本,后台启动,每天8:39分定时执行python脚本,完成订单!
//附带shell脚本code
source ~/anaconda3/etc/profile.d/conda.sh
conda activate py10
SCRIPT_PATH=./order_auto.py
read -p "请输入用户名: " USERNAM
read -s -p "请输入密码(输入时不可见): " PASSWORD
echo ""
read -p "请输入要预约的场地号(例如 3): " SCENE
# 设定目标时间(24小时制)
TARGET_HOUR=8
TARGET_MIN=39
TARGET_SEC=0
echo " 等待系统时间到达 ${TARGET_HOUR}:${TARGET_MIN}:${TARGET_SEC} ..."
echo "用户名: $USERNAME | 场地号: $SCENE
while true; do
current_hour=$(date +%H)
current_min=$(date +%M)
current_sec=$(date +%S)
# 到达目标时间则执行
if [ "$current_hour" -eq "$TARGET_HOUR" ] && \
[ "$current_min" -eq "$TARGET_MIN" ] && \
[ "$current_sec" -ge "$TARGET_SEC" ]; then
now=$(date '+%Y-%m-%d %H:%M:%S')
echo " 时间到!当前系统时间:$now"
echo "开始执行 Python 脚本..."
python $SCRIPT_PATH $USERNAME $PASSWORD $SCENE
echo " 任务完成:$(date '+%Y-%m-%d %H:%M:%S')"
break
fi
sleep 0.5
done
确定?
编辑
