中科大研究生信息平台抢课脚本低级版本

    • 一、引言
    • 二、思路
    • 三、程序编写
    • 四、测试
    • 四、总结

一、引言

源于科大的某些开课学院对非本院的学生开课有限制,原则是本院学生优先选课,之后才会给别的学院的学生开放选课权限,导致选课名额很少甚至没有,而申请加课麻烦并且未必加的上,手动抢课还得盯着屏幕影响干其他事情,如果能写一个脚本出来替代人工的话那简直不要太美妙。

二、思路

中科大用的是统一认证平台,我尝试了一下不知道什么原因爬虫没能通过验证,只好采用手动cookie的方法了。自动选课我们要准备四个东西,第一cookie,第二自己的studentid,第三目标课程的courseid,第四个courseSelectTurnAssoc,现在告诉大家如何获取这些参数:

  1. studentid和courseSelectTurnAssoc**

进入选课系统,没错,下图被我马赛克的画横线的地方就是studentid,第二个马赛克就是courseSelectTurnAssoc的数据
中科大研究生信息平台抢课脚本低级版本-编程知识网

  1. courseid

    打开浏览器调式模式,对要选的课进行搜索,我们会在调式的地方看到数据包 。中科大研究生信息平台抢课脚本低级版本-编程知识网
    别错了哟,对应的Network,All,选择std-count数据包
    查看Response就有courseid,我们搜索出了四个,对应上图就有四个知识产权。如果数据包太多,在搜索前clear一下,就是图中右上角灰色的禁止图标。
    中科大研究生信息平台抢课脚本低级版本-编程知识网

  2. cookie

同样的我们查看Header数据,找到cookie 中科大研究生信息平台抢课脚本低级版本-编程知识网

至此,我们已经获得程序必要的三个参数

三、程序编写

# 模块引用
import requests
import time
import smtplib
from email.mime.text import MIMEText
from email.header import Header
import threading
#############全局变量管理##################
#cookie 信息 从浏览器获得 该方法避免了 繁琐的 统一认证平台
cookies_str="_ga=GA1.3.79267311.1599554285;UM_distinctid=176902dc65a27-04b32c81e9051b-5a301e44-151800-xxxxxxxxxxxx"
#studentId 这个也得从 浏览器获得
studentId ="15xxxx"
# courseSelectTurnAssoc 
courseSelectTurnAssoc="381"
# 目标课程的 id 从浏览器获得 132506 代表 高级计算机网络 133574 132503表示计算机应用数学,这里计算机应用数学开了两次课
courseId="132512"				#社会计算
###邮箱服务,当选课成功后或者程序报错及时发邮件通知,如果不懂可以删除####
mail_host="smtp.qq.com"  		#设置服务器
mail_user="xxxxx"    			#用户名
mail_pass="xxxxxx"   	#口令 
###########邮箱服务 end###########################################
#设置请求头
req_header = {'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36','Content-Type': 'application/x-www-form-urlencoded'
}
# 选课请求 url
xuanke_url="https://jw.ustc.edu.cn/ws/for-std/course-select/add-drop-response"
# 查询余量 url
# xuanke_yulinag_url = "https://jw.ustc.edu.cn/ws/for-std/course-select/std-count"
# 获得选课请求 url
xuanke_qingqiu_url="https://jw.ustc.edu.cn/ws/for-std/course-select/add-request"
#################程序主体######################################
# 解析cookie
def SetCookies(cookies_str):cookies={}kv_list=cookies_str.split(';')for kv in kv_list:l=kv.split("=")cookies[l[0]]=l[1]+";Path=/; Domain=.jw.ustc.edu.cn; "return cookies# 获取选课请求id 
def GetXuanKeRequestId(courseId,studentId,courseSelectTurnAssoc):payload="studentAssoc="+studentId+"&lessonAssoc="+courseId+"&courseSelectTurnAssoc="+courseSelectTurnAssoc+"&scheduleGroupAssoc=&virtualCost=0"response = requests.post(xuanke_qingqiu_url, headers=req_header, data=payload,cookies=SetCookies(cookies_str))if response.status_code==200:return response.textelse:return ""
# 返回结果示例
# {'id': 'ecdc71c0-7ef1-11eb-92c9-005056bb0899', 'requestId': 'ecdbfca1-7ef1-11eb-a295-005056bb0c34', 'exception': None, 'errorMessage': {'textZh': '不符合选课条件组要求', 'textEn': 'No suitable selection group', 'text': '不符合选课条件组要求'}, 'success': False}
# {'id': '6449908f-7ef2-11eb-92c9-005056bb0899', 'requestId': '6448cd44-7ef2-11eb-a295-005056bb0c34', 'exception': None, 'errorMessage': {'textZh': '同课程代码只能选一门', 'textEn': 'Duplicate courses are not allowed', 'text': '同课程代码只能选一门'}, 'success': False}
# {'id': '78a1b1bc-7ef2-11eb-92c9-005056bb0899', 'requestId': '78a13ca6-7ef2-11eb-a295-005056bb0c34', 'exception': None, 'errorMessage': None, 'success': True}# 选课请求
def PostXuanKe(courseId,studentId,courseSelectTurnAssoc):try:requestId = GetXuanKeRequestId(courseId,studentId,courseSelectTurnAssoc)if requestId:payload="studentId="+studentId+"&requestId="+requestIdresponse = requests.post(xuanke_url, headers=req_header, data=payload,cookies=SetCookies(cookies_str))if response.status_code==200:if response.json():result = response.json()if result["success"]:print("选课成功!")# 如果没有邮箱服务请注释SnedEmail("接收邮箱号","选课成功!")return Trueelse:print(result["errorMessage"]["textZh"])return Falseelse:return Falseelse:print("执行选课失败")#这个错误很可能是cookies到期了 需要 检查程序SnedEmail("接收邮箱号","执行选课失败")return Falseelse:print("获取请求失败")#这个错误很可能是cookies到期了 需要 检查程序SnedEmail("接收邮箱号","执行选课失败")return Falseexcept Exception as e:print(e)SnedEmail("接收邮箱号","程序报错")return False# 邮箱服务,如果没有请删除
def SnedEmail(resv,msg):sender = mail_user	# 发件人receivers = [resv]  # 接收邮件,可设置为你的QQ邮箱或者其他邮箱# 三个参数:第一个为文本内容,第二个 plain 设置文本格式,第三个 utf-8 设置编码message = MIMEText(msg, 'plain', 'utf-8')message['From'] = Header("程序员", 'utf-8')   # 发送者message['To'] =  Header("结果通知", 'utf-8')        # 接收者message['Subject'] = Header(msg, 'utf-8')try:smtpObj = smtplib.SMTP()#注意Windows 和 Linux此处有区别 否则邮箱会发不出去,linux用smtplib.SMTP_SSL()smtpObj.connect(mail_host, 25)    # linux系统用465smtpObj.login(mail_user,mail_pass)  smtpObj.sendmail(sender, receivers, message.as_string())print("邮件发送成功")except smtplib.SMTPException:print("Error: 无法发送邮件")# 任务函数
def run(courseId):while(1):result=PostXuanKe(courseId,studentId,courseSelectTurnAssoc)if result:break#选课成功 终止任务time.sleep(3)# 3秒执行一次选课,可以减少时间间隔2秒 1秒# 入口函数 目的是为了多线程
def main():t1 = threading.Thread(target=run, args=("132581",))#组合数学t1.start()
# 执行入口函数
main()

四、测试

我把它放在了Centos服务器上托管运行的,指令是nohup,具体可以百度使用方法,python用的是3版本,测试解决还不错
中科大研究生信息平台抢课脚本低级版本-编程知识网
中科大研究生信息平台抢课脚本低级版本-编程知识网

四、总结

按照我的经验,有些课程其实没必要抢,即使一开始你看是满课,但是随着时间的推移有些人会退课的,但是会有个别的课及其火热,比如计算机应用数学,很难抢课,该脚本并没有非法的技术手段,利用的是别人退选的机会迅速抢课,或者开放权限之后迅速做出相应。希望大家可以抢到喜欢的课。