北航自动打卡

北航自动打卡脚本

脚本基于chrome和selenium,模拟浏览器点击

进行了简单模拟适配,原文出处. 项目用于学习交流,仅用于各项无异常时打卡,建议如实打卡。

功能列表:

  • 在校打卡、不在校打卡
  • 自定义定位
  • 检测登录是否成功和网页能否打开
  • 定时自动打卡*
  • 微信推送打卡结果**
  • 日志记录
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
import logging
from time import sleep
import time
import datetime
import requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

user = "******" # 你的统一认证账号
passwd = "******" # 你的统一认证密码json
position = ("******", "******") # 定位,(纬度, 经度)
SCKEY = "********" # 微信推送api,到http://sc.ftqq.com/ 免费申请,不需要请留空

set_time = [(18, 5)] # (小时,分钟), 如果多个时间可以写成[(h, m),(h, m)]的形式
max_attempt = 5 # 失败重复五次


def daka():
login_flag, browser = login()
if not login_flag:
return

browser.execute_script("window.navigator.geolocation.getCurrentPosition=function(success){" +
"var position = {\"coords\" : {\"latitude\": \"" + position[0] + "\",\"longitude\": \""
+ position[1] + "\"}};" +
"success(position);}")

location_button = browser.find_element_by_css_selector('div[name=area]>input')
location_button.click()
logger.info("成功输入经纬度")

# zgfxdq = browser.find_element_by_xpath("//div[@name='zgfxdq']/div/div[2]/span[1]")
# ActionChains(browser).move_to_element(zgfxdq).click(zgfxdq).perform()
# logger.info("成功输入未在低风险地区")

tiwen = browser.find_element_by_xpath("//div[@name='tw']/div/div[2]/span[1]")
ActionChains(browser).move_to_element(tiwen).click(tiwen).perform()
logger.info("成功输入体温")

sfzx = browser.find_element_by_xpath("//div[@name='sfzx']/div/div[2]/span[1]")
ActionChains(browser).move_to_element(sfzx).click(sfzx).perform()
logger.info("成功确定在校")

askforleave = browser.find_element_by_xpath("//div[@name='askforleave']/div/div[2]/span[1]")
ActionChains(browser).move_to_element(askforleave).click(askforleave).perform()
logger.info("是否请加外出")

sffxzs = browser.find_element_by_xpath("//div[@name='sffxzs']/div/div[2]/span[1]")
ActionChains(browser).move_to_element(sffxzs).click(sffxzs).perform()
logger.info("是否返校住宿")

# jcjgqr = browser.find_element_by_xpath("//div[@name='jcjgqr']/div/div[1]/span[1]")
# ActionChains(browser).move_to_element(jcjgqr).click(jcjgqr).perform()
# logger.info("属于哪种情况")
sfcyglq = browser.find_element_by_xpath("//div[@name='sfcyglq']/div/div[2]/span[1]")
ActionChains(browser).move_to_element(sfcyglq).click(sfcyglq).perform()
logger.info("是否处于观察期")

sfyzz = browser.find_element_by_xpath("//div[@name='sfyzz']/div/div[2]/span[1]")
ActionChains(browser).move_to_element(sfyzz).click(sfyzz).perform()
logger.info("是否发热乏力")

# sfjcbh = browser.find_element_by_xpath("//div[@name='sfjcbh']/div/div[2]/span[1]")
# ActionChains(browser).move_to_element(sfjcbh).click(sfjcbh).perform()
# logger.info("是否接触无症状感染")
#
# mjry = browser.find_element_by_xpath("//div[@name='mjry']/div/div[2]/span[1]")
# ActionChains(browser).move_to_element(mjry).click(mjry).perform()
# logger.info("是否接触密切接触人员")
#
# csmjry = browser.find_element_by_xpath("//div[@name='csmjry']/div/div[2]/span[1]")
# ActionChains(browser).move_to_element(csmjry).click(csmjry).perform()
# logger.info("近14日内本人/共同居住者")
#
#
#
# szsqsfybl = browser.find_element_by_xpath("//div[@name='szsqsfybl']/div/div[2]/span[1]")
# ActionChains(browser).move_to_element(szsqsfybl).click(szsqsfybl).perform()
# logger.info("所在社区是否有确诊病例")
#
# sfcxzysx = browser.find_element_by_xpath("//div[@name='sfcxzysx']/div/div[2]/span[1]")
# ActionChains(browser).move_to_element(sfcxzysx).click(sfcxzysx).perform()
# logger.info("是否有任何与疫情相关的, 值得注意的情况")



# 点击提交
submit_button = browser.find_element_by_css_selector(
'body > div.item-buydate.form-detail2 > div > div > section > div.list-box > div > a')
ActionChains(browser).move_to_element(submit_button).click(submit_button).perform()

browser.implicitly_wait(3)
while True:
try:
confirm_button = browser.find_element_by_css_selector(
'#wapcf > div > div.wapcf-btn-box > div.wapcf-btn.wapcf-btn-ok')
result = '提交成功'
break
except:
try:
confirm_button = browser.find_element_by_css_selector('#wapat > div > div.wapat-btn-box > div')
reason = browser.find_element_by_css_selector('#wapat > div > div.wapat-title').text
result = f'打卡失败,原因:{reason}'
break
except:
time.sleep(1)

ActionChains(browser).move_to_element(confirm_button).click(confirm_button).perform()

logger.info(result)

datee = datetime.date.today()

send_message(f"{datee} {result}")
sleep(50)
browser.quit()
logger.info("流程结束")


def login():
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--no-sandbox')
browser = webdriver.Chrome(chrome_options=chrome_options)

try:
url = "https://app.buaa.edu.cn/uc/wap/login"
browser.get(url)

# 账号密码
user_name_input = browser.find_element_by_css_selector(
'#app > div.content > div:nth-child(1) > input[type=text]')
user_name_input.send_keys(user)
user_pwd_input = browser.find_element_by_css_selector(
'#app > div.content > div:nth-child(2) > input[type=password]')
user_pwd_input.send_keys(passwd)

except:
logger.info("打开打卡网页失败,请确认网络")
send_message("打开打卡网页失败,请确认网络")
return False, None

logger.info("成功打开打卡网页")

# 点击登录按钮
login_button = browser.find_element_by_css_selector('#app > div.btn')
ActionChains(browser).move_to_element(login_button).click(login_button).perform()
browser.implicitly_wait(2)

# 跳转并点击获取位置按钮
# 这样写是为了等待跳转页面加载出来
fail_cnt = 0
while True:
location_button = browser.find_elements_by_css_selector('div[name=area]>input')
if len(location_button) > 0:
logger.info("登录成功")
return True, browser
else:
# 出现密码错误提示框
if len(browser.find_elements_by_css_selector('div.wapat-btn-box')) > 0:
send_message("打卡失败,用户名密码错误,程序已退出,请检查")
logger.info("打卡失败,用户名密码错误,请检查")
exit(0)

# 若只是反应慢,重试
if fail_cnt >= max_attempt:
send_message("登录超时超过最大尝试次数,请检查网络或打卡系统已崩溃")
logger.info("登录超时超过最大尝试次数")
return False, None
time.sleep(10)
browser.get("https://app.buaa.edu.cn/site/ncov/xisudailyup")
logger.info("登录超时,正在重试")
fail_cnt += 1


def main(): # 0:05进行打卡
logger.info("正在进行验证...")
flag, browser = login() # 测试能否进入网页以及用户名密码是否正确
browser.quit()
if not flag:
exit(0)
while True:
while True:
# time_up = True # debug
time_up = False
now = datetime.datetime.now()
for hour, minute in set_time:
if now.hour == hour and now.minute == minute:
time_up = True
if time_up:
break
logger.debug(f"时间未到,当前时间 {now}")
sleep(20)
logger.info("时间已到,正在打卡")
daka()


def send_message(msg):
if SCKEY == "":
return
payload = {'text': msg}
requests.get(f"https://sc.ftqq.com/{SCKEY}.send", params=payload)


if __name__ == "__main__":
log_file = "log.log"
formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
logger = logging.getLogger("main")
fh = logging.FileHandler(log_file, mode='w')
fh.setFormatter(formatter)
ch = logging.StreamHandler()
ch.setFormatter(formatter)
logger.addHandler(fh)
logger.addHandler(ch)
logger.setLevel(logging.INFO)
main()

北航自动打卡
https://zhangfuli.github.io/2021/01/10/北航自动打卡/
作者
张富利
发布于
2021年1月10日
许可协议