
selenium自动化测试中,循环操作和动态页面元素常常导致“元素未找到”错误。本文将深入探讨隐式等待和`time.sleep()`的局限性,并详细介绍如何利用selenium的显式等待机制(`webdriverwait`和`expected_conditions`)来解决此类问题,确保自动化脚本的稳定性和健壮性,特别是在重复执行任务时。
在进行Web自动化测试或数据抓取时,尤其是在涉及页面导航、动态内容加载或重复操作的场景中,我们经常会遇到“元素未找到”(ElementNotVisibleException 或 NoSuchElementException)的错误。这通常发生在脚本尝试与某个元素交互时,该元素尚未完全加载、渲染或变得可交互。本文将以一个实际的预约系统自动化案例为例,深入探讨这一问题,并提供使用Selenium显式等待的解决方案,以构建更稳定、可靠的自动化脚本。
在上述预约系统的自动化流程中,用户反馈在首次执行时元素能被找到,但在循环重复执行时,却报告Element {#mat-select-value-1} was not present after 7 seconds!。这典型地揭示了两种常见的等待机制的不足:
显式等待是Selenium中最强大和灵活的等待机制。它允许我们定义一个特定的条件,并设置一个最长等待时间。WebDriver会在此时间内不断检查该条件是否满足,一旦满足,立即继续执行;如果超时仍未满足,则抛出TimeoutException。
显式等待主要通过WebDriverWait类和expected_conditions模块来实现。
立即学习“Python免费学习笔记(深入)”;
在使用显式等待之前,需要从Selenium库中导入相关模块:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By
WebDriverWait的构造函数接收两个参数:WebDriver实例和最长等待时间(秒)。
expected_conditions模块提供了多种预定义的条件,例如:
根据用户提供的错误信息Element {#mat-select-value-1} was not present after 7 seconds!,问题出在选择第一个类别时。我们可以使用显式等待来确保该下拉菜单元素加载并变得可点击。
假设sb是WebDriver的实例(或其包装类,其行为类似WebDriver)。
原始代码片段:
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_first_category(sb):
# 定义最长等待时间,例如10秒
wait = WebDriverWait(sb, 10)
# 等待类别选择器元素变得可点击
# 使用CSS选择器定位 #mat-select-value-1
first_category_selector = wait.until(
EC.element_to_be_clickable((By.ID, "mat-select-value-1")) # 注意:By.ID不需要#前缀
)
first_category_selector.click()
print("First category selector clicked >>>>> Success")
# 等待下拉菜单中的“Application Centre”选项出现并可点击
# 这里假设sb.click('span:contains("Application Centre")') 内部能够处理等待或这是一个可靠的定位方式
# 如果该选项也是动态加载的,也需要显式等待
application_center_option = wait.until(
EC.element_to_be_clickable((By.XPATH, '//span[contains(text(), "Application Centre")]'))
)
application_center_option.click()
print("Application Centre option selected >>>>> Success")
select_second_category(sb)注意事项:
在Check_Appointment函数中,我们希望在没有预约信息时返回主页并重试,直到找到预约信息。显式等待可以更好地处理“没有预约”信息的出现或“有预约”信息的出现。
原始Check_Appointment代码片段:
def Check_Appointment(sb):
while True:
no_appointment_message = "We are sorry but no appointment slots are currently available. New slots open at regular intervals, please try again later"
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)
print("We are sorry but no appointment slots are currently available.")
go_to_homepage(sb) # 这里重复调用 go_to_homepage
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使用显式等待和try-except优化后的Check_Appointment:
为了更好地处理预约信息页面的状态,我们可以尝试等待“无预约”消息或“有预约”的元素出现。
def Check_Appointment(sb):
wait = WebDriverWait(sb, 15) # 给页面加载和信息出现留足时间
no_appointment_xpath = '/html/body/app-root/div/div/app-eligibility-criteria/section/form/mat-card[1]/form/div[4]'
while True:
try:
# 尝试等待“无预约”消息出现
# 注意:这里假设sb.get_text能够获取到元素文本,或者我们可以直接等待元素出现并获取文本
# 更好的做法是等待包含该文本的元素出现
# 等待包含“no appointment”消息的元素出现
# 假设该消息总是出现在特定的元素中,并且我们可以等待该元素的文本包含特定内容
wait.until(EC.text_to_be_present_in_element((By.XPATH, no_appointment_xpath), "no appointment"))
# 如果条件满足,说明没有预约
print("We are sorry but no appointment slots are currently available.")
go_to_homepage(sb)
# 每次返回主页后,需要重新开始整个预约流程,所以这里不需要break,而是让外层循环继续
# 如果 go_to_homepage 会自动触发 click_new_booking,那么这里就直接返回
return # 返回到主循环,让它重新开始整个流程
except TimeoutException:
# 如果在规定时间内没有出现“无预约”消息,则可能是找到了预约
# 此时可以尝试等待“有预约”的标志性元素,或者直接认为当前页面有预约
print("Earliest available slot for Applicants")
# playsound('./Music.mp3') # 触发警报
print("Attention Alarm >>>>> Success")
get_appointment_data(sb)
break # 找到预约,跳出循环
except Exception as e:
print(f"An unexpected error occurred in Check_Appointment: {e}")
go_to_homepage(sb) # 遇到其他错误也返回主页重试
return # 返回到主循环重要提示:
通过采纳显式等待,您的Selenium自动化脚本将能够更有效地应对Web页面的动态性,显著提升其健壮性和可靠性,尤其是在需要重复执行复杂任务的场景中。
以上就是Selenium Python自动化中处理动态元素与显式等待的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号