使用Python webdriver图书馆抢座自动预约的正确方法


Posted in Python onMarch 04, 2021

文章目录 微信登录问题Python chrome driver操作导入库并声明浏览器:完整流程:用js来预约生成js代码 主函数——程序出错时尝试:检测是否成功:logging: 生成每天的日志文件 Windows定时任务后记:
学校的图书馆需要网上预约。复习考研的人多、疫情座位少,约上一个好点的座位对于我这种经常忘记事情的懒人来说很难。

考虑到老师实验室有一台供我们使用的Windows服务器是不会关机的,正好可以帮我在早上7:00预约系统开启的时候执行程序去预约一个座位。所以产生了这个想法。

微信登录问题

想用chromedriver去操作,方便快捷,但我们图书馆的预约在微信上进行的,在微信公众号上认证过帐号以后,会发送一个链接,点进去就是自己的登录信息。经过和同学的验证,他将他的链接发送给我,我就可以打开他的登录信息。这让我感到很神奇,本以为登录信息仅仅携带在网址上,但如果在微信中用浏览器打开,再将网址复制到其它浏览器,会登陆失败。查找一系列百度谷歌想弄清楚这个问题,应该与cookies之类的有关,这里希望以后可以填坑。

当我没有找到头绪的时候,我偶然间发现学校图书馆开放了另一个入口可以在网页上预约,而这个流程就清晰很多了:

  • 进入网站
  • 输入账号和密码,点击登录按钮
  • 找到座位并选择

Python chrome driver操作

使用Python webdriver图书馆抢座自动预约的正确方法

有几个注意的点:

  • 每天早上系统开放的时间有几分钟的差别,需要留时间尝试。
  • 刚开放的时候,系统会很卡,所以很可能会出现获取元素失败之类的情况。

这就要求我们的程序得有足够的鲁棒性(哈哈蛤) 容错能力,不会一下崩了就没用了。
所以我选择用try...except...的方法去进行,写了好多个try, 希望能找到不写这么多Try的更好的方法。

导入库并声明浏览器:

from selenium import webdriver
option = webdriver.ChromeOptions()
url='网址'
local_dir = 'C:\\Users\\Administrator\\Desktop\\librarytest\\' #webdiriver 位置
browser = webdriver.Chrome(local_dir+"chromedriver.exe",options=option)

完整流程:

使用selenium操作非常简单,就是find_element_by_id()find_element_by_xpath(),主要是看F12去找他们的xpath或者id。

def wholeProcess(browser):
 browser.get(url)
 try:
 btn=browser.find_element_by_xpath("/html/body/div[4]/div[2]/div[2]/dl/input") #找到登录的按钮,如果没找到证明还没到开放时间/系统在崩溃
 except:
 return 1 #1说明预约还没到时候
 '''执行到这里说明打开啦'''
 try:
 btn.click()
 username=browser.find_element_by_id("un")
 password=browser.find_element_by_id("pd")#找到账号密码
 username.send_keys(studentNumber)
 password.send_keys(loginPassword)
 btn=browser.find_element_by_xpath('//*[@id="index_login_btn"]/input')#找到登录按键
 btn.click()
 js=generateJsCode(startTime,endTime)#使用js代码来预约
 res=browser.execute_script(js)
 return 0
 except:
 return 2 #2说明打开了网页,但是遇到了其它问题

用js来预约

找到座位并选择,如果用鼠标操作的话是很繁琐的,包括先找到座位图标点击下拉选择开始时间和结束时间,再点击预约,这个过程麻烦不说,主要是容易出错。
而其实一个座位预定的本质其实是提交一个表单。浏览器的前端做了那么多人性化的操作,如可视化座位表、下拉框、温馨提示等,就是为了人使用时好看而又方便,而我们作为计算机就可以饶过他,直接提交表单。这里用的是selenium的execute_script()函数,可以用来执行网页上的js代码。

生成js代码

用F12去观察发现,图书管的表单提交需要下面几步:

$("#date").val("2020-12-10"); 
$("#reserveForm#seat").val("13022"); //座位号
$("#start").val("540"); //用分钟表示的时间 : 540=9*60 即九点
$("#end").val("1260");
$("#reserveForm").submit();

因此这个函数用来生成js代码:

def generateJsCode(startTime_ori,endTime_ori):
 seatnumber_str = seatId
 startTime_str = str(startTime_ori * 60)
 endTime_str = str(endTime_ori * 60)
 tomorrowTime = (datetime.datetime.now() + datetime.timedelta(days=1)).strftime('%Y-%m-%d') # 明天
 js = '$("#date").val("' + tomorrowTime + '");$("#reserveForm #seat").val("' + seatnumber_str + '");$("#start").val("' + startTime_str + '");$("#end").val("' + endTime_str + '");$("#reserveForm").submit();'
 return js

主函数——程序出错时尝试:

返回的状态中,如果网页没打开,让他休息10s再尝试,如果是其它原因,那么休息0.5秒就继续尝试:

if __name__=='__main__':
 browser = webdriver.Chrome(local_dir+"chromedriver.exe",options=option)#声明浏览器
 while True:
 state=wholeProcess(browser)
 if state==0: #没出错
  break:
 elif state==1: 
  logger.info("打开网页失败")
  time.sleep(10)
 elif state==2: 
  logger.info("其它错误")
  time.sleep(0.5)

检测是否成功:

除了上面提到的网页崩溃导致WebDriver报错,还有几种可能导致失败:

  • 座位被人抢了?
  • 已经有过预约了
  • 有人约了但不是全部时间段。

这几种错误都不会报错,会在执行代码后以标签的形式告诉我们,可以用关键字定位这些标签,如果失败可以选择预约PlanB:
比如:

try:
 a=browser.find_element_by_xpath("//*[contains(text(),'尽快')]") #有人约了(非全部时间)
 error_reason=a.text
 isNoSeat=True

logging: 生成每天的日志文件

写好小程序以后,几个兄弟听说了也想尝试,每天预约。
不想每天早上七点起来看,为了防止为止错误发生后还不知道是哪步出错,采取的办法是写日志文件(事后追责),这里使用的是logging这个包。
logger的初始化代码来源 : python的logging模块

import logging
# 创建一个logger
logger = logging.getLogger('mylogger')
logger.setLevel(logging.DEBUG)
# 创建一个handler,用于写入日志文件
fh = logging.FileHandler(local_dir+'logfile\\'+logname+'.log')
fh.setLevel(logging.DEBUG)
# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# 定义handler的输出格式
formatter = logging.Formatter('[%(asctime)s][%(thread)d][%(filename)s][line: %(lineno)d][%(levelname)s] ## %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# 给logger添加handler
logger.addHandler(fh)
logger.addHandler(ch)
# 记录一条日志

记录时只要使用 logger.info("xxxxx")就可以,非常方便,写在了上面。

Windows定时任务

  •  此电脑上右键管理
  • 右侧有创建任务(下图)

使用Python webdriver图书馆抢座自动预约的正确方法

  • 触发器选项卡中新建,并设定时间
  • 操作选项卡中新建,并选择程序路径(下图)

使用Python webdriver图书馆抢座自动预约的正确方法

这样就程序就会每天早上执行,只要有一台不关机的电脑。

后记:

大家开始使用我的代码,但都是我放在学校的服务器上,为了方便他们修改自己想要的预约时间、位置等信息,我写了个微信小程序方便同学修改时间。

思路就是使用微信小程序修改自己的预约信息,同步到微信的数据库。
早上预约时,我的程序通过微信云开发数据库的API获取到这些预约信息(时间、座位、学号、密码),再去预约,免去了总要去服务器上修改程序/参数的麻烦事。
具体的小程序部分的内容这里不展开,以后再写日记。

这就是上学期快期末的时候搞的一个小事情,虽然原理非常简单,但能帮自己和同学去预约图书馆还是很快乐的,尤其是每天早上醒来大家都收到企业微信的“预约成功”的提示的时候,然而过程中还有一些没懂的知识和没填的坑,所以在CSDN写个小记,怕以后忘了。

到此这篇关于使用Python webdriver图书馆抢座自动预约的正确方法的文章就介绍到这了,更多相关Python webdriver图书馆抢座自动预约内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
跟老齐学Python之集成开发环境(IDE)
Sep 12 Python
Python列表append和+的区别浅析
Feb 02 Python
各种Python库安装包下载地址与安装过程详细介绍(Windows版)
Nov 02 Python
python 中split 和 strip的实例详解
Jul 12 Python
python+selenium打印当前页面的titl和url方法
Jun 22 Python
使用python绘制3维正态分布图的方法
Dec 29 Python
Python中捕获键盘的方式详解
Mar 28 Python
PyTorch中Tensor的维度变换实现
Aug 18 Python
基于pandas中expand的作用详解
Dec 17 Python
Python基于class()实现面向对象原理详解
Mar 26 Python
基于Python-turtle库绘制路飞的草帽骷髅旗、美国队长的盾牌、高达的源码
Feb 18 Python
python实现股票历史数据可视化分析案例
Jun 10 Python
Python与C/C++的相互调用案例
Mar 04 #Python
解决Python import .pyd 可能遇到路径的问题
Mar 04 #Python
关于PySnooper 永远不要使用print进行调试的问题
Mar 04 #Python
pip/anaconda修改镜像源,加快python模块安装速度的操作
Mar 04 #Python
Pytorch实现WGAN用于动漫头像生成
Mar 04 #Python
基于PyInstaller各参数的含义说明
Mar 04 #Python
解决Pyinstaller打包软件失败的一个坑
Mar 04 #Python
You might like
隐藏你的.php文件的实现方法
2007/03/19 PHP
PHP ajax 分页类代码
2008/11/13 PHP
PHP+ajax 无刷新删除数据
2010/02/20 PHP
php 解压rar文件及zip文件的方法
2014/05/05 PHP
浅析php创建者模式
2014/11/25 PHP
PHP用mysql_insert_id()函数获得刚插入数据或当前发布文章的ID
2016/11/25 PHP
php实现文件上传及头像预览功能
2017/01/15 PHP
PHP基于面向对象封装的分页类示例
2019/03/15 PHP
PHP const定义常量及global定义全局常量实例解析
2020/05/28 PHP
javascript:void(0)是什么意思示例介绍
2013/11/17 Javascript
JavaScript实现动画打开半透明提示层的方法
2015/04/21 Javascript
基于javascript代码检测访问网页的浏览器呈现引擎、平台、Windows操作系统、移动设备和游戏系统
2015/12/03 Javascript
nodejs简单实现操作arduino
2016/09/25 NodeJs
JavaScript 限制文本框不可输入英文单双引号的方法
2016/12/20 Javascript
Vue2.0基于vue-cli+webpack父子组件通信(实例讲解)
2017/09/14 Javascript
Angular5.0 子组件通过service传递值给父组件的方法
2018/07/13 Javascript
详解Angular模板引用变量及其作用域
2018/11/23 Javascript
简单谈谈Python中的闭包
2016/11/30 Python
简单谈谈python基本数据类型
2018/09/26 Python
python 实现分页显示从es中获取的数据方法
2018/12/26 Python
利用pandas合并多个excel的方法示例
2019/10/10 Python
详解opencv中画圆circle函数和椭圆ellipse函数
2019/12/27 Python
Python OrderedDict字典排序方法详解
2020/05/21 Python
HTML5和CSS3让网页设计提升到下一个高度
2009/08/14 HTML / CSS
CSS3制作轮播图的一种方法
2019/11/11 HTML / CSS
Gucci法国官方网站:意大利奢侈品牌
2018/07/25 全球购物
美国礼品卡交易网站:Cardpool
2018/08/27 全球购物
美国室内盆栽植物购买网站:Plants.com
2020/04/24 全球购物
公司周年庆典邀请函
2014/01/12 职场文书
教师现实表现材料
2014/02/14 职场文书
医学专业应届生的自我评价
2014/02/28 职场文书
李开复演讲稿
2014/05/24 职场文书
副检察长四风问题对照检查材料思想汇报
2014/10/07 职场文书
2015年社区中秋节活动总结
2015/03/23 职场文书
Win11怎么解除儿童账号限制?Win11解除微软儿童账号限制方法
2022/07/07 数码科技
HTML5页面打开微信小程序功能实现
2022/09/23 HTML / CSS