【问题标题】:selenium.common.exceptions.ElementNotVisibleException: Message: element not interactable and explicit wait not working with Selenium and Pythonselenium.common.exceptions.ElementNotVisibleException:消息:元素不可交互且显式等待不适用于 Selenium 和 Python
【发布时间】:2019-06-27 12:05:18
【问题描述】:

我正在尝试访问PenFed 以获得我当前的未结金额。我做了很多研究,不幸的是,我仍然很难过。我正在使用 Python Selenium,我试图单击侧面的初始登录按钮以查看用户名字段。这是元素的 HTML 代码:

<a href="https://www.penfed.org/" class="pfui-button-login login-slide-button pfui-button pfui-btn-tertiary-dark-blue-outline" id="mobile-login" data-di-id="#mobile-login">Login</a>

当我尝试运行以下代码时:

driver.find_element_by_id("mobile-login").click()

我收到以下错误:

selenium.common.exceptions.ElementNotVisibleException: Message: element not interactable

即使我尝试使用 WebDriver 等待功能,例如:

try:
    WebDriverWait(driver, 5).until(EC.visibility_of_element_located((By.ID, "mobile-login"))).click()
except ElementNotVisibleException:
    WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.ID, "mobile-login"))).click()

无论我让他们等待多久,我都会收到超时消息:

raise TimeoutException(message, screen, stacktrace) selenium.common.exceptions.TimeoutException: Message:

我的所有研究都表明调用等待函数应该可以修复它,但它对我不起作用。我还读到在单击按钮之前我必须调用的元素顶部可能有一个图像覆盖,但我也没有在网站代码中看到任何内容。如果我正在测试它,我能够通过代码单击按钮的唯一方法是我先物理单击它,所以我不知道我可以使用其他任何东西。提前感谢您的帮助!

更新:我发现以下代码对我有用:

element = driver.find_element_by_id("mobile-login")
driver.execute_script("$(arguments[0]).click();", element)

但我不知道 execute_script 实际上做了什么。有人可以解释那段代码是否有效,或者是否有任何其他替代方案适用于他们?

【问题讨论】:

  • 我有点困惑,你是不是想和这个元素交互? <button class="pfui-button login-slide-button pfui-button-login dtm-global-nav" data-id="Open Log In Drawer" data-component="globalnavl1" type="button"> Log In </button>
  • @Rajagopalan 是的,这个线程中的其他人指出,通过调整我的浏览器,我可以看到实际的登录按钮 ID,但我只看到移动登录的 ID。谢谢!

标签: python selenium selenium-webdriver css-selectors webdriverwait


【解决方案1】:

您尝试单击的链接适用于移动网站,如果您以桌面分辨率查看该网站,则该链接不可见。如果您缩小浏览器直到它改变布局,您将看到与该链接对应的登录按钮出现。这就是您收到ElementNotVisibleException 的原因。

对于你的第二个问题,使用.execute_script() 起作用的原因是它直接执行JS 并且可以点击任何东西......隐藏与否。 Selenium 旨在像用户一样与页面交互,因此它不会让您单击不可见的元素等。 如果您打算让您的脚本像用户一样工作,则需要避免使用.execute_script(),因为它允许您在页面上执行用户无法执行的操作。

如果您想像桌面用户一样登录,您需要使用下面的 CSS 选择器单击“登录”按钮

button[data-id='Open Log In Drawer']

这将打开一个侧面板,您可以在其中输入您的用户名等并登录。仅供参考...您可能需要等待让面板有机会打开,然后才能继续登录过程。

【讨论】:

    【解决方案2】:

    所需元素是动态元素,因此要定位元素,您必须诱导 WebDriverWait 以使 元素可点击,您可以使用以下解决方案:

    • 代码块:

      from selenium import webdriver
      from selenium.webdriver.chrome.options import Options
      from selenium.webdriver.support.ui import WebDriverWait
      from selenium.webdriver.common.by import By
      from selenium.webdriver.support import expected_conditions as EC
      
      options = Options()
      options.add_argument('start-maximized')
      options.add_argument('--disable-extensions')
      driver = webdriver.Chrome(chrome_options=options, executable_path=r'C:\WebDrivers\chromedriver.exe')
      driver.get('https://www.penfed.org/')
      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.pfui-button.login-slide-button.pfui-button-login.dtm-global-nav[data-id='Open Log In Drawer']"))).click()
      
    • 浏览器快照:

    【讨论】:

    • 我正在使用webdriver等待功能,但我仍然遇到问题。我认为主要是我在寻找错误的按钮 ID,所以每次运行 webdriver wait 时都会遇到超时异常。
    【解决方案3】:

    您指定的代码是JQueryexecute_script(p1, p2) 运行一个 js 脚本,其中 p1 是脚本(在您的情况下是单击元素的 JQuery 行), p2 是所需的元素。如果arguments[0] 等于“元素”,您似乎不需要 p2,但我不完全确定。

    一个潜在的解决方法是使用一个计数器来计算您单击该元素的次数。如果计数器达到某个数字并且页面没有更改(您可以通过在当前页面上查找唯一元素/值来检查),那么您知道它不可点击。

    祝你好运!

    【讨论】:

    • 谢谢!我认为这更像是一个旁注,我不认为 execute_script 正在攻击问题的根源,而只是攻击了分支。我在 stackoverflow 上找到了它并且它有效,但这为我提供了一些关于该功能的良好背景!
    猜你喜欢
    • 2019-04-01
    • 1970-01-01
    • 2019-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-19
    • 1970-01-01
    相关资源
    最近更新 更多