
在进行网页自动化测试时,模态框(modal dialog)是一个常见的交互元素。用户点击某个按钮后,模态框会浮现在当前页面之上,并包含新的输入字段或操作按钮。然而,与模态框内元素进行交互时,开发者常会遇到以下挑战:
为了克服上述挑战,我们应该采用一系列稳健的自动化实践。
绝对 XPath 极易受页面结构变化影响。推荐使用以下更具韧性的定位策略:
在提供的案例中,模态框按钮可以通过 CSS 选择器 button[type=primary] .andes-button__content 来定位,模态框本身可以通过 .andes-modal__overlay 定位,而内部输入框则可以通过 [data-testid=name-input] 定位,这些都是非常稳健的定位方式。
time.sleep() 是一种硬性等待,效率低下且不可靠。Selenium 提供了 WebDriverWait 和 expected_conditions (EC) 来实现显式等待,这允许我们等待特定条件满足后再进行下一步操作。
常用的 expected_conditions 包括:
示例:等待元素可见
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
# 等待ID为'myElement'的元素在10秒内变得可见
element = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.ID, 'myElement'))
)针对按钮点击后模态框不立即弹出的情况(防抖),可以实现一个简单的重试逻辑。在每次点击后,检查模态框是否已经出现。
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
def click_and_wait_for_modal_with_retry(driver, max_retries, button_locator, modal_locator_by, modal_locator_value):
"""
点击按钮并等待模态框出现,带重试机制。
:param driver: WebDriver实例
:param max_retries: 最大重试次数
:param button_locator: 按钮的定位器(元组,如 (By.CSS_SELECTOR, 'button.my-button'))
:param modal_locator_by: 模态框定位器的类型 (如 By.CSS_SELECTOR)
:param modal_locator_value: 模态框定位器的值 (如 '.andes-modal__overlay')
"""
retries = 0
while retries < max_retries:
print(f"尝试点击按钮,第 {retries + 1} 次...")
# 1. 等待按钮可点击并点击
button = WebDriverWait(driver, 10).until(EC.element_to_be_clickable(button_locator))
button.click()
# 2. 简短的等待,给页面响应时间,避免过于频繁的检查
time.sleep(0.5)
# 3. 检查模态框是否已出现且可见
# find_elements 返回列表,如果为空则说明元素未找到
modal_elements = driver.find_elements(modal_locator_by, modal_locator_value)
if len(modal_elements) > 0 and modal_elements[0].is_displayed():
print("模态框已成功显示。")
return
retries += 1
print("模态框未显示,重试中...")
raise Exception(f'超出最大重试次数 {max_retries},模态框仍未显示。')
在模态框出现后,其内部元素可能仍然需要时间加载。因此,我们应该先等待模态框本身变得可见,然后将 WebDriverWait 的作用域限制在模态框内部,以更精确地等待其子元素。
# 等待模态框元素本身可见
dialog = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, '.andes-modal__overlay'))
)
# 现在,针对模态框内部的元素创建新的WebDriverWait实例
# 这样可以确保我们只在模态框内查找元素
wait_in_dialog = WebDriverWait(dialog, 10)
# 等待模态框内部的输入框可见
name_input = wait_in_dialog.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, '[data-testid=name-input]'))
)
name_input.send_keys('您的姓名')下面是一个整合了上述所有最佳实践的完整 Selenium 自动化脚本示例,用于演示如何与模态框进行交互:
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 定义点击并等待模态框的重试函数
def click_and_wait_for_modal_with_retry(driver, max_retries, button_locator, modal_locator_by, modal_locator_value):
retries = 0
while retries < max_retries:
print(f"尝试点击按钮,第 {retries + 1} 次...")
# 等待按钮可点击并点击
button = WebDriverWait(driver, 10).until(EC.element_to_be_clickable(button_locator))
button.click()
# 给页面一些时间响应
time.sleep(0.5)
# 检查模态框是否已出现且可见
modal_elements = driver.find_elements(modal_locator_by, modal_locator_value)
if len(modal_elements) > 0 and modal_elements[0].is_displayed():
print("模态框已成功显示。")
return
retries += 1
print("模态框未显示,重试中...")
raise Exception(f'超出最大重试次数 {max_retries},模态框仍未显示。')
# --- Selenium 自动化流程开始 ---
driver = webdriver.Chrome() # 或其他浏览器驱动,如 Firefox()
wait = WebDriverWait(driver, 20) # 全局等待对象,用于页面级别的操作
driver.maximize_window()
# 1. 打开目标网页
driver.get(
'https://www.portalinmobiliario.com/MLC-2148268902-departamento-los-espinos-id-116373-_JM#position=1&search_layout=grid&type=item&tracking_id=eba8327b-85c0-4317-8c63-7c69c5b34e16'
)
# 2. 处理 Cookie 同意弹窗(如果存在)
# 注意:这里使用ID定位,非常稳健
try:
consent_button = wait.until(EC.presence_of_element_located((By.ID, 'newCookieDisclaimerButton')))
consent_button.click()
wait.until(EC.staleness_of(consent_button)) # 等待Cookie弹窗消失
print("已点击Cookie同意按钮。")
except Exception as e:
print(f"未找到或无法点击Cookie同意按钮,或已处理: {e}")
# 3. 点击“联系”按钮并等待模态框弹出
# 按钮定位器:通过CSS选择器定位,比绝对XPath更稳定
contact_button_locator = (By.CSS_SELECTOR, 'button[type=primary] .andes-button__content')
# 模态框定位器:通过CSS选择器定位模态框的overlay
modal_overlay_locator_by = By.CSS_SELECTOR
modal_overlay_locator_value = '.andes-modal__overlay'
try:
click_and_wait_for_modal_with_retry(driver, 3, contact_button_locator,
modal_overlay_locator_by, modal_overlay_locator_value)
except Exception as e:
print(e)
driver.quit()
exit()
# 4. 模态框已弹出,现在定位模态框本身,并等待其内部元素
# 等待模态框(overlay)可见
dialog = wait.until(EC.visibility_of_element_located((modal_overlay_locator_by, modal_overlay_locator_value)))
print("模态框(overlay)已可见。")
# 创建一个新的WebDriverWait实例,作用域为模态框内部,用于定位模态框内的元素
wait_in_dialog = WebDriverWait(dialog, 10)
# 5. 定位并操作模态框内的输入框
# 输入框定位器:使用data-testid属性,非常推荐的定位方式
name_input = wait_in_dialog.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '[data-testid=name-input]')))
name_input.send_keys('测试姓名')
print("已在姓名输入框中输入内容。")
# 模拟输入其他字段,例如邮箱和电话
# email_input = wait_in_dialog.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '[data-testid=email-input]')))
# email_input.send_keys('test@example.com')
# phone_input = wait_in_dialog.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '[data-testid=phone-input]')))
# phone_input.send_keys('1234567890')
time.sleep(5) # 演示目的,等待一段时间查看结果
driver.quit()
print("自动化测试完成。")通过遵循这些最佳实践,您将能够更有效地处理 Selenium 自动化测试中的模态框交互,构建出更健壮、更可靠的自动化脚本。
以上就是Selenium 模态框自动化交互:应对点击防抖与动态元素定位挑战的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号