Python Requests模拟登录实现图书馆座位自动预约
本文实例为大家分享了Python实现图书馆座位自动预约的具体代码,供大家参考,具体内容如下
配置
通过公网主机定时运行脚本,并发送邮件到自己的qq邮箱,这样在微信就会有消息提示是否预约成功
vim/etc/crontab
设置每到早上7:01自动运行脚本即可
程序流程
(以yuyue.juneberry.cn网站为例)
- get访问登录页面,获取cookie和表单里面的隐藏post字段
- 构造登录post数据,加入从表单里面拿到的隐藏post字段
- post构造后的数据,模拟登录,激活cookie(使cookie有登入权限)
- get访问座位预约界面,激活cookie(使cookie有预约座位权限)
- post预约请求,实现预约座位
- 解析返回结果,判断是否成功,并邮件提醒
要点
- requests库中的requests.session()能够创建可传递cookies的会话
- 拿到
的数据并传递到post的数据中 - 抓包判断网站逻辑,筛选出各个请求的参数,并在程序中实现
函数解释
- classFUCK()主类
- _get_date_str(self):获取当前日期,并加上一天,用这个函数构造url的特征字段(图书馆设置提前一天预约座位)
- def_get_order_url(self):构造"预约座位"的post目标url
- def_get_static_post_attr:这个函数解析get请求的返回页面,并从中提取出
的字段,用于之后的构造post数据 - deflogin(self):实现登录功能
- defrun(self):实现座位预约功能
- def_is_success(self,text):判断预约结果
- deferror_log_once(self,text='defaulterror(once)'):
- deferror_log(self,text='defaulterror'):这两个函数设置程序状态为"已经出错"或者"未出错"状态(用于自动化运行的时候避免将重复的错误信息写入日志)
- deferror_log(self,text='defaulterror'):单次将错误信息写入本地日志
- sendmail.send_mail()邮件发送模块
代码及注释
#/bin/python #-*-coding:utf-8-*- importtime importsys importrequests frombs4importBeautifulSoup frommailimportsendmail __author__='xy' #主类 classFUCK(): def__init__(self,username,password,seatNO,mailto): """ 以四个参数初始化,用户名,密码,要预约的座位号,接受预约结果提醒邮件的邮箱 """ self.username=username self.password=password self.seatNO=seatNO self.mailto=mailto self.base_url='http://yuyue.juneberry.cn' self.login_url='http://yuyue.juneberry.cn' self.order_url=self._get_order_url() self.login_content='' self.middle_content='' self.final_content='' self.s=requests.session()#创建可传递cookies的会话 #postdataforlogin self.data1={ 'subCmd':'Login', 'txt_LoginID':self.username,#S+学号 'txt_Password':self.password,#密码 'selSchool':60,#60表示北京交通大学 } #postdatafororderaseat self.data2={ 'subCmd':'query', } #自定义http头,然而我在程序里并没有使用 self.headers={ 'Connection':'keep-alive', 'Content-Type':'application/x-www-form-urlencoded', } self.login() self.run() self._is_success(self.final_content) #怀疑程序出错时,取消下行注释,可打印一些参数 #self._debug() def_get_date_str(self): s=time.localtime(time.time()) ########333 date_str=str(s.tm_year)+'%2f'+str(s.tm_mon)+'%2f'+str(s.tm_mday+1) date_str=date_str.replace('%2f1%2f32','%2f2%2f1')\ .replace('%2f2%2f29','%2f3%2f1')\ .replace('%2f3%2f32','%2f4%2f1')\ .replace('%2f4%2f31','%2f5%2f1')\ .replace('%2f5%2f32','%2f6%2f1')\ .replace('%2f6%2f31','%2f7%2f1')\ .replace('%2f7%2f32','%2f8%2f1')\ .replace('%2f8%2f32','%2f9%2f1')\ .replace('%2f9%2f31','%2f10%2f1')\ .replace('%2f10%2f32','%2f11%2f1')\ .replace('%2f11%2f31','%2f12%2f1')\ .replace('%2f12%2f32','%2f1%2f1') returndate_str def_get_order_url(self): return"http://yuyue.juneberry.cn/BookSeat/BookSeatMessage.aspx?seatNo=101001"+self.seatNO+"&seatShortNo=01"+self.seatNO+"&roomNo=101001&date="+self._get_date_str() def_get_static_post_attr(self,page_content,data_dict): """ 拿到的post参数,并添加到post_data中 """ soup=BeautifulSoup(page_content,"html.parser") foreachinsoup.find_all('input'): if'value'ineach.attrsand'name'ineach.attrs: data_dict[each['name']]=each['value']#添加到login的post_data中 #self.data2[each['name']]=each['value']#添加到order的post_data中 returndata_dict def_debug(self): printself.order_url printself.data1 printself.data2 printself.headers printself.s.cookies #printself.login_content #printself.middle_content printself.final_content deflogin(self): homepage_content=self.s.get(self.base_url).content self.data1=self._get_static_post_attr(homepage_content,self.data1) r=self.s.post(self.login_url,self.data1) self.login_content=r.content defrun(self): #这个get的意思是:原先的cookie没有预约权限, #访问这个get之后,会使cookie拥有预约权限,从而执行下一个post self.middle_content=self.s.get('http://yuyue.juneberry.cn/BookSeat/BookSeatListForm.aspx').content #经测试,这个post只需要一个subCmd的参数就可以正常返回,因此不必根据get内容更新post参数 #self.data2=self._get_static_post_attr(middle_content,self.data2) #这个post请求完成了预约功能! r=self.s.post(self.order_url,self.data2) self.final_content=r.content def_is_success(self,text): """ 接受最终的html内容,判断是否成功,并触发日志记录和邮件提醒 """ if' 已经存在有效的预约记录。'intext: self.clear_error_once('[done!]Youalreadyorderedaseat!') elif' 选择的日期不允许预约。'intext: self.clear_error_once('[done!]Dateiswrong!') elif' 所选座位已经被预约。'intext: self.clear_error_once('[done!]Thisseatisnotavailable,maybetakenbyothers!') elif' 座位预约成功'intext: self.clear_error_once('[done!]Success!Anemailissendingtoyou!') sendmail.send_mail('BJTULibrarySeat_NO:'+self.seatNO+'ordered!', 'Sendingbyrobot.Donotreplythismail!',self.mailto) else: self.error_log_once('Error!302tologinpage') deferror_log_once(self,text='defaulterror(once)'): try: is_error_file=open('./isopen_xy.txt','r') except: is_error_file=open('./isopen_xy.txt','w') if'1'notinis_error_file.read(): print'writtingerrortolog...' self.error_log(text) else: print'alreadywrittentolog' is_error_file.close() sendmail.send_mail('BJTU_Librarysystemerroronce!','errortext!') deferror_log(self,text='defaulterror'): is_error_file=open('./isopen_xy.txt','w') is_error_file.write('1\n') is_error_file.close() f=open("./log_xy.txt",'a') f.write(time.strftime("%Y-%m-%d%X",time.localtime())+text+'\n') f.close() defclear_error_once(self,text='success'): printtext is_error_file=open('./isopen_xy.txt','w') is_error_file.write('0\n') is_error_file.close() if__name__=='__main__': iflen(sys.argv)<5: print'Usage:pythonlibrary.py[username][password][seat_NO][email]' print'eg.pythonlibrary.pyS13280001123456003XXXX@qq.com\n' print'Anyproblems,mailto:i[at]cdxy.me' print'#-*-Editbycdxy16.03.24-*-' sys.exit(0) else: FUCK(sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4])
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。