【问题标题】:How to use WebDriverWait from Selenium properly through Python?如何通过 Python 正确使用 Selenium 中的 WebDriverWait?
【发布时间】:2020-10-26 16:29:45
【问题描述】:

我只是想现在这个问题已经解决了,我会添加一个编辑。替换这 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)

简而言之,它通过一个表格,单击一个打开弹出窗口的按钮,从弹出窗口中提取文本,然后关闭所述弹出窗口。我必须等待弹出窗口打开并完全关闭。我目前正在使用 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

如果我返回 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 现在是空白的(它不再找到文本)。我不太明白为什么会这样。这不是点击或按钮,我只是想在从中提取信息之前检查弹出窗口是否打开。

【问题讨论】:

  • 您能告诉我们您网页的网址吗?
  • imgur.com/a/fKsiw6a 我正在单击 seq_file 中的剪贴板,这会在同一页面上打开一个弹出窗口,其中包含要提取的信息

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


【解决方案1】:

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

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

time.sleep(秒)

time.sleep(secs) 将当前线程的执行挂起给定的秒数。该参数可以是一个浮点数,以指示更精确的睡眠时间。实际的挂起时间可能少于请求的时间,因为任何捕获的信号都会在执行该信号的捕获例程后终止 sleep()。此外,由于系统中其他活动的调度,暂停时间可能比请求的时间长。

您可以在How to sleep webdriver in python for milliseconds找到详细讨论

此外,

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

  • 要收集所需的文本,您需要使用visibility_of_element_located()

  • <button> 本质上是交互式的,因此您需要在需要与其交互时才使用 presence_of_element_located() 而不是 element_to_be_clickable()

  • 一个可能的解决方案:

    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()
    

【讨论】:

  • 我只使用 time.sleep() 因为我想一次更改 1 步(我知道 time.sleep() 有效,但我不知道如何使用 WebDriverWait,因此如果程序失败,我确切地知道它在哪里/为什么失败)。我同意 WebDriverWait 比 time.sleep() 好得多,但是在我的上述情况下它不起作用。是因为我也在使用 time.sleep() 吗?如果我没有以最佳方式使用它,我该如何优化它的使用?
  • @samman 查看更新的答案并告诉我状态。
  • 哦,那么WebDriverWait也可以点击对象吗? IE。替换 .click() 选项?另外,为什么用//tr 而不是/tr? /tr 为我工作?
  • @samman 1) element_to_be_clickable() 有效、高效且经过验证,应该没有任何疑问。 2) click() 应始终通过 WebDriverWait 调用,无论是 <span> 还是 <button>
  • @samman 查看更新的答案并告诉我状态。
猜你喜欢
  • 2020-11-26
  • 2021-05-03
  • 2019-11-07
  • 1970-01-01
  • 2020-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多