北航自动打卡脚本
脚本基于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 loggingfrom time import sleepimport timeimport datetimeimport requestsfrom selenium import webdriverfrom selenium.webdriver.chrome.options import Optionsfrom selenium.webdriver.common.action_chains import ActionChainsfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECuser = "******" passwd = "******" position = ("******" , "******" ) SCKEY = "********" set_time = [(18 , 5 )] 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("成功输入经纬度" ) 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("是否返校住宿" ) 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("是否发热乏力" ) 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 (): logger.info("正在进行验证..." ) flag, browser = login() browser.quit() if not flag: exit(0 ) while True : while True : 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()