selenium之 坑:點擊后頁面刷新重新獲取刷新前的頁面(StaleElementReferenceException: Message: Element not found in the cache...)


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

 

我們來試試看:

代碼:

 

  1.  
    # -*- coding: utf-8 -*-
  2.  
     
  3.  
    from selenium import webdriver
  4.  
     
  5.  
    driver = webdriver.Firefox()
  6.  
    driver.get( 'http://www.baidu.com')
  7.  
     
  8.  
    print driver.find_element_by_id('kw') # kw before refresh
  9.  
     
  10.  
    driver.refresh() # refresh
  11.  
     
  12.  
    print driver.find_element_by_id('kw') # kw after refresh
  13.  
     
  14.  
    driver.quit()

結果:

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

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

  1.  
    # -*- coding: utf-8 -*-
  2.  
     
  3.  
    from selenium import webdriver
  4.  
     
  5.  
    driver = webdriver.Firefox()
  6.  
    driver.get( 'http://www.baidu.com')
  7.  
     
  8.  
    kw = driver.find_element_by_id( 'kw') # 先定位並獲得kw元素
  9.  
    kw.click()
  10.  
     
  11.  
    driver.refresh() # refresh
  12.  
     
  13.  
    kw.click() # 刷新后,仍用原來的kw元素操作,這時會報錯
  14.  
     
  15.  
    driver.quit()

結果:

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

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

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

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

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

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

很簡單:

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

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

解決方法示例:

錯誤寫法:

all_a = driver.find_elements_by_class('classname')
for a in all_a:
a.click()
...
這樣就容易點擊了第一個a之后,頁面出現刷新的情況,再想點第二個就會報這個錯
可以改成:
counts_a = len(driver.find_elements_by_class('class name'))
for i in range(counts_a):
driver.find_element_by_xpath('//a[@class="class name"][i+1]').click()
可能會更好一些,當然,也有其他的寫法,大概意思就是需要在刷新后重新去定位一次,再用重新定位到的元素去操作

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM