1:需求分析

由于新冠疫情的影响,学校图书馆和自习室必须在监管之下运行,每日提供的坐席和开放时间受限。大部分自习室被关闭,导致坐席需求很大,而供应很少。新规要求,图书馆和自习室的坐席必须在学校官网上预定,而且预定时间是周日到周四早上八点,仅能预定后一天的位置。

在考试周,座位非常难抢到,因此萌发了通过程序抢座的念头。

目前需求是,程序在周天到周日的早上八点启动,并打开抢座页面,抢座后关闭程序。抢座成功后,学校会自动发送抢座成功的邮件。

2:软硬件应用

服务器:树莓派4B+、Linux系统

语言:Python

依赖库:Selenium,date

Linux工具:crontab

3:抢座程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from time import sleep
import datetime

#点击buchen按钮
def clickbucheng(driver):
inputs = driver.find_elements_by_tag_name('input')
for input in inputs:
if input.get_attribute('value') == 'buchen':
ActionChains(driver).click(input).perform()
# writetohtml(driver,r"C:\Users\97532\OneDrive\程序仓库\getPlatzinBibliothek\1.html")
window = driver.window_handles[1]
driver.switch_to.window(window)
driver.find_elements_by_css_selector('#bs_form_main > div > div.bs_etvg > div > label > div.bs_form_uni.bs_right.padding0 > input')[0].click()
print(datetime.datetime.now().strftime('%Y.%m.%d-%H:%M:%S'),": start buchen")
return 1
return 0

#发送表格信息
def sendform(driver):
# writetohtml(driver,r'C:\Users\97532\OneDrive\程序仓库\getPlatzinBibliothek\2.html')
#sex:M/W
urinfo = {"sex":"M","vorname":"***","name":"***","strasse":"Hai***1","ort":"***","status":"S-RWTH","matnr":"***93","email":"im@xieqifei.com","telefon":"0049***4845"}
radios = driver.find_elements_by_name('sex')
vorname = driver.find_element_by_name('vorname')
name = driver.find_element_by_name('name')
strasse = driver.find_element_by_name('strasse')
ort = driver.find_element_by_name('ort')
status = Select(driver.find_element_by_name('statusorig'))
matnr = driver.find_element_by_name('matnr')
email = driver.find_element_by_name('email')
telefon = driver.find_element_by_name('telefon')
tnbed = driver.find_element_by_name('tnbed')
submit = driver.find_element_by_css_selector('#bs_foot > div.bs_form_row > div.bs_right > input')
for radio in radios:
if radio.get_attribute("value") == urinfo['sex']:
radio.click()
break
vorname.send_keys(urinfo['vorname'])
name.send_keys(urinfo['name'])
strasse.send_keys(urinfo['strasse'])
ort.send_keys(urinfo['ort'])
status.select_by_value(urinfo['status'])
matnr.send_keys(urinfo['matnr'])
email.send_keys(urinfo['email'])
telefon.send_keys(urinfo['telefon'])
tnbed.click()
telefon.click()
sleep(4)
# WebDriverWait(driver, 10).until(EC.element_to_be_clickable(By.XPATH,'//*[@id="bs_foot"]/div[3]/div[2]/input'))
submit.click()
print(datetime.datetime.now().strftime('%Y.%m.%d-%H:%M:%S'),": send MsgForm")
return 1

#确认预定
def confirm(driver):
confirm = driver.find_element_by_css_selector('#bs_foot > div.bs_form_row > div.bs_right > input')
confirm.click()
print(datetime.datetime.now().strftime('%Y.%m.%d-%H:%M:%S'),": confirm,buchen success!")

#可发送用户名密码抢座
def sendpw(driver):
logininfo = {"pw_email":"im@xieqifei.com","password":"***"}
pw_email = driver.find_element_by_name('pw_email')
pw = driver.find_element_by_css_selector('#bs_pw_anm > div:nth-child(3) > div.bs_form_sp2 > input')
submit2 = driver.find_element_by_css_selector('#bs_pw_anm > div.bs_form_foot > div.bs_form_row > div.bs_right > input')
pw_email.send_keys(logininfo['pw_email'])
pw.send_keys(logininfo['password'])
# sleep(3)
submit2.submit()

"""
def writetohtml(driver,path):
f = open(path,'wb')
f.write(driver.page_source.encode("utf-8", "ignore"))
f.close()
"""

if __name__ == "__main__":
#path = "/home/pi/Programms/getPlatzinBibliothek/chromedriver"
option = webdriver.ChromeOptions()
option.add_argument('--headless')
driver = webdriver.Chrome(options=option)
print(datetime.datetime.now().strftime('%Y.%m.%d-%H:%M:%S'),": chrome start up")
# driver.get('file:///C:/Users/97532/Desktop/Anmeldung.html')
driver.get('https://buchung.hsz.rwth-aachen.de/angebote/aktueller_zeitraum/_Lernraumbuchung.html')
ok = clickbucheng(driver)
count = 0
while ok != 1 and count < 10:
sleep(1)
driver.refresh()
ok = clickbucheng(driver)
count = count + 1
else:
if ok == 1:
sendform(driver)
confirm(driver)
#driver.get_screenshot_as_file(r"/home/pi/Programms/tushuguan.jpg")
sleep(1)
print(datetime.datetime.now().strftime('%Y.%m.%d-%H:%M:%S'),": chrome shutdown")
driver.quit()

使用Selenium驱动chrome浏览器,实行web自动化,完成抢座功能。

4:定时任务

在树莓派上,利用Linux定时工具crontab,指定程序在每周天到周四上午八点运行。

创建shell脚本,bibplatz.sh

1
2
3
#!/bin/bash
cd /home/pi/Programms/getPlatzinBibliothek
python3 -u getplatz.py > result.log 2>&1

添加任务

1
crontab -e

在vim编辑器中添加任务

1
0 8 * * 0-4 /home/pi/bibplatz.sh &

crontab的格式为:* * * * * command

五个*分别代表,分钟,小时,天,月,周

查看任务

1
crontab -l

5:参考资料

Linux定时任务Crontab命令详解

Linux后台运行Python程序的几种方法讲解

linux下后台运行python程序并输出到日志文件中

评论