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

确定?

编辑