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

Python/Selenium:如何正确结合any_of与element_to_be_clickable使用?

问题描述

我在Selenium项目中需要等待三个元素中的任意一个变为可点击状态,当前使用的代码如下:

LOC1 = (By.ID, "ID1")
LOC2 = (By.ID, "ID2")
LOC2 = (By.ID, "ID3")  # 注:此处存在笔误,应为LOC3
def get_correct_el(self):
    def wait_for_el():
        return self.robot.wait.until(
            EC.any_of(
                EC.element_to_be_clickable(LOC1),
                EC.element_to_be_clickable(LOC2),
                EC.element_to_be_clickable(LOC3),
            )
        )
    el = wait_for_el()
    while el != self.driver.find_element(*LOC1):
        el.click()
        el = wait_for_el()

代码可正常运行,但Pylance报出以下类型错误:

Argument of type "(WebDriverOrWebElement) -> (WebElement | Literal[False])" cannot be assigned to parameter "expected_conditions" of type "(D@any_of) -> T@any_of" in function "any_of"
Type "(WebDriverOrWebElement) -> (WebElement | Literal[False])" cannot be assigned to type "(Unknown) -> WebElement"
Function return type "WebElement | Literal[False]" is incompatible with type "WebElement"
Type "WebElement | Literal[False]" cannot be assigned to type "WebElement"
"Literal[False]" is incompatible with "WebElement"PylancereportArgumentType
(function) def element_to_be_clickable(mark: WebElement | Tuple[str, str]) -> ((WebDriverOrWebElement) -> (WebElement | Literal[False]))
An Expectation for checking an element is visible and enabled such that you can click it.

element is either a locator (text) or an WebElement

我已确认是any_of的类型校验问题:any_of期望参数类型为*expected_conditions: Callable[[D], T],但element_to_be_clickable的返回类型为Callable[[WebDriverOrWebElement], Union[Literal[False], WebElement]],二者签名不匹配。想请教该错误是否可忽略,以及如何正确使用any_of与element_to_be_clickable。


解决方案

1. 错误是否可忽略?

可以忽略。该报错仅为Pylance的静态类型检查提示,Selenium的any_of内部逻辑完全能处理element_to_be_clickable返回的False或WebElement类型——当条件不满足时返回False,满足时返回对应元素,any_of会正确识别第一个满足的条件并返回结果,不影响代码实际运行。

若不想看到该报错,可在EC.any_of代码行添加类型忽略注解:

EC.any_of(
    EC.element_to_be_clickable(LOC1),
    EC.element_to_be_clickable(LOC2),
    EC.element_to_be_clickable(LOC3),
)  # type: ignore[arg-type]

2. 正确使用方式

方式一:修正类型兼容问题(适合类型洁癖)

自己封装一个类型兼容的element_to_be_clickable版本,确保返回的Callable仅返回WebElement(因为wait.until会自动等待到条件返回真值,实际不会返回False):

from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.remote.webelement import WebElement
from typing import Callable, Tuple, Any

def my_element_to_be_clickable(locator: Tuple[str, str]) -> Callable[[Any], WebElement]:
    def condition(driver: Any) -> WebElement:
        el = EC.element_to_be_clickable(locator)(driver)
        assert el is not False, "目标元素不可点击"
        return el
    return condition

# 使用时替换原方法
def get_correct_el(self):
    def wait_for_el():
        return self.robot.wait.until(
            EC.any_of(
                my_element_to_be_clickable(LOC1),
                my_element_to_be_clickable(LOC2),
                my_element_to_be_clickable(LOC3),
            )
        )
    el = wait_for_el()
    while el != self.driver.find_element(*LOC1):
        el.click()
        el = wait_for_el()

方式二:简化逻辑(更实用)

先修正代码中的笔误:将LOC2 = (By.ID, "ID3")改为LOC3 = (By.ID, "ID3"),避免后续逻辑出错。之后直接保留原逻辑并添加类型忽略即可,因为实际运行无问题。


内容的提问来源于stack exchange,提问作者kiesel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 17:13:30