如何通过 Python 正确使用 Selenium 中的 WebDriverWait?

How to use WebDriverWait from Selenium properly through Python?

既然问题已经解决,我只是想添加一个编辑。替换那 2 个 time.sleep() 使我的程序从 180 秒减少到 30 秒。WebDriverWait 大大改进了运行时间。

只是想确定我是否正确设置了 WebDriverWait。这是我的工作脚本,我使用 time.sleep()

for x,sequence in enumerate(table.find_elements_by_xpath('//*[@id="gwzSngrOrderResultPanelRoot"]/table/tbody/tr/td[9]'),1):
        driver.find_element_by_xpath(f'//*[@id="gwzSngrOrderResultPanelRoot"]/table/tbody/tr[{x}]/td[9]/span[2]').click()
        time.sleep(5)
        element = WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.XPATH, '//*[@id="gwzViewResultsModalDialog"]/div/div/div[3]/button')))
        seq_info=driver.find_element_by_xpath('//*[@id="gwzViewResultsModalDialog"]/div/div/div[2]/div')
        seq_list.append([seq_info.text])
        driver.find_element_by_xpath('//*[@id="gwzViewResultsModalDialog"]/div/div/div[3]/button').click()
        time.sleep(5)

简而言之,它经过 table,单击打开弹出窗口的按钮,从弹出窗口中提取文本,然后关闭所述弹出窗口。我必须等待弹出窗口打开并完全关闭。我目前正在使用 time.sleep(),但我正在尝试切换到 WebDriverWait。这就是我实现它的方式。

for x,sequence in enumerate(table.find_elements_by_xpath('//*[@id="gwzSngrOrderResultPanelRoot"]/table/tbody/tr/td[9]'),1):
        driver.find_element_by_xpath(f'//*[@id="gwzSngrOrderResultPanelRoot"]/table/tbody/tr[{x}]/td[9]/span[2]').click()
        element = WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.XPATH, '//*[@id="gwzViewResultsModalDialog"]/div/div/div[3]/button')))
        seq_info=driver.find_element_by_xpath('//*[@id="gwzViewResultsModalDialog"]/div/div/div[2]/div')
        seq_list.append([seq_info.text])
        driver.find_element_by_xpath('//*[@id="gwzViewResultsModalDialog"]/div/div/div[3]/button').click()
        time.sleep(5)

但是,上面的方法不起作用。我收到此错误:

driver.find_element_by_xpath('//*[@id="gwzViewResultsModalDialog"]/div/div/div[3]/button').click()
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable

如果我 return 到 time.sleep(),这就消失了,因此让我觉得我一定是错误地设置了我的 WebDriverWait。等待是浏览器的打开和关闭,所以我们必须等到按钮出现,所以我把按钮本身的xpath放在了WebDriverWait中。这是正确的设置吗?

编辑: 谢谢@DebanjanB 的回答。但是,我在尝试删除我的 time.sleep() 时遇到了另一个问题,这就是我目前拥有的。

for x,sequence in enumerate(table.find_elements_by_xpath('//*[@id="gwzSngrOrderResultPanelRoot"]/table/tbody/tr/td[9]'),1):
        driver.find_element_by_xpath(f'//*[@id="gwzSngrOrderResultPanelRoot"]/table/tbody/tr[{x}]/td[9]/span[2]').click()
        time.sleep(5)
        #WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//*[@id="gwzViewResultsModalDialog"]/div/div/div[2]/div')))
        seq_info=driver.find_element_by_xpath('//*[@id="gwzViewResultsModalDialog"]/div/div/div[2]/div')
        seq_list.append([seq_info.text])
        WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="gwzViewResultsModalDialog"]/div/div/div[3]/button'))).click()

上面的 time.sleep() 在提取数据之前等待弹出窗口打开(来自上一次点击)。如果我用下面的#WebDriver 删除 time.sleep,它仍然向前移动,但由于某种原因 seq_info.text 现在是空白的(它不再找到文本)。我不太明白为什么会这样。这不是单击或按钮,我只是想在从中提取信息之前检查弹出窗口是否打开。

简答,,虽然在语法上是正确的,但您没有以最佳方式使用 WebDriverWait

除了 ,您还使用了 time.sleep()

time.sleep(秒)

time.sleep(secs) suspends the execution of the current thread for the given number of seconds. The argument may be a floating point number to indicate a more precise sleep time. The actual suspension time may be less than that requested because any caught signal will terminate the sleep() following execution of that signal’s catching routine. Also, the suspension time may be longer than requested by an arbitrary amount because of the scheduling of other activity in the system.

您可以在

中找到详细的讨论

此外,

  • for 循环中,当您打算迭代而不是 /tr[{x}] 时,您需要 //tr[{x}]

  • 要收集所需的 text 你需要使用 visibility_of_element_located().

  • <button> 本质上是交互式的,所以当您需要与它们交互时,您需要使用 element_to_be_clickable() 而不是 presence_of_element_located()

  • 可能的解决方案:

    for x,sequence in enumerate(table.find_elements_by_xpath('//*[@id="gwzSngrOrderResultPanelRoot"]/table/tbody/tr/td[9]'),1):
          WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="gwzSngrOrderResultPanelRoot"]/table/tbody//tr[{x}]/td[9]/span[2]'))).click()
          seq_list.append(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//*[@id='gwzViewResultsModalDialog']/div/div/div[2]/div"))).text)
          WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="gwzViewResultsModalDialog"]/div/div/div[3]/button'))).click()