python 实现图书馆、体育馆自动预约功能 您所在的位置:网站首页 清华大学门票如何预约 python 实现图书馆、体育馆自动预约功能

python 实现图书馆、体育馆自动预约功能

2023-08-04 14:25| 来源: 网络整理| 查看: 265

武汉大学体育馆场地可以从网上进行预约,包括羽毛球场,乒乓球场等。预约系统最近是晚上6点开始,可以预约未来2天内的场地。在所有场馆中,室内羽毛球场最为抢手,经常出现系统刚开放所有场地就被“秒杀”的情况。我有几天很想去打羽毛球但是是死活约不到场地,对此我很生气啊,所以就在思考能不能用python制作一个“抢场地机器人”,使其在系统开放预约时准时启动,代替人完成预约任务。

在开始之前,请确保你已经准备好:

Python 3.5 或以上;一个顺手的编辑器 / IDE,如PyCharm、Sublime Text;Python基本语法知识几个第三方库,requests,剩下time、json、smtplib、email、sys好像是标准库,自带了,无需安装

这篇教程适用于武汉大学体育馆预约系统,链接在这。

 

python实现思路

正常手动预约非常简单,先登录然后查找对应时间可用的场地,点击预约即可,这里还有一步比较关键是支付,调用微信支付并完成支付还是比较麻烦的,但是如果本省在系统中有足够的余额便可以一键支付。转换成python来看就更简单了了,首先登陆,在保证账户余额足够的情况下,可以跳过查找位置的问题,直接对向预约的场地发起预约请求,使用余额支付即可。接下来就让我们试试看:

首先是登陆用户,很简单,这个登陆界面链验证码都没有,非常easy,打开浏览器的F12,切换到网络界面,勾选持续日志,输入用户名和密码,就登入了系统,在浏览器的网络界面中(Firefox和Chrome皆可),就可以看到有一个POST请求的参数就是你的用户名和密码,用这个地址就可以用python登陆咯。这是登录后的界面。

 

登录其实就是你把用户名密码提交过去,服务器给你返回一个Token或者Session,使用这个作为cookie的一部分后续服务器就知道你是谁了,所以使用python第一步登录然后就是获取这个Token或者Session。这个服务器使用的是session,登录并获取session的代码这样写。这里注意一点,进行post访问的时候需要一个文件头,来伪装自己的身份,否则原始程序的身份可能会不能访问哦。

def Login(name,pass): url = 'http://gym.whu.edu.cn/loginAction!UserLogin' head = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0'} param = {'name':name, 'password':pass} session = requests.Session().post(url, headers = head, data = param) return(session.cookies.get_dict())

登录之后,并成功获取了Session,接下来正常操作应该是找可用场地,但是我们是直接预约嘛,其实是可以跳过找场地这个过程的,直接看看提交预约时,你给服务器发送的数据即可。在浏览器中进行一次提交,找到这个关键的post,可以看到以下几个参数

fdId=32 beginTime=2019-09-21+12:30:00 endTime=2019-09-21+13:30:00 ffId=4 ggId=2 usrId=990 money=7.00 ordTime=2019-09-19+19:30:00 payType=2

研究了下,fdid应该是预定的场地编号,后面是起止时间,然后ffid是运动类型编号,ggid是场馆编号,usrId应该是使用cookie的用户账户,尝试登陆其他账户也是990,就不用了管了,接下来花钱的金额,后面ordtime应该就是请求发出的时间,最后支付类型,使用python把这些参数发出即可。函数这么写

def Res(JSESSIONID, fdId): Time = '2019-09-21' url = 'http://gym.whu.edu.cn/OrderAction!bookOrder?deposit=0.00' head = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0', 'Host': 'gym.whu.edu.cn', 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2', 'Accept-Encoding': 'gzip, deflate', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-Requested-With': 'XMLHttpRequest', 'Content-Length': '150', 'Connection': 'keep-alive', 'Referer': 'http://gym.whu.edu.cn/wechat/booking/gymHome.jsp?ggId=4', 'Cookie': 'iPlanetDirectoryPro=kZtrSgx3gCXpsQecF4Elfb; JSESSIONID=' + JSESSIONID} strtime = time.strftime('%Y-%m-%d+%H%%3A%M%%3A%S',time.localtime(time.time())) param = 'fdId=' + fdId + '&beginTime=' + Time +'+19%3A30%3A00&endTime=' + Time +\ '+20%3A30%3A00&ffId=18&ggId=4&usrId=990&money=10.00&ordTime=' + strtime + '&payType=2' res = requests.post(url, data = param, headers = head, verify=False) return(res)

这儿我把头写的完善了点, 把乱起八糟的东西都加上了,还有最重要的session。仔细看代码,有些不一样

这里敲黑板,这里坑害了我好久,让我尝试无数遍的地方。

哪里不一样呢?在参数中的时间那,本来是冒号的地方我改成了%3A,参数直接写成冒号传入,报错Struts Problem Report,这个错误害的我好苦,网上并没有解决方案。最后试了许久想到是不是编码的问题,所以换了下编码方式,具体想了解Unicode和UTF-8以及ANSI的同学可以自行百度。换成这个传入参数柳暗花明又一村,终于成功了,击掌!!!!

最后,预定成功了,我得知道啊,上网查了下,我微信QQ都不如发邮件方便,这个都是网上查的,直接上代码吧。

def send(flag, mess): #传入flag(成功与否的标志),mess(预定的位置时间) mail = smtplib.SMTP() mail.connect("smtp.qq.com") # 连接 qq 邮箱的SMTP服务 mail.login("[email protected]", "xxxx") # 账号和授权码 if flag == 1: print('预定成功') message = MIMEText(mess) # 邮件内容 message['Subject'] = Header('羽毛球场预定成功提醒') # 邮件主题 mail.sendmail("[email protected]", ["[email protected]"], message.as_string()) # 发送账号、接收账号和邮件信息

授权码查找方法如上所示。

好了,基本主要功能就完成了,在指定时间把程序跑起来就可以了,不需要掐好时间,我的想法是没到时间代码就沉睡,每10s判断一下到时间没,到开始预约的前一分钟,开始登陆预约操作,直到预约成功,发送邮件并跳出循环,结束程序,代码就完成了。

if __name__ == '__main__': print('sleep_now', end = '') #未到时间,休眠 while True: strtime = time.strftime('%H%M',time.localtime(time.time())) if strtime == '1759': print('Start Booking') res = Res(jsid, '36') trytime = 1 while res.headers['Content-Length'] != '1': trytime += 1 res = Res(jsid, '36') time.sleep(1) if trytime > 20: send(0, '预定失败') print(trytime) sys.exit() send(1, '预定成功') break else: time.sleep(10) print('.', end = '')

最后,放一个全部代码吧,方便大家使用

import requests import time import json import smtplib from email.mime.text import MIMEText from email.header import Header import sys def Login(name,pass): url = 'http://gym.whu.edu.cn/loginAction!UserLogin' head = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0'} param = {'name':name, 'password':pass} session = requests.Session().post(url, headers = head, data = param) return(session.cookies.get_dict()) def Res(JSESSIONID, fdId): Time = '2019-09-21' url = 'http://gym.whu.edu.cn/OrderAction!bookOrder?deposit=0.00' head = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0', 'Host': 'gym.whu.edu.cn', 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2', 'Accept-Encoding': 'gzip, deflate', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-Requested-With': 'XMLHttpRequest', 'Content-Length': '150', 'Connection': 'keep-alive', 'Referer': 'http://gym.whu.edu.cn/wechat/booking/gymHome.jsp?ggId=4', 'Cookie': 'iPlanetDirectoryPro=kZtrSgx3gCXpsQecF4Elfb; JSESSIONID=' + JSESSIONID} strtime = time.strftime('%Y-%m-%d+%H%%3A%M%%3A%S',time.localtime(time.time())) param = 'fdId=' + fdId + '&beginTime=' + Time +'+19%3A30%3A00&endTime=' + Time +\ '+20%3A30%3A00&ffId=18&ggId=4&usrId=990&money=10.00&ordTime=' + strtime + '&payType=2' res = requests.post(url, data = param, headers = head, verify=False) return(res) def Send(flag, mess): #传入flag(成功与否的标志),mess(预定的位置时间) mail = smtplib.SMTP() mail.connect("smtp.qq.com") # 连接 qq 邮箱的SMTP服务 mail.login("[email protected]", "xxxx") # 账号和授权码 if flag == 1: print('预定成功') message = MIMEText(mess) # 邮件内容 message['Subject'] = Header('羽毛球场预定成功提醒') # 邮件主题 mail.sendmail("[email protected]", ["[email protected]"], message.as_string()) # 发送账号、接收账号和邮件信息 if __name__ == '__main__': print('sleep_now', end = '') #未到时间,休眠 while True: strtime = time.strftime('%H%M',time.localtime(time.time())) if strtime == '1759': print('Start Booking') res = Res(jsid, '36') trytime = 1 while res.headers['Content-Length'] != '1': trytime += 1 res = Res(jsid, '36') time.sleep(1) if trytime > 20: Send(0, '预定失败') print(trytime) sys.exit() Send(1, '预定成功') break else: time.sleep(10) print('.', end = '')

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有