【问题标题】:How to prevent "State Element Reference" errors in selenium如何防止硒中的“状态元素引用”错误
【发布时间】:2022-02-17 07:04:42
【问题描述】:
driver = webdriver.Chrome(service=s)
url="https://fourminutebooks.com/book-summaries/"
driver.get(url)

page_tabs = driver.find_elements(By.CSS_SELECTOR, "a[class='post_title w4pl_post_title']")
#html = driver.find_elements(By.CSS_SELECTOR,"header[class='entry-header page-header']")

length_page_tabs = len(page_tabs)
in_length = len(page_tabs)
for i in range(length_page_tabs):
  ran = random.randint(0,in_length)
  page_tabs[ran].click()
  driver.execute_script("window.history.go(-1)")
  time.sleep(10)


  #need to get page source of html and then open it to a new file, extract what I want and add it to the email

    

我正在尝试单击其中一个链接,获取 html 代码,将其通过电子邮件发送给自己,然后返回一页并重复。但是,单击第一个随机链接后,代码停止工作,而是得到this error

【问题讨论】:

  • 请将错误作为文本粘贴到您的问题中,使其更具可读性,可以复制和粘贴等。还请包括错误的完整堆栈跟踪。

标签: python selenium


【解决方案1】:

当您将一些元素集合放入变量中时,您必须非常小心,然后进行迭代并执行一些操作。

page_tabs = driver.find_elements...

这种情况下的所有元素都被缓存了,每个浏览器的导航到另一个页面、刷新页面等操作都会使所有这些缓存的元素陈旧。这意味着它们变得像过时并且无法再与它们交互了。

因此,为了避免过时的元素引用错误,您必须防止任何页面重新加载,或者在每次页面状态更改后刷新元素。

【讨论】:

    【解决方案2】:

    StaleElementReferenceException

    StaleElementReferenceException 是一种 WebDriverException 类型,当对元素的引用消失时抛出 stale,即元素不再出现在 @987654322页面的@。

    StaleElementReferenceException 的一些可能原因包括:

    • 您不再在同一页面上,或者自上次找到该元素后页面可能已刷新。
    • 该元素可能已被删除并重新添加到DOM Tree,因为它已被找到。比如一个元素被重新定位。当值更新并重建节点时,这通常会发生在 javascript 框架中。
    • 元素可能位于 iframe 或其他已刷新的上下文中。

    这个用例

    在您的用例中,您已使用locator strategy 创建了一个webelement 列表,即page_tabs

    page_tabs = driver.find_elements(By.CSS_SELECTOR, "a[class='post_title w4pl_post_title']")
    

    每当您调用page_tabs[ran] 时,循环中的下一步都会被重定向到一个新页面,其中page_tabs 列表中的元素变得陈旧并加载新元素。

    当您调用 driver.execute_script("window.history.go(-1)") 时向前移动,您将返回到 page_tabs 元素所在的主页,并且它们会再次重新加载。此时,page_tabs 列表仍继续包含先前搜索的 web 元素,这些元素现在已成为 stale。因此,在第二次迭代中,您将面临 StaleElementReferenceException


    解决方案

    在您的用例中避​​免 StaleElementReferenceException 因为所需的元素是 <A> 标记,因此您可以将 href 属性存储在列表中,而不是保存元素调用 get(href) 如下:

    driver.get("https://fourminutebooks.com/book-summaries/")
    hrefs = [my_elem.get_attribute("href") for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "a[class='post_title w4pl_post_title']")))]
    for href in hrefs:
        driver.get(href)
        print("Placeholder to perform the desired operations on the respective page")
    driver.quit()
    

    参考文献

    您可以在以下位置找到一些相关的详细讨论:

    【讨论】:

      【解决方案3】:

      使用 driver.execute_script 和 javascript。 Javascript 永远不会过时,因为它会立即进行评估。换句话说,如果您使用 Python 选择一个元素,然后与它进行交互,那么它很有可能不再存在。您可以确定它仍然存在的唯一方法是在与它交互时对其进行评估,而这样做的唯一方法是留在浏览器上下文中。

      【讨论】:

        猜你喜欢
        • 2022-01-19
        • 2021-05-10
        • 2020-04-30
        • 1970-01-01
        • 2015-02-02
        • 2015-08-29
        • 2018-01-09
        • 2021-11-01
        • 1970-01-01
        相关资源
        最近更新 更多