侯体宗的博客
  • 首页
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Python Requests模拟登录实现图书馆座位自动预约

Python  /  管理员 发布于 7年前   317

本文实例为大家分享了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的会话
  • 拿到<input type=hidden>的数据并传递到post的数据中
  • 抓包判断网站逻辑,筛选出各个请求的参数,并在程序中实现

函数解释

  • class FUCK()主类
  • _get_date_str(self):获取当前日期,并加上一天,用这个函数构造url的特征字段(图书馆设置提前一天预约座位)
  • def _get_order_url(self):构造"预约座位"的post目标url
  • def _get_static_post_attr:这个函数解析get请求的返回页面,并从中提取出<input type=hidden>的字段,用于之后的构造post数据
  • def login(self):实现登录功能
  • def run(self):实现座位预约功能
  • def _is_success(self, text):判断预约结果
  • def error_log_once(self, text='default error (once)'):
  • def error_log(self, text='default error'):这两个函数设置程序状态为"已经出错"或者"未出错"状态(用于自动化运行的时候避免将重复的错误信息写入日志)
  • def error_log(self, text='default error'):单次将错误信息写入本地日志
  • sendmail.send_mail()邮件发送模块

代码及注释

# /bin/python# -*- coding:utf-8 -*-import timeimport sysimport requestsfrom bs4 import BeautifulSoupfrom mail import sendmail__author__ = 'xy'# 主类class FUCK(): 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的会话  # post data for login  self.data1 = {   'subCmd': 'Login',   'txt_LoginID': self.username, # S+学号   'txt_Password': self.password, # 密码   'selSchool': 60, # 60表示北京交通大学  }  # post data for order a seat  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')  return date_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):  """  拿到<input type='hidden'>的post参数,并添加到post_data中  """  soup = BeautifulSoup(page_content, "html.parser")  for each in soup.find_all('input'):   if 'value' in each.attrs and 'name' in each.attrs:    data_dict[each['name']] = each['value'] # 添加到login的post_data中    # self.data2[each['name']] = each['value'] # 添加到order的post_data中  return data_dict def _debug(self):  print self.order_url  print self.data1  print self.data2  print self.headers  print self.s.cookies  # print self.login_content  # print self.middle_content  print self.final_content def login(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 def run(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 '<h5 id="MessageTip">已经存在有效的预约记录。</h5>' in text:   self.clear_error_once('[done!] You already ordered a seat!')  elif '<h5 id="MessageTip">选择的日期不允许预约。</h5>' in text:   self.clear_error_once('[done!] Date is wrong!')  elif '<h5 id="MessageTip">所选座位已经被预约。</h5>' in text:   self.clear_error_once('[done!] This seat is not available, maybe taken by others!')  elif '<h5 id="MessageTip">座位预约成功' in text:   self.clear_error_once('[done!] Success! An email is sending to you!')   sendmail.send_mail('BJTU Library Seat_NO:' + self.seatNO + 'ordered!',        'Sending by robot. Do not reply this mail!', self.mailto)  else:   self.error_log_once('Error! 302 to login page') def error_log_once(self, text='default error (once)'):  try:   is_error_file = open('./isopen_xy.txt', 'r')  except:   is_error_file = open('./isopen_xy.txt', 'w')  if '1' not in is_error_file.read():   print 'writting error to log...'   self.error_log(text)  else:   print 'already written to log'  is_error_file.close()  sendmail.send_mail('BJTU_Library system error once !', 'error text!') def error_log(self, text='default error'):  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() def clear_error_once(self, text='success'):  print text  is_error_file = open('./isopen_xy.txt', 'w')  is_error_file.write('0\n')  is_error_file.close()if __name__ == '__main__': if len(sys.argv) < 5:  print 'Usage: python library.py [username] [password] [seat_NO] [email]'  print 'eg. python library.py S13280001 123456 003 [email protected]\n'  print 'Any problems, mail to: i[at]cdxy.me'  print '#-*- Edit by cdxy 16.03.24 -*-'  sys.exit(0) else:  FUCK(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


  • 上一条:
    详解python多线程、锁、event事件机制的简单使用
    下一条:
    Python多线程中阻塞(join)与锁(Lock)使用误区解析
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在go语言中实现字符串可逆性压缩及解压缩功能(0个评论)
    • 使用go + gin + jwt + qrcode实现网站生成登录二维码在app中扫码登录功能(0个评论)
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客