0

我正在编写一段代码来自动化登录过程。该过程包括在第一页填写用户名,单击按钮并进入第二页,我将在其中填写 pw 并按下第二个按钮。该网页有时会看到大量流量,并在单击第一页后给出“稍后再试...”消息。为了解决这个问题,我设置了一个循环来继续点击,直到我们进入下一页。

一旦我进入下一页,我仍然处于 while 循环中。但是,我期待寻找“稍后再试”消息会产生NoSuchElementException并因此中断循环,但我得到了StaleElementReferenceException。我明白,因为我转到另一个页面,所以这个“稍后再试”元素不再存在于 DOM 中。

为什么会引发 StaleElementReferenceException 而不是 NoSuchElementException?如果网页上的流量很低,则不会生成“稍后再试”消息,并且除了 NoSuchElementException 会中断循环。消息一出现,StaleElement。即使我们不将元素存储在变量中,Selenium 是否会跟踪元素的引用?如果是这样,我们如何删除它?

我最初尝试使用except StaleElementReferenceException:来捕获此异常。但什么也没有发生。代码最终点击进入下一页,但继续运行循环,在 StaleElementReferenceException(第 4 行)处中断。我如何捕捉到这个异常?我已经浏览了我认为所有相关的问题,但没有找到有效的答案。

编辑 1 我知道在人们使用的 SO 上找到了不同的示例except StaleElementReferenceException:但是,它在我下面的代码中不起作用。代码一直循环,直到它设法传递到下一页,但随后因过时元素异常而中断。

while True:
    try:
        #looking for "try again later" message
        WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, "//[@id='uiview']/ui-view/div/div[1]/div[1]/ui-view/div/div[2]/div/div[2]/form/div[3]/p")))
        #if it finds the element it clicks the login button.
        login_butn_1.click()
        print("clicked")

        #if logging in works; no "try again later" element, so we can break the loop
    except NoSuchElementException:
        print("no such element")
        break
    #Sometimes loading time is too long for "try again later"... message too appear and locating that element times out
    #Need to reselect the button to be able to click it
    except TimeoutException:           
        webdriver.ActionChains(self.driver).move_to_element(login_butn_1).click(login_butn_1).perform()
        print("time out")

    except StaleElementReferenceException:
        print("stale element exception")
        break
4

1 回答 1

0

陈旧的意思是陈旧的、腐烂的、不再新鲜的。陈旧元素是指旧元素或不再可用的元素。假设在 WebDriver 中作为 WebElement 引用的网页上有一个元素。如果 DOM 发生变化,那么 WebElement 就会过时。如果我们尝试与过时的元素交互,则会抛出 StaleElementReferenceException。

这是正常的,默认情况下轮询元素状态时,我记得 500 毫秒会发生这种情况。您也可以在您的情况下添加它,例如逻辑上“元素不在 DOM 中”意味着不存在。或者添加额外的等待,因为在几毫秒内可以刷新并出现。

尝试添加额外的等待或将其放入 try{} catch{} 并刷新元素,这意味着尝试再次初始化它element = driver.find_element(By.XPATH, '//[@id='uiview']/ui-view/div/div[1]/div[1]/ui-view/div/div[2]/div/div[2]/form/div[3]/p"]')

注意元素的刷新会引发异常

于 2020-04-27T10:14:38.623 回答