Selenium循环代码问题:元素未找到致重复流程中断求助
Selenium重复执行时元素定位失败问题解决
我是Python新手,这是我的第一个项目。我的Selenium脚本首次测试时能正常定位元素,在Check_Appointment函数中设置了逻辑:如果检测到无预约提示文本,就返回主页重启流程;但重复执行时出现以下错误:
error encountered: Message: Element {#mat-select-value-1} was not present after 7 seconds!
我希望浏览器能持续重复步骤直到元素内容发生变化,以下是完整代码:
from time import sleep from playsound import playsound def click_new_booking(sb): sleep(5) # Search For Application Button sb.highlight_click('/html/body/app-root/div/div/app-dashboard/section[1]/div/div[2]/div/button') print("Start New Booking (Button) click >>>> Success") sleep(3) select_first_category(sb) def select_first_category(sb): sleep(1) sb.highlight(".mt-15") sb.click('#mat-select-value-1') # Opens (Choose your Visa Application Centre) 'the Drop-down menu sb.click('span:contains("Application Centre")') select_second_category(sb) def select_second_category(sb): sleep(1) sb.highlight_click('#mat-select-value-5') # Opens (Choose your appointment category) 'the Drop-down menu sb.click('//*[@id="mat-option-2"]/span') select_last_category(sb) def select_last_category(sb): sleep(1) sb.highlight_click('#mat-select-value-3') # Opens (Choose your sub-category) 'the Drop-down menu sb.click('//*[@id="mat-option-3"]/span') Check_Appointment(sb) def Check_Appointment(sb): while True: no_appointment_message = "no appointment" element_text = sb.get_text('/html/body/app-root/div/div/app-eligibility-criteria/section/form/mat-card[1]/form/div[4]') if no_appointment_message in element_text: go_to_homepage(sb) else: print("Earliest available slot for Applicants") playsound('./Music.mp3') print("Attention Alarm >>>> Success") get_appointment_data(sb) break # Break the loop when an appointment is found def get_appointment_data(sb): # Search For Continue Button sb.highlight_click('button.mat-focus-indicator') print("Continue 1 Enabled (Button) click >>>> Success") sleep(4) def go_to_homepage(sb): sb.highlight_click('/html/body/app-root/div/header/div[1]/div/a/img') print("Back to Booking There is No Dates >>>> Success") click_new_booking(sb) def open_the_form_turnstile_page(sb): # 页面打开逻辑(需补充) pass def click_turnstile_and_verify(sb): # Turnstile验证逻辑(需补充) pass with SB(uc=True, demo=True) as sb: while True: try: open_the_form_turnstile_page(sb) click_turnstile_and_verify(sb) click_new_booking(sb) # 修正原代码中错误的函数定义 except Exception as e: print(f'error encountered: {e}') finally: sleep(2) quit()
问题原因分析
- 硬编码sleep不可靠:固定等待时间无法适配页面加载波动,元素可能未完全渲染就被调用。
- 动态元素ID失效:Angular Material生成的元素ID(如
#mat-select-value-1)是动态的,页面刷新后会变化,导致定位失败。 - 递归调用导致流程混乱:
go_to_homepage调用click_new_booking,Check_Appointment又循环调用go_to_homepage,易引发栈溢出或页面状态异常。 - 主循环强制退出:
finally块中的quit()会在每次循环后关闭浏览器,无法实现持续重复执行。
修复方案
1. 替换硬sleep为显式等待
使用Selenium显式等待,等待元素可见/可点击后再操作,替代固定sleep:
from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC def wait_for_element(sb, locator, timeout=15): return WebDriverWait(sb.driver, timeout).until( EC.element_to_be_clickable(locator) )
2. 使用稳定的定位方式
避免依赖动态ID,改用元素属性、文本或层级结构定位:
- 替换
#mat-select-value-1为mat-select[placeholder="Choose your Visa Application Centre"] - 替换
//*[@id="mat-option-2"]/span为//span[text()="你的选项文本"]
3. 重构循环逻辑,避免递归
将流程控制移到主循环,移除递归调用,改为循环重试:
with SB(uc=True, demo=True) as sb: try: open_the_form_turnstile_page(sb) click_turnstile_and_verify(sb) while True: try: click_new_booking(sb) select_first_category(sb) select_second_category(sb) select_last_category(sb) status_text = check_appointment_status(sb) if "no appointment" not in status_text: print("Earliest available slot for Applicants") playsound('./Music.mp3') print("Attention Alarm >>>> Success") get_appointment_data(sb) break print("无可用预约,返回主页重试...") go_to_homepage(sb) sleep(3) # 避免频繁请求被限制 except Exception as e: print(f'单次流程执行失败: {e}') go_to_homepage(sb) sleep(5) except Exception as e: print(f'初始化失败: {e}')
4. 移除不必要的quit()
主循环中的finally: quit()会直接关闭浏览器,导致无法重复执行,应移除该语句,仅在找到预约或严重错误时退出。
最终优化后的核心代码示例
from time import sleep from playsound import playsound from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC def wait_for_element(sb, locator, timeout=15): return WebDriverWait(sb.driver, timeout).until( EC.element_to_be_clickable(locator) ) def click_new_booking(sb): start_btn = wait_for_element(sb, (By.XPATH, '/html/body/app-root/div/div/app-dashboard/section[1]/div/div[2]/div/button')) sb.highlight_click(start_btn) print("Start New Booking (Button) click >>>> Success") def select_first_category(sb): select_locator = (By.CSS_SELECTOR, 'mat-select[placeholder="Choose your Visa Application Centre"]') select_element = wait_for_element(sb, select_locator) sb.highlight_click(select_element) option_locator = (By.XPATH, '//span[text()="Application Centre"]') option_element = wait_for_element(sb, option_locator) sb.click(option_element) select_second_category(sb) def select_second_category(sb): select_locator = (By.CSS_SELECTOR, 'mat-select[placeholder="Choose your appointment category"]') select_element = wait_for_element(sb, select_locator) sb.highlight_click(select_element) option_locator = (By.XPATH, '//span[text()="你的类别文本"]') option_element = wait_for_element(sb, option_locator) sb.click(option_element) select_last_category(sb) def select_last_category(sb): select_locator = (By.CSS_SELECTOR, 'mat-select[placeholder="Choose your sub-category"]') select_element = wait_for_element(sb, select_locator) sb.highlight_click(select_element) option_locator = (By.XPATH, '//span[text()="你的子类别文本"]') option_element = wait_for_element(sb, option_locator) sb.click(option_element) def check_appointment_status(sb): status_locator = (By.XPATH, '/html/body/app-root/div/div/app-eligibility-criteria/section/form/mat-card[1]/form/div[4]') status_element = wait_for_element(sb, status_locator) return sb.get_text(status_element) def go_to_homepage(sb): home_btn = wait_for_element(sb, (By.XPATH, '/html/body/app-root/div/header/div[1]/div/a/img')) sb.highlight_click(home_btn) print("Back to Booking There is No Dates >>>> Success") def get_appointment_data(sb): continue_btn = wait_for_element(sb, (By.CSS_SELECTOR, 'button.mat-focus-indicator')) sb.highlight_click(continue_btn) print("Continue 1 Enabled (Button) click >>>> Success") def open_the_form_turnstile_page(sb): sb.get("你的目标页面URL") # 补充实际页面URL def click_turnstile_and_verify(sb): # 补充Turnstile验证的具体逻辑 pass with SB(uc=True, demo=True) as sb: try: open_the_form_turnstile_page(sb) click_turnstile_and_verify(sb) while True: try: click_new_booking(sb) select_first_category(sb) select_second_category(sb) select_last_category(sb) status_text = check_appointment_status(sb) if "no appointment" not in status_text: print("Earliest available slot for Applicants") playsound('./Music.mp3') print("Attention Alarm >>>> Success") get_appointment_data(sb) break print("无可用预约,返回主页重试...") go_to_homepage(sb) sleep(3) except Exception as e: print(f'单次流程执行失败: {e}') go_to_homepage(sb) sleep(5) except Exception as e: print(f'初始化失败: {e}')
内容的提问来源于stack exchange,提问作者Saber Abd ElHalim
相关产品推荐
相关产品推荐

