time.sleep 在 selenium 中隐式或显式等待不能可靠地工作吗?

implicit or explicit waits in selenium don't work reliably by time.sleep does?

我有一些 selenium 代码可以登录到 jupyterlab(运行 本地)。没有等待,它会失败,因为它试图在它存在之前找到密码输入文本框。所以我尝试使用显式等待,因为这似乎是最干净的解决方案,但它工作不正常。隐式等待从不工作,它似乎在加载页面之前阻止网络服务器 10 秒,所以总是失败。 time.sleep 始终有效,但是它会加载页面,然后等待 10 秒再输入密码,这比 selenium 等待方法效率低且不够干净,据我所知,selenium 等待方法最多等待 10 秒,但一旦元素变得可用。我做错了什么?

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWait
  1. 显式等待 - 有时有效

    driver = webdriver.Firefox()
    driver.get(f"http://localhost:8888")
    wait = WebDriverWait(driver, 10)
    password_input = wait.until(ec.presence_of_element_located((By.ID, "password_input")))
    password = "my_password"
    password_input.send_keys(password + Keys.RETURN)
    

    有时我会收到错误消息:

    selenium.common.exceptions.ElementNotInteractableException: Message: Element is not reachable by keyboard

  2. 隐式等待 - 有时会出错

    driver = webdriver.Firefox()
    driver.get(f"http://localhost:8888")
    driver.implicitly_wait(10)
    password_input = driver.find_element_by_css_selector("password_input")
    password = "my_password"
    password_input.send_keys(password + Keys.RETURN)
    

    有时我会收到错误消息:

    selenium.common.exceptions.ElementNotInteractableException: Message: Element is not reachable by keyboard

  3. time.sleep - 始终有效

    driver = webdriver.Firefox()
    driver.get(f"http://localhost:8888")
    time.sleep(10)
    password_input = driver.find_element_by_id("password_input")
    password = "my_password"
    password_input.send_keys(password + Keys.RETURN)
    

    虽然这总能奏效,但它无缘无故地浪费了时间。硒等待方法确实应该有效。

我做错了什么?

虽然 How to resolve ElementNotInteractableException: Element is not visible in Selenium webdriver? 在技术上是重复的,但它为 Java 解决了这个问题,当重复用于不同的语言时它总是让我很烦,所以我会为 Python.


ec.presence_of_element_located(...) 方法仅测试文档对象模型中元素的存在。它不能确保元素是用户可以与之交互的东西。另一个元素可能会与其重叠,或者在您调用 password_input.send_keys(...).

之前该元素可能会在视图中隐藏一小段时间

等到元素为 "clickable" 通常是最好的解决方案:

driver = webdriver.Firefox()
driver.get(f"http://localhost:8888")
wait = WebDriverWait(driver, 10)

# waiting until element is "clickable" means user can interact with
# it, and thus send_keys(...) can simulate keyboard interaction.
password_input = wait.until(ec.element_to_be_clickable((By.ID, "password_input")))

password = "my_password"
password_input.send_keys(password + Keys.RETURN)