mirror of
https://github.com/KenanZhu/AutoLibrary.git
synced 2026-06-17 23:13:03 +08:00
fix(pages): 移除裸 except Exception 改用精确异常类型并加固元素操作防护
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -149,9 +149,6 @@ class AutoLib(MsgBase):
|
|||||||
except WebDriverException as e:
|
except WebDriverException as e:
|
||||||
self._showTrace(f"浏览器驱动初始化失败: {e}", self.TraceLevel.ERROR)
|
self._showTrace(f"浏览器驱动初始化失败: {e}", self.TraceLevel.ERROR)
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
|
||||||
self._showTrace(f"浏览器驱动初始化失败: {e}", self.TraceLevel.ERROR)
|
|
||||||
return False
|
|
||||||
self._showTrace(f"浏览器驱动已初始化, 类型: {self.__driver_type}, 路径: {self.__driver_path}")
|
self._showTrace(f"浏览器驱动已初始化, 类型: {self.__driver_type}, 路径: {self.__driver_path}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
+15
-23
@@ -85,9 +85,7 @@ class LoginPage:
|
|||||||
EC.presence_of_element_located(self.CAPTCHA_IMG)
|
EC.presence_of_element_located(self.CAPTCHA_IMG)
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except (NoSuchElementException, TimeoutException):
|
except TimeoutException:
|
||||||
return False
|
|
||||||
except Exception:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def fillCredentials(
|
def fillCredentials(
|
||||||
@@ -104,17 +102,21 @@ class LoginPage:
|
|||||||
el.clear()
|
el.clear()
|
||||||
el.send_keys(password)
|
el.send_keys(password)
|
||||||
return True
|
return True
|
||||||
except (NoSuchElementException, TimeoutException):
|
except (NoSuchElementException, ElementNotInteractableException):
|
||||||
return False
|
|
||||||
except Exception:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def getCaptchaImageSrc(
|
def getCaptchaImageSrc(
|
||||||
self,
|
self,
|
||||||
) -> str:
|
) -> str | None:
|
||||||
|
|
||||||
captcha_el = self._driver.find_element(*self.CAPTCHA_IMG)
|
# return 'None' if captcha image element is not found.
|
||||||
return captcha_el.get_attribute("src")
|
# But the 'get_attribute("src")' also return 'None' if there's no attribute with
|
||||||
|
# that name, which is not what we want.
|
||||||
|
try:
|
||||||
|
captcha_el = self._driver.find_element(*self.CAPTCHA_IMG)
|
||||||
|
return captcha_el.get_attribute("src")
|
||||||
|
except NoSuchElementException:
|
||||||
|
return None
|
||||||
|
|
||||||
def refreshCaptcha(
|
def refreshCaptcha(
|
||||||
self,
|
self,
|
||||||
@@ -123,10 +125,7 @@ class LoginPage:
|
|||||||
try:
|
try:
|
||||||
self._driver.find_element(*self.CAPTCHA_IMG).click()
|
self._driver.find_element(*self.CAPTCHA_IMG).click()
|
||||||
return True
|
return True
|
||||||
except (NoSuchElementException, TimeoutException,
|
except (NoSuchElementException, ElementNotInteractableException):
|
||||||
ElementNotInteractableException):
|
|
||||||
return False
|
|
||||||
except Exception:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def fillCaptcha(
|
def fillCaptcha(
|
||||||
@@ -139,9 +138,7 @@ class LoginPage:
|
|||||||
el.clear()
|
el.clear()
|
||||||
el.send_keys(captcha_text)
|
el.send_keys(captcha_text)
|
||||||
return True
|
return True
|
||||||
except (NoSuchElementException, TimeoutException):
|
except (NoSuchElementException, ElementNotInteractableException):
|
||||||
return False
|
|
||||||
except Exception:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def clickLogin(
|
def clickLogin(
|
||||||
@@ -151,10 +148,7 @@ class LoginPage:
|
|||||||
try:
|
try:
|
||||||
self._driver.find_element(*self.LOGIN_BUTTON).click()
|
self._driver.find_element(*self.LOGIN_BUTTON).click()
|
||||||
return True
|
return True
|
||||||
except (NoSuchElementException, TimeoutException,
|
except (NoSuchElementException, ElementNotInteractableException):
|
||||||
ElementNotInteractableException):
|
|
||||||
return False
|
|
||||||
except Exception:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def waitLoginSuccess(
|
def waitLoginSuccess(
|
||||||
@@ -172,9 +166,7 @@ class LoginPage:
|
|||||||
EC.presence_of_element_located(self.SUCCESS_INDICATOR_CONTENT)
|
EC.presence_of_element_located(self.SUCCESS_INDICATOR_CONTENT)
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except (NoSuchElementException, TimeoutException):
|
except TimeoutException:
|
||||||
return False
|
|
||||||
except Exception:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def stopPageLoad(
|
def stopPageLoad(
|
||||||
|
|||||||
+40
-29
@@ -14,8 +14,10 @@ from selenium.webdriver.support.ui import WebDriverWait
|
|||||||
from selenium.webdriver.support import expected_conditions as EC
|
from selenium.webdriver.support import expected_conditions as EC
|
||||||
from selenium.webdriver.remote.webdriver import WebDriver
|
from selenium.webdriver.remote.webdriver import WebDriver
|
||||||
from selenium.common.exceptions import (
|
from selenium.common.exceptions import (
|
||||||
|
ElementNotInteractableException,
|
||||||
NoSuchElementException,
|
NoSuchElementException,
|
||||||
TimeoutException,
|
TimeoutException,
|
||||||
|
WebDriverException,
|
||||||
)
|
)
|
||||||
|
|
||||||
from pages.ReserveView import ReserveView
|
from pages.ReserveView import ReserveView
|
||||||
@@ -38,6 +40,15 @@ class MainShell:
|
|||||||
|
|
||||||
self._driver = driver
|
self._driver = driver
|
||||||
|
|
||||||
|
def _clickTab(
|
||||||
|
self,
|
||||||
|
locator: tuple,
|
||||||
|
) -> None:
|
||||||
|
|
||||||
|
WebDriverWait(self._driver, 2).until(
|
||||||
|
EC.element_to_be_clickable(locator)
|
||||||
|
).click()
|
||||||
|
|
||||||
def gotoReserveView(
|
def gotoReserveView(
|
||||||
self,
|
self,
|
||||||
) -> ReserveView:
|
) -> ReserveView:
|
||||||
@@ -65,9 +76,7 @@ class MainShell:
|
|||||||
try:
|
try:
|
||||||
self._driver.find_element(*self.TAB_LOGOUT).click()
|
self._driver.find_element(*self.TAB_LOGOUT).click()
|
||||||
return True
|
return True
|
||||||
except NoSuchElementException:
|
except (NoSuchElementException, ElementNotInteractableException):
|
||||||
return False
|
|
||||||
except Exception:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def waitCheckinButton(
|
def waitCheckinButton(
|
||||||
@@ -81,8 +90,6 @@ class MainShell:
|
|||||||
return True
|
return True
|
||||||
except TimeoutException:
|
except TimeoutException:
|
||||||
return False
|
return False
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def waitExtendButton(
|
def waitExtendButton(
|
||||||
self,
|
self,
|
||||||
@@ -95,40 +102,50 @@ class MainShell:
|
|||||||
return True
|
return True
|
||||||
except TimeoutException:
|
except TimeoutException:
|
||||||
return False
|
return False
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def isCheckinButtonDisabled(
|
def isCheckinButtonDisabled(
|
||||||
self,
|
self,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
|
|
||||||
btn = self._driver.find_element(*self.BTN_CHECKIN)
|
try:
|
||||||
return "disabled" in btn.get_attribute("class")
|
btn = self._driver.find_element(*self.BTN_CHECKIN)
|
||||||
|
return "disabled" in btn.get_attribute("class")
|
||||||
|
except NoSuchElementException:
|
||||||
|
return True
|
||||||
|
|
||||||
def isExtendButtonDisabled(
|
def isExtendButtonDisabled(
|
||||||
self,
|
self,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
|
|
||||||
btn = self._driver.find_element(*self.BTN_EXTEND)
|
try:
|
||||||
return "disabled" in btn.get_attribute("class")
|
btn = self._driver.find_element(*self.BTN_EXTEND)
|
||||||
|
return "disabled" in btn.get_attribute("class")
|
||||||
|
except NoSuchElementException:
|
||||||
|
return True
|
||||||
|
|
||||||
def clickCheckinButton(
|
def clickCheckinButton(
|
||||||
self,
|
self,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
btn = WebDriverWait(self._driver, 2).until(
|
try:
|
||||||
EC.element_to_be_clickable(self.BTN_CHECKIN)
|
btn = WebDriverWait(self._driver, 2).until(
|
||||||
)
|
EC.element_to_be_clickable(self.BTN_CHECKIN)
|
||||||
btn.click()
|
)
|
||||||
|
btn.click()
|
||||||
|
except (TimeoutException, ElementNotInteractableException):
|
||||||
|
return
|
||||||
|
|
||||||
def clickExtendButton(
|
def clickExtendButton(
|
||||||
self,
|
self,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
btn = WebDriverWait(self._driver, 2).until(
|
try:
|
||||||
EC.element_to_be_clickable(self.BTN_EXTEND)
|
btn = WebDriverWait(self._driver, 2).until(
|
||||||
)
|
EC.element_to_be_clickable(self.BTN_EXTEND)
|
||||||
btn.click()
|
)
|
||||||
|
btn.click()
|
||||||
|
except (TimeoutException, ElementNotInteractableException):
|
||||||
|
return
|
||||||
|
|
||||||
def enableCheckinButtonByJS(
|
def enableCheckinButtonByJS(
|
||||||
self,
|
self,
|
||||||
@@ -154,13 +171,7 @@ class MainShell:
|
|||||||
self,
|
self,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
self._driver.refresh()
|
try:
|
||||||
|
self._driver.refresh()
|
||||||
def _clickTab(
|
except (TimeoutException, WebDriverException):
|
||||||
self,
|
return
|
||||||
locator: tuple,
|
|
||||||
) -> None:
|
|
||||||
|
|
||||||
WebDriverWait(self._driver, 2).until(
|
|
||||||
EC.element_to_be_clickable(locator)
|
|
||||||
).click()
|
|
||||||
|
|||||||
@@ -44,8 +44,6 @@ class RecordsView:
|
|||||||
return self._driver.find_elements(*self.RECORDS_LIST)
|
return self._driver.find_elements(*self.RECORDS_LIST)
|
||||||
except TimeoutException:
|
except TimeoutException:
|
||||||
return None
|
return None
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def getRecordTimeElement(
|
def getRecordTimeElement(
|
||||||
self,
|
self,
|
||||||
@@ -71,8 +69,6 @@ class RecordsView:
|
|||||||
)
|
)
|
||||||
except TimeoutException:
|
except TimeoutException:
|
||||||
return False
|
return False
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
try:
|
try:
|
||||||
more_btn = self._driver.find_element(*self.MORE_BTN)
|
more_btn = self._driver.find_element(*self.MORE_BTN)
|
||||||
if more_btn.is_displayed() and more_btn.is_enabled():
|
if more_btn.is_displayed() and more_btn.is_enabled():
|
||||||
@@ -82,8 +78,6 @@ class RecordsView:
|
|||||||
return False
|
return False
|
||||||
except (NoSuchElementException, StaleElementReferenceException):
|
except (NoSuchElementException, StaleElementReferenceException):
|
||||||
return False
|
return False
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def getRecordText(
|
def getRecordText(
|
||||||
self,
|
self,
|
||||||
|
|||||||
+48
-55
@@ -53,6 +53,50 @@ class ReserveView:
|
|||||||
|
|
||||||
self._driver = driver
|
self._driver = driver
|
||||||
|
|
||||||
|
def _clickOptionByJS(
|
||||||
|
self,
|
||||||
|
trigger_id: str,
|
||||||
|
option_css: str,
|
||||||
|
) -> bool:
|
||||||
|
|
||||||
|
script = f"""
|
||||||
|
try {{
|
||||||
|
var trigger = document.getElementById('{trigger_id}');
|
||||||
|
if (trigger) {{
|
||||||
|
trigger.click();
|
||||||
|
var option = document.querySelector("{option_css}");
|
||||||
|
if (option) {{
|
||||||
|
option.click();
|
||||||
|
return true;
|
||||||
|
}}
|
||||||
|
return false;
|
||||||
|
}}
|
||||||
|
return false;
|
||||||
|
}} catch (e) {{
|
||||||
|
return false;
|
||||||
|
}}
|
||||||
|
"""
|
||||||
|
result = self._driver.execute_script(script)
|
||||||
|
time.sleep(0.1)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _clickOption(
|
||||||
|
self,
|
||||||
|
trigger: tuple,
|
||||||
|
option: tuple,
|
||||||
|
) -> bool:
|
||||||
|
|
||||||
|
try:
|
||||||
|
WebDriverWait(self._driver, 2).until(
|
||||||
|
EC.element_to_be_clickable(trigger)
|
||||||
|
).click()
|
||||||
|
WebDriverWait(self._driver, 2).until(
|
||||||
|
EC.element_to_be_clickable(option)
|
||||||
|
).click()
|
||||||
|
return True
|
||||||
|
except (TimeoutException, ElementNotInteractableException):
|
||||||
|
return False
|
||||||
|
|
||||||
def selectDate(
|
def selectDate(
|
||||||
self,
|
self,
|
||||||
date_str: str,
|
date_str: str,
|
||||||
@@ -109,21 +153,15 @@ class ReserveView:
|
|||||||
).click()
|
).click()
|
||||||
except (TimeoutException, ElementNotInteractableException):
|
except (TimeoutException, ElementNotInteractableException):
|
||||||
return None
|
return None
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
try:
|
try:
|
||||||
WebDriverWait(self._driver, 2).until(
|
WebDriverWait(self._driver, 2).until(
|
||||||
EC.element_to_be_clickable((By.ID, self.ROOM_BTN_FMT.format(room=room)))
|
EC.element_to_be_clickable((By.ID, self.ROOM_BTN_FMT.format(room=room)))
|
||||||
).click()
|
).click()
|
||||||
except (TimeoutException, ElementNotInteractableException):
|
except (TimeoutException, ElementNotInteractableException):
|
||||||
return None
|
return None
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
try:
|
try:
|
||||||
return SeatMapDialog(self._driver)
|
return SeatMapDialog(self._driver)
|
||||||
except (TimeoutException):
|
except TimeoutException:
|
||||||
return None
|
|
||||||
except Exception:
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def submitReserve(
|
def submitReserve(
|
||||||
@@ -137,57 +175,12 @@ class ReserveView:
|
|||||||
return True
|
return True
|
||||||
except (TimeoutException, ElementNotInteractableException):
|
except (TimeoutException, ElementNotInteractableException):
|
||||||
return False
|
return False
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def refresh(
|
def refresh(
|
||||||
self,
|
self,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
self._driver.refresh()
|
|
||||||
|
|
||||||
def _clickOptionByJS(
|
|
||||||
self,
|
|
||||||
trigger_id: str,
|
|
||||||
option_css: str,
|
|
||||||
) -> bool:
|
|
||||||
|
|
||||||
script = f"""
|
|
||||||
try {{
|
|
||||||
var trigger = document.getElementById('{trigger_id}');
|
|
||||||
if (trigger) {{
|
|
||||||
trigger.click();
|
|
||||||
var option = document.querySelector("{option_css}");
|
|
||||||
if (option) {{
|
|
||||||
option.click();
|
|
||||||
return true;
|
|
||||||
}}
|
|
||||||
return false;
|
|
||||||
}}
|
|
||||||
return false;
|
|
||||||
}} catch (e) {{
|
|
||||||
return false;
|
|
||||||
}}
|
|
||||||
"""
|
|
||||||
result = self._driver.execute_script(script)
|
|
||||||
time.sleep(0.1)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _clickOption(
|
|
||||||
self,
|
|
||||||
trigger: tuple,
|
|
||||||
option: tuple,
|
|
||||||
) -> bool:
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
WebDriverWait(self._driver, 2).until(
|
self._driver.refresh()
|
||||||
EC.element_to_be_clickable(trigger)
|
except TimeoutException:
|
||||||
).click()
|
return
|
||||||
WebDriverWait(self._driver, 2).until(
|
|
||||||
EC.element_to_be_clickable(option)
|
|
||||||
).click()
|
|
||||||
return True
|
|
||||||
except (TimeoutException, ElementNotInteractableException):
|
|
||||||
return False
|
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
|
|||||||
@@ -45,9 +45,8 @@ class CheckinResultDialog(Dialog):
|
|||||||
self._waitPresence(self.RESULT_MSG)
|
self._waitPresence(self.RESULT_MSG)
|
||||||
el = self._find(*self.RESULT_MSG)
|
el = self._find(*self.RESULT_MSG)
|
||||||
return el.text
|
return el.text
|
||||||
except (TimeoutException, NoSuchElementException, StaleElementReferenceException):
|
except (TimeoutException, NoSuchElementException,
|
||||||
return ""
|
StaleElementReferenceException):
|
||||||
except Exception:
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def getDetails(
|
def getDetails(
|
||||||
@@ -59,8 +58,6 @@ class CheckinResultDialog(Dialog):
|
|||||||
return [el.text for el in elements if el.text.strip()]
|
return [el.text for el in elements if el.text.strip()]
|
||||||
except (NoSuchElementException, StaleElementReferenceException):
|
except (NoSuchElementException, StaleElementReferenceException):
|
||||||
return []
|
return []
|
||||||
except Exception:
|
|
||||||
return []
|
|
||||||
|
|
||||||
def clickOk(
|
def clickOk(
|
||||||
self,
|
self,
|
||||||
@@ -69,7 +66,5 @@ class CheckinResultDialog(Dialog):
|
|||||||
try:
|
try:
|
||||||
self._waitClickable(self.OK_BTN).click()
|
self._waitClickable(self.OK_BTN).click()
|
||||||
return True
|
return True
|
||||||
except (NoSuchElementException, TimeoutException, ElementNotInteractableException):
|
except (TimeoutException, ElementNotInteractableException):
|
||||||
return False
|
|
||||||
except Exception:
|
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ See the LICENSE file for details.
|
|||||||
from selenium.common.exceptions import (
|
from selenium.common.exceptions import (
|
||||||
ElementNotInteractableException,
|
ElementNotInteractableException,
|
||||||
NoSuchElementException,
|
NoSuchElementException,
|
||||||
|
StaleElementReferenceException,
|
||||||
TimeoutException,
|
TimeoutException,
|
||||||
)
|
)
|
||||||
from selenium.webdriver.common.by import By
|
from selenium.webdriver.common.by import By
|
||||||
@@ -50,9 +51,7 @@ class RenewDialog(Dialog):
|
|||||||
self._waitVisible(self.ROOT)
|
self._waitVisible(self.ROOT)
|
||||||
self._waitPresence(self.MESSAGE_HEAD)
|
self._waitPresence(self.MESSAGE_HEAD)
|
||||||
self._waitPresence(self.RESULT_MSG)
|
self._waitPresence(self.RESULT_MSG)
|
||||||
except (NoSuchElementException, TimeoutException):
|
except TimeoutException:
|
||||||
return False
|
|
||||||
except Exception:
|
|
||||||
return False
|
return False
|
||||||
head_msg = self._find(*self.MESSAGE_HEAD).text.strip()
|
head_msg = self._find(*self.MESSAGE_HEAD).text.strip()
|
||||||
if "警告" in head_msg:
|
if "警告" in head_msg:
|
||||||
@@ -60,9 +59,7 @@ class RenewDialog(Dialog):
|
|||||||
try:
|
try:
|
||||||
self._waitAllPresence(self.TIME_OPTS)
|
self._waitAllPresence(self.TIME_OPTS)
|
||||||
self._waitPresence(self.OK_BTN)
|
self._waitPresence(self.OK_BTN)
|
||||||
except (NoSuchElementException, TimeoutException):
|
except TimeoutException:
|
||||||
return False
|
|
||||||
except Exception:
|
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -70,13 +67,19 @@ class RenewDialog(Dialog):
|
|||||||
self,
|
self,
|
||||||
) -> str:
|
) -> str:
|
||||||
|
|
||||||
return self._find(*self.MESSAGE_HEAD).text.strip()
|
try:
|
||||||
|
return self._find(*self.MESSAGE_HEAD).text.strip()
|
||||||
|
except (NoSuchElementException, StaleElementReferenceException):
|
||||||
|
return ""
|
||||||
|
|
||||||
def getResultMessage(
|
def getResultMessage(
|
||||||
self,
|
self,
|
||||||
) -> str:
|
) -> str:
|
||||||
|
|
||||||
return self._find(*self.RESULT_MSG).text.strip()
|
try:
|
||||||
|
return self._find(*self.RESULT_MSG).text.strip()
|
||||||
|
except (NoSuchElementException, StaleElementReferenceException):
|
||||||
|
return ""
|
||||||
|
|
||||||
def getTimeOptions(
|
def getTimeOptions(
|
||||||
self,
|
self,
|
||||||
@@ -101,7 +104,10 @@ class RenewDialog(Dialog):
|
|||||||
prefer_earlier,
|
prefer_earlier,
|
||||||
)
|
)
|
||||||
if result.selected_index >= 0:
|
if result.selected_index >= 0:
|
||||||
all_time_opts[result.selected_index].click()
|
try:
|
||||||
|
all_time_opts[result.selected_index].click()
|
||||||
|
except (ElementNotInteractableException, StaleElementReferenceException):
|
||||||
|
return TimeSelectionResult(free_times=result.free_times)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def getOkButton(
|
def getOkButton(
|
||||||
@@ -117,8 +123,5 @@ class RenewDialog(Dialog):
|
|||||||
try:
|
try:
|
||||||
self._find(*self.OK_BTN).click()
|
self._find(*self.OK_BTN).click()
|
||||||
return True
|
return True
|
||||||
except (NoSuchElementException, TimeoutException,
|
except (NoSuchElementException, ElementNotInteractableException):
|
||||||
ElementNotInteractableException):
|
|
||||||
return False
|
|
||||||
except Exception:
|
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -45,8 +45,6 @@ class ReserveResultDialog(Dialog):
|
|||||||
return self._find(*self._titleLocator()).text
|
return self._find(*self._titleLocator()).text
|
||||||
except (NoSuchElementException, StaleElementReferenceException):
|
except (NoSuchElementException, StaleElementReferenceException):
|
||||||
return ""
|
return ""
|
||||||
except Exception:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def isSuccess(
|
def isSuccess(
|
||||||
self,
|
self,
|
||||||
@@ -77,5 +75,3 @@ class ReserveResultDialog(Dialog):
|
|||||||
return [el.text for el in elements if el.text.strip()]
|
return [el.text for el in elements if el.text.strip()]
|
||||||
except (NoSuchElementException, StaleElementReferenceException):
|
except (NoSuchElementException, StaleElementReferenceException):
|
||||||
return []
|
return []
|
||||||
except Exception:
|
|
||||||
return []
|
|
||||||
|
|||||||
@@ -43,9 +43,7 @@ class SeatMapDialog(Dialog):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
self._waitAllPresence(self.SEAT_ITEMS)
|
self._waitAllPresence(self.SEAT_ITEMS)
|
||||||
except (NoSuchElementException, TimeoutException):
|
except TimeoutException:
|
||||||
return None
|
|
||||||
except Exception:
|
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
seat_el = self._find(By.ID, f"seat_{int(seat_id):03d}")
|
seat_el = self._find(By.ID, f"seat_{int(seat_id):03d}")
|
||||||
@@ -58,8 +56,6 @@ class SeatMapDialog(Dialog):
|
|||||||
except (NoSuchElementException, ValueError, TimeoutException,
|
except (NoSuchElementException, ValueError, TimeoutException,
|
||||||
ElementNotInteractableException, StaleElementReferenceException):
|
ElementNotInteractableException, StaleElementReferenceException):
|
||||||
pass
|
pass
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
try:
|
try:
|
||||||
all_seats = self._findAll(*self.SEAT_ITEMS)
|
all_seats = self._findAll(*self.SEAT_ITEMS)
|
||||||
seat_id_upper = seat_id.lstrip('0').upper()
|
seat_id_upper = seat_id.lstrip('0').upper()
|
||||||
@@ -76,5 +72,3 @@ class SeatMapDialog(Dialog):
|
|||||||
except (NoSuchElementException, TimeoutException,
|
except (NoSuchElementException, TimeoutException,
|
||||||
ElementNotInteractableException, StaleElementReferenceException):
|
ElementNotInteractableException, StaleElementReferenceException):
|
||||||
return None
|
return None
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ import logging
|
|||||||
from typing import TYPE_CHECKING, Callable, Optional
|
from typing import TYPE_CHECKING, Callable, Optional
|
||||||
|
|
||||||
from selenium.common.exceptions import (
|
from selenium.common.exceptions import (
|
||||||
NoSuchElementException,
|
ElementNotInteractableException,
|
||||||
|
StaleElementReferenceException,
|
||||||
TimeoutException,
|
TimeoutException,
|
||||||
)
|
)
|
||||||
from selenium.webdriver.common.by import By
|
from selenium.webdriver.common.by import By
|
||||||
@@ -106,9 +107,7 @@ class TimeSelectDialog(Dialog):
|
|||||||
self._waitAllPresence(
|
self._waitAllPresence(
|
||||||
(By.CSS_SELECTOR, f"#{time_id} ul li a")
|
(By.CSS_SELECTOR, f"#{time_id} ul li a")
|
||||||
)
|
)
|
||||||
except (NoSuchElementException, TimeoutException):
|
except TimeoutException:
|
||||||
return []
|
|
||||||
except Exception:
|
|
||||||
return []
|
return []
|
||||||
return self._findAll(
|
return self._findAll(
|
||||||
By.CSS_SELECTOR,
|
By.CSS_SELECTOR,
|
||||||
@@ -133,7 +132,10 @@ class TimeSelectDialog(Dialog):
|
|||||||
prefer_earlier,
|
prefer_earlier,
|
||||||
)
|
)
|
||||||
if result.selected_index >= 0:
|
if result.selected_index >= 0:
|
||||||
all_time_opts[result.selected_index].click()
|
try:
|
||||||
|
all_time_opts[result.selected_index].click()
|
||||||
|
except (ElementNotInteractableException, StaleElementReferenceException):
|
||||||
|
return TimeSelectionResult(free_times=result.free_times)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def selectTimeRange(
|
def selectTimeRange(
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ See the LICENSE file for details.
|
|||||||
import queue
|
import queue
|
||||||
|
|
||||||
from selenium.common.exceptions import (
|
from selenium.common.exceptions import (
|
||||||
|
ElementNotInteractableException,
|
||||||
NoSuchElementException,
|
NoSuchElementException,
|
||||||
TimeoutException,
|
TimeoutException,
|
||||||
)
|
)
|
||||||
@@ -83,9 +84,6 @@ class CheckinFlow(MsgBase):
|
|||||||
dialog.clickOk()
|
dialog.clickOk()
|
||||||
self._showTrace(f"用户 {username} 签到失败 !", self.TraceLevel.ERROR)
|
self._showTrace(f"用户 {username} 签到失败 !", self.TraceLevel.ERROR)
|
||||||
return False
|
return False
|
||||||
except (NoSuchElementException, TimeoutException):
|
except (TimeoutException, NoSuchElementException, ElementNotInteractableException):
|
||||||
self._showTrace("签到时发生未知错误 !", self.TraceLevel.ERROR)
|
|
||||||
return False
|
|
||||||
except Exception:
|
|
||||||
self._showTrace("签到时发生未知错误 !", self.TraceLevel.ERROR)
|
self._showTrace("签到时发生未知错误 !", self.TraceLevel.ERROR)
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -39,6 +39,28 @@ class RenewFlow(MsgBase):
|
|||||||
self._driver: WebDriver = driver
|
self._driver: WebDriver = driver
|
||||||
self._shell: MainShell = shell
|
self._shell: MainShell = shell
|
||||||
|
|
||||||
|
def _validateRenewTime(
|
||||||
|
self,
|
||||||
|
end_time: str,
|
||||||
|
target_renew_mins: int,
|
||||||
|
) -> bool:
|
||||||
|
|
||||||
|
if target_renew_mins > self.LIBRARY_CLOSE_MINS:
|
||||||
|
actual_renew_duration = self.LIBRARY_CLOSE_MINS - timeStrToMins(end_time)
|
||||||
|
if actual_renew_duration <= 0:
|
||||||
|
self._showTrace(
|
||||||
|
f"当前结束时间 {end_time} 已接近闭馆时间,无法续约 !", self.TraceLevel.ERROR
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
self._showTrace(
|
||||||
|
f"续约时间已调整至闭馆时间 "
|
||||||
|
f"{minsToTimeStr(self.LIBRARY_CLOSE_MINS)},"
|
||||||
|
f"实际续约时长为 "
|
||||||
|
f"{actual_renew_duration // 60} 小时 "
|
||||||
|
f"{actual_renew_duration % 60} 分钟"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
def execute(
|
def execute(
|
||||||
self,
|
self,
|
||||||
username: str,
|
username: str,
|
||||||
@@ -106,37 +128,7 @@ class RenewFlow(MsgBase):
|
|||||||
self._showTrace(f"当前可供续约的时间有: {result.free_times}")
|
self._showTrace(f"当前可供续约的时间有: {result.free_times}")
|
||||||
self._shell.refresh()
|
self._shell.refresh()
|
||||||
return False
|
return False
|
||||||
except (NoSuchElementException, TimeoutException) as e:
|
except (NoSuchElementException, TimeoutException, ElementNotInteractableException) as e:
|
||||||
self._showTrace(f"用户 {username} 续约失败 ! : {e}", self.TraceLevel.ERROR)
|
self._showTrace(f"用户 {username} 续约失败 ! : {e}", self.TraceLevel.ERROR)
|
||||||
self._shell.refresh()
|
self._shell.refresh()
|
||||||
return False
|
return False
|
||||||
except (ElementNotInteractableException) as e:
|
|
||||||
self._showTrace(f"用户 {username} 续约失败 ! : {e}", self.TraceLevel.ERROR)
|
|
||||||
self._shell.refresh()
|
|
||||||
return False
|
|
||||||
except Exception as e:
|
|
||||||
self._showTrace(f"用户 {username} 续约失败 ! : {e}", self.TraceLevel.ERROR)
|
|
||||||
self._shell.refresh()
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _validateRenewTime(
|
|
||||||
self,
|
|
||||||
end_time: str,
|
|
||||||
target_renew_mins: int,
|
|
||||||
) -> bool:
|
|
||||||
|
|
||||||
if target_renew_mins > self.LIBRARY_CLOSE_MINS:
|
|
||||||
actual_renew_duration = self.LIBRARY_CLOSE_MINS - timeStrToMins(end_time)
|
|
||||||
if actual_renew_duration <= 0:
|
|
||||||
self._showTrace(
|
|
||||||
f"当前结束时间 {end_time} 已接近闭馆时间,无法续约 !", self.TraceLevel.ERROR
|
|
||||||
)
|
|
||||||
return False
|
|
||||||
self._showTrace(
|
|
||||||
f"续约时间已调整至闭馆时间 "
|
|
||||||
f"{minsToTimeStr(self.LIBRARY_CLOSE_MINS)},"
|
|
||||||
f"实际续约时长为 "
|
|
||||||
f"{actual_renew_duration // 60} 小时 "
|
|
||||||
f"{actual_renew_duration % 60} 分钟"
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ from dataclasses import dataclass
|
|||||||
|
|
||||||
from selenium.common.exceptions import (
|
from selenium.common.exceptions import (
|
||||||
ElementNotInteractableException,
|
ElementNotInteractableException,
|
||||||
NoSuchElementException,
|
|
||||||
TimeoutException,
|
TimeoutException,
|
||||||
)
|
)
|
||||||
from selenium.webdriver.remote.webdriver import WebDriver
|
from selenium.webdriver.remote.webdriver import WebDriver
|
||||||
@@ -70,10 +69,7 @@ class ReserveFlow(MsgBase):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
view = self._shell.gotoReserveView()
|
view = self._shell.gotoReserveView()
|
||||||
except (NoSuchElementException, TimeoutException) as e:
|
except (TimeoutException, ElementNotInteractableException) as e:
|
||||||
self._showTrace(f"加载预约选座页面失败 ! : {e}", self.TraceLevel.ERROR)
|
|
||||||
return False
|
|
||||||
except Exception as e:
|
|
||||||
self._showTrace(f"加载预约选座页面失败 ! : {e}", self.TraceLevel.ERROR)
|
self._showTrace(f"加载预约选座页面失败 ! : {e}", self.TraceLevel.ERROR)
|
||||||
return False
|
return False
|
||||||
if not view.selectDate(ctx.date):
|
if not view.selectDate(ctx.date):
|
||||||
@@ -140,8 +136,6 @@ class ReserveFlow(MsgBase):
|
|||||||
self._showTrace("预约结果加载失败 !", self.TraceLevel.ERROR)
|
self._showTrace("预约结果加载失败 !", self.TraceLevel.ERROR)
|
||||||
except (TimeoutException, ElementNotInteractableException):
|
except (TimeoutException, ElementNotInteractableException):
|
||||||
self._showTrace("预约提交失败 !", self.TraceLevel.ERROR)
|
self._showTrace("预约提交失败 !", self.TraceLevel.ERROR)
|
||||||
except Exception:
|
|
||||||
self._showTrace("预约提交失败 !", self.TraceLevel.ERROR)
|
|
||||||
if not submit_reserve and have_hover_on_page:
|
if not submit_reserve and have_hover_on_page:
|
||||||
view.refresh()
|
view.refresh()
|
||||||
if reserve_success:
|
if reserve_success:
|
||||||
|
|||||||
Reference in New Issue
Block a user