【问题标题】:Selenium identifies the button as clickable when it wasn'tSelenium 将按钮识别为可点击
【发布时间】:2020-10-22 07:00:13
【问题描述】:

我遇到了一个问题,Selenium 说一个按钮即使在被禁用时也是可点击的。

我将 Selenium 与一个网站一起使用,您必须先在该网站上选择一个日期,然后从下拉列表中选择时间段,然后才能点击“预订”按钮并实际执行任何操作。在选择日期和时间段之前,按钮元素是

<div id="pt1:b2" class="x28o xfn p_AFDisabled p_AFTextOnly" style="width:300px;" _afrgrp="0" role="presentation"><a data-afr-fcs="false" class="xfp" aria-disabled="true" role="button"><span class="xfx">Book</span></a></div>

选择日期和时间段后,按钮变为

<div id="pt1:b2" class="x28o xfn p_AFTextOnly" style="width:300px;" _afrgrp="0" role="presentation"><a href="#" onclick="this.focus();return false" data-afr-fcs="true" class="xfp" role="button"><span class="xfx">Book</span></a></div>

我正在尝试使用此代码等待按钮可点击

wait = WebDriverWait(driver, 10)
wait.until(EC.element_to_be_clickable((By.ID, 'pt1:b2')))

但 Selenium 表示,即使没有选择日期或时间段,并且该按钮完全变灰且无法点击,该按钮在网站加载后几乎可以立即点击。我已经通过检查从导航到 url 之后和等待按钮可点击之后的时间戳来测试这一点,并且几乎没有延迟。我已经手动尝试了除循环之外的尝试并在两者之间休眠以能够成功单击按钮,但宁愿找出导致此问题的原因。有什么想法吗?

【问题讨论】:

  • Selenium 不会真正检测到元素是否被其他元素覆盖、折叠到 1 点或以您不希望的方式处理点击。如果无法点击一个元素,则当它能够接受点击事件时,元素是可点击的。
  • 有没有办法等待按钮使用 Selenium 实际可点击?元素属性在实际可点击和不可点击之间变化很大。例如,我不太熟悉 Selenium 的功能,但它可能会等待类不包含禁用的文本或等待按钮具有链接目标或其他东西。
  • 这取决于元素和具体情况。当 elemet 设置了特定的 ptoperties 时,我必须添加额外的 JS 语句作为等待的条件,以确保从用户的角度来看该元素确实处于可点击状态。
  • 您为此使用了 Selenium 的哪些功能?我已经列出了元素状态不是和可点击时的状态,所以想知道您是否对哪些属性对区分最有用有任何想法。
  • 我使用execute_script()(见this example)。但是如果满足点击条件,为我提供答案的大部分工作都是我们的前端工程师。抱歉,我现在知道的就这些了。

标签: python selenium selenium-webdriver webdriverwait expected-condition


【解决方案1】:

仅通过搜索要更改的类属性而不是 element_to_be_clickable 即可解决此问题。

wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div[class='x28o xfn p_AFTextOnly']")))

【讨论】:

    【解决方案2】:

    element_to_be_clickable()

    element_to_be_clickable 是检查元素是否可见并启用以便您可以单击它的期望。它是defined

    def element_to_be_clickable(locator):
        """ An Expectation for checking an element is visible and enabled such that
        you can click it."""
        def _predicate(driver):
        element = visibility_of_element_located(locator)(driver)
        if element and element.is_enabled():
            return element
        else:
            return False
    
        return _predicate
        
    

    现在,即使没有选择日期或时间段,当网站加载时,class 属性值 p_AFDisabled 的存在决定了元素是 启用 还是已禁用。接下来,当您填写日期或时间段时,class 属性的值 p_AFDisabled 将被删除,元素变为 可点击

    因此,理想情况下,要等待按钮可点击,您需要为element_to_be_clickable() 诱导WebDriverWait,并且您可以使用以下任一Locator Strategies

    • 使用CSS_SELECTOR

      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.p_AFTextOnly > a[onclick] > span.xfx"))).click()
      
    • 使用XPATH

      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[contains(@class, 'p_AFTextOnly')]/a[@onclick]/span[text()='Book']"))).click()
      
    • 注意:您必须添加以下导入:

      from selenium.webdriver.support.ui import WebDriverWait
      from selenium.webdriver.common.by import By
      from selenium.webdriver.support import expected_conditions as EC
      

    【讨论】:

      【解决方案3】:

      Selenium isclickable 检查是否已显示并启用以检查点击能力

      isdisplay 检查 style 属性,而 isenabled 检查 disabled 属性

      现在 disable 在大多数情况下不是通过 html disable 属性处理,而是通过 javascript 和 css 类处理

      所以可点击条件在这些情况下不起作用

      https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html

      所以在这种情况下,点击不会引发错误

      https://github.com/SeleniumHQ/selenium/blob/trunk/py/selenium/common/exceptions.py

      如果您检查异常类,您可以看到异常仅用于不可见、单击拦截和未启用

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-25
        • 2020-06-24
        • 1970-01-01
        • 1970-01-01
        • 2023-04-06
        • 2014-02-16
        • 2016-05-08
        相关资源
        最近更新 更多