You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()

问题原因分析

  1. 硬编码sleep不可靠:固定等待时间无法适配页面加载波动,元素可能未完全渲染就被调用。
  2. 动态元素ID失效:Angular Material生成的元素ID(如#mat-select-value-1)是动态的,页面刷新后会变化,导致定位失败。
  3. 递归调用导致流程混乱:go_to_homepage调用click_new_booking,Check_Appointment又循环调用go_to_homepage,易引发栈溢出或页面状态异常。
  4. 主循环强制退出: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 17:57:32