天天看點

[214]selenium之 坑(StaleElementReferenceException: Message: Element not found in the cache...)

今天給大家分享一個selenium中經常會有人遇到的坑:

selenium.common.exceptions.StaleElementReferenceException: Message: Element not found in the cache - perhaps the page has changed since it was looked up

群裡經常會有人問,“我循環去點選一列連結,但是隻能點到第一個,第二個就失敗了,為什麼?”。原因就在這裡:你點選第二個時已經是新頁面,當然找不到之前頁面的元素。這時,他會問“可是明明元素就在那裡,沒有變,甚至我是回退回來的,頁面都沒有變,怎麼會說是新頁面?”。這個就需要你明白頁面長得一樣不代表就是同一張頁面,就像兩個人長得一樣不一定是同一個人,他們的身份證号不同。頁面,甚至頁面上的元素都是有自己的身份證号(id)的。

我們來試試看:

代碼:

# -*- coding: utf-8 -*-
from selenium import webdriver


driver = webdriver.Firefox()
driver.get('http://www.baidu.com')

print driver.find_element_by_id('kw')  # kw before refresh

driver.refresh()  # refresh

print driver.find_element_by_id('kw')  # kw after refresh

driver.quit()           

複制

結果:

<selenium.webdriver.remote.webelement.WebElement (session="6c251157-6d81-435c-9100-97696a46ab9c", element="{f74ae41d-a557-4d5c-9029-3c122e3d0744}")>
<selenium.webdriver.remote.webelement.WebElement (session="6c251157-6d81-435c-9100-97696a46ab9c", element="{d7bd4320-31f2-4708-824f-f1a8dba3e79b}")>           

複制

我們發現,僅僅是重新整理了一下頁面,兩次的element id是不同的,也就是說這是兩個不同的元素,如果你用以下的方式來定位,自然會因為找不到而報錯:

# -*- coding: utf-8 -*-
from selenium import webdriver


driver = webdriver.Firefox()
driver.get('http://www.baidu.com')

kw = driver.find_element_by_id('kw')  # 先定位并獲得kw元素
kw.click()

driver.refresh()  # refresh

kw.click()  # 重新整理後,仍用原來的kw元素操作,這時會報錯

driver.quit()           

複制

結果:

Traceback (most recent call last):
  File "D:/Code/py/AutoTestFramework/src/others/tryrefreshpage.py", line 16, in <module>
    kw.click()
  File "C:\APP\Python2.7.10\lib\site-packages\selenium\webdriver\remote\webelement.py", line 75, in click
    self._execute(Command.CLICK_ELEMENT)
  File "C:\APP\Python2.7.10\lib\site-packages\selenium\webdriver\remote\webelement.py", line 469, in _execute
    return self._parent.execute(command, params)
  File "C:\APP\Python2.7.10\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 201, in execute
    self.error_handler.check_response(response)
  File "C:\APP\Python2.7.10\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 194, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: Element not found in the cache - perhaps the page has changed since it was looked up
Stacktrace:
    ....           

複制

原因很明顯,你用别人的身份證id去找現在的人,哪怕這兩個人長得很像,他也會告訴你:對不起,你找錯人了。

當然,不僅僅這一種情況,如果你執行以下的操作,都有可能找錯人:

  • refresh,不論你是主動重新整理還是頁面自動重新整理
  • back,已經跳轉到了其他頁面,然後你用driver.back()跳回來,這也是一張新的頁面了
  • 跳轉到了新的頁面,但這張新頁面上有一些元素跟之前頁面是長得一樣的,這也是一張新的頁面了。比如:一排分頁按鈕,你點選下一頁跳轉到了第二頁,想要還用原來的元素操作到下一頁,那也是不可能的了。

    除此之外可能還有其他的原因,總之你看到這類型長得差不多,但是對頁面有了操作的情況,就應該想想這種可能性了。

那遇到這種情況該怎麼辦?

很簡單:

隻要重新整理頁面之後重新擷取元素就行,不要提前擷取一組元素,然後去循環操作每一個元素,這種情況還是擷取元素的個數,然後在循環中擷取相應位置的元素,在用的時候才去擷取,這樣你就擷取到最新的id了,也不會出現找錯人的尴尬了。

總之一句話,遇到頁面有變化的情況,不要去循環元素,去循環個數或者定位方式,在循環中擷取元素。