用Python模拟登录华工新版教务系统选课 (PyExecJS)

之前学校用的是老版正方教务系统,也写过文章,而最近学校更换了教务系统,作为计算机的学生,当然还是看看能不能写个脚本抢下课啦。

具体用的时候也需要加点多线程的功能,我大概开了15个线程吧,不得不说学校这次的教务系统的服务器比之前的好了。

成果大概就是帮一位女同学成功抢到了课(主要是脚本也没有扩散,毕竟如果多人使用这种脚本对服务器还是有点影响的

模拟登录请求

第一步是登录一次教务系统,然后抓包看看数据包的构成

我们发现数据包由 rsa,ul,pl,it,execution,_eventid构成,我们一一在Chrome Network左侧搜索,我们很容易能够找到lt,execution,这在html里面就有,而这个数据是变化的,所以必须每次请求获得。

然后我们搜索rsa,rsa这个一看就知道是已加密的内容,所以必定在js里面出现,我们很快就能找到rsa,并且得知ul和pl是用户名和密码的长度信息,所以我们就只用得到rsa即可完成模拟登录了。

然而这个加密是在另外一个名叫des.js的文件完成的,这个函数名为strEnc,第一个参数为用户名、密码和lt值的拼接,并且我初步观察了加密的流程,是比较复杂的,根据平常爬虫的思路,我们有两种办法:

1.用Python直接模拟加密过程

2.用selenium

第一种方法显然是比较复杂的,所以我尝试了些许时间就放弃了,而第二种方法由于运行速度比较慢,所以也被我排除了。

于是我就想到能不能运行js文件来获得同样的效果,所以我用了一个名为 PyExecJS 的Python库来运行js文件,我们首先把des.js这个文件下载到本地,然后再操作。

所以到这里,我们的登录流程差不多已经理好思路了,开始写代码了。

登录代码

我们获得一个Session对象,我们选课的核心即是获取登录成功的Cookie值,请求一次登录页面然后用正则表达式获取这两个数据的值。

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0'
}

session = requests.Session()
r = session.get('https://sso.scut.edu.cn/cas/login?service=http%3A%2F%2Fxsjw2018.scuteo.com%2Fjwglxt%2F%2Fdriotlogin',headers=headers)
lt = re.findall('id="lt" name="lt" value="(.*?)"',r.text)[0]
execution = re.findall('name="execution" value="(.*?)"',r.text)[0]

随后利用PyexecJS这个库运行js代码获得rsa值,首先compile des.js代码,然后利用call方法调用strEnc函数获得rsa的值。

with open('des.js')as f:
    ctx = execjs.compile(f.read())
s = user+pw+lt
rsa = ctx.call('strEnc',user+pw+lt,'1','2','3')

获得到rsa值以后,就可以构造登录的数据包进行登录了

login_data = {
    'rsa':rsa,
    'ul':len(user),
    'pl':len(pw),
    'lt':lt,
    'execution':execution,
    '_eventId':'submit'
}
r = session.post('https://sso.scut.edu.cn/cas/login?service=http%3A%2F%2Fxsjw2018.scuteo.com%2Fjwglxt%2Fdriotlogin',data=login_data,headers=headers)

选课过程

多选几门课,进行抓包,然后分析数据包的构成,根据分析,主要是前三项数据决定了是哪门课程,而这些信息都在html里面有,所以就不细说了,不过需要注意的是一直要用我们首先创建的Session对象才能正常发送请求。