为什么 Selenium 的 wait.until_not(EC.invisibility_of_element_located) 等待加载器消失的时间太长?

Why does Selenium's wait.until_not(EC.invisibility_of_element_located) wait for too long for a loader to disappear?

等待元素不可见时,哪个 selenium.webdriver.support.expected_conditions 更适合使用? 就我而言,我将数据输入到表单中,单击保存并等待加载程序消失

from selenium.webdriver.support import expected_conditions as EC 
wait = WebDriverWait(driver, 10)
wait.until(EC.presence_of_element_located((SelectBy.CSS_SELECTOR, ".spinner")))
debug("loader appeared")
wait.until(EC.invisibility_of_element_located((SelectBy.CSS_SELECTOR, ".spinner")))
debug("loader disappeared")

在输出中,我看到第二次等待执行了20秒(我的全局隐式等待是20秒)

360ms ⟥     [debug] loader appeared
21s 141ms ⟥ [debug] loader disappeared

定位器很好,我正在尝试了解等待有什么问题。 有没有人有类似的问题?我很乐意提出任何建议。

来自 Waits

的文档

Warning: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example, setting an implicit wait of 10 seconds and an explicit wait of 15 seconds could cause a timeout to occur after 20 seconds.

可能是以下 2 个等待的混淆:

  • 全局隐式等待为 20 秒
  • WebDriverWait(驱动程序, 10)

导致不可预测等待时间。


解决方案

同时使用以下代码行将 WebDriverWait you need to reconfigure 归纳为 0

  • Python:

    driver.implicitly_wait(0)
    
  • Java:

    driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
    
  • DotNet:

    driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(0);
    

您的等待操作相互堆叠,因为您的代码是链式的。

让我用你的代码解释一下:

# 1. create a wait object
wait = WebDriverWait(driver, 10)

# 2. execute a wait statement
wait.until(EC.presence_of_element_located((SelectBy.CSS_SELECTOR, ".spinner")))
debug("loader appeared")

# 3. execute a wait statement
wait.until(EC.invisibility_of_element_located((SelectBy.CSS_SELECTOR, ".spinner")))
debug("loader disappeared")

两个等待语句(#2 和#3)都使用相同的等待对象,因此它们的执行将“堆栈”:

  1. 等待对象将等待 10 秒的条件
  2. 等待 10 秒(继承) + 微调器出现
  3. 等待 10 秒 (继承) + 微调器出现 (继承) + 微调器消失

操作 #2 等待 10 秒。操作 #3 等待 20 秒。

来自 Explicit Waits

的文档

你也可以试试这个:

try:
  WebDriverWait(driver, 10).until(
    EC.invisibility_of_element_located((By.CSS_SELECTOR, ".spinner"))
  )
finally:
  debug('loader disappeared')

In the code above, Selenium will wait for a maximum of 10 seconds for an element matching the given criteria to be found. If no element is found in that time, a TimeoutException is thrown. By default, WebDriverWait calls the ExpectedCondition every 500 milliseconds until it returns success. ExpectedCondition will return true (Boolean) in case of success or not null if it fails to locate an element.

这种方式解决了我的问题,我认为这是一个很好的做法,你不会等待超过预设时间。