前言
selenium定位一組元素,批量操作循環點擊的時候會報錯:Element not found in the cache - perhaps the page has changed since it was looked up
實現目標:批量點擊標題,獲取每個頁面的url地址
代碼如下:
# coding:utf-8
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("https://www.cnblogs.com/yoyoketang/")
all = driver.find_elements_by_css_selector(".postTitle2")
for i in all:
i.click()
print(driver.current_url) # 打印當前頁url
driver.back()
運行結果:
http://www.cnblogs.com/yoyoketang/p/7259993.html
Traceback (most recent call last):
selenium.common.exceptions.StaleElementReferenceException: Message: Element not found in the cache - perhaps the page has changed since it was looked up
這里不少人就會問了:
- “為什么第一次點擊可以,for循環第二次點擊就不行了呢?”
由於第一次點擊后,頁面刷新了,我們可以手工點擊的時候,注意觀察頁面,頁面是有刷新動作的。
- “為什么明明定位到了,點擊會報錯呢?”
頁面刷新后元素的屬性是沒變,但是element卻變了,所有之前定位的元素element都過期了。
- “那么如何實現呢?”
如何實現,這個才是本篇重點要講的。
分析問題
1.當頁面上有點擊行為的時候,頁面是會刷新的,為了模擬頁面刷新后查看元素是不是會變,我們可以用refresh刷新頁面,然后查看刷新前后元素的變化。
# coding:utf-8
from selenium import webdriver
import time
driver = webdriver.Firefox()
driver.get("https://www.cnblogs.com/yoyoketang/")
all = driver.find_elements_by_css_selector(".postTitle2")
print(all) # 刷新前
driver.refresh()
all_new = driver.find_elements_by_css_selector(".postTitle2")
print(all_new) # 刷新后
運行結果:
[<selenium.webdriver.remote.webelement.WebElement (session="36801e98-3a57-41b1-a58e-021fe925fd57", element="{88a2f797-3833-4ea4-a734-72c5c59800ff}")>, <selenium.webdriver.remote.webelement.WebElement (session="36801e98-3a57-41b1-a58e-021fe925fd57", element="{529248de-6ca0-43d9-8747-34d7dad28c6c}")>,
...后面太長省略了]
2.很明顯element里面的值發生了變化,所以第一次點擊是可以點的,點完之后,頁面刷新了,然后頁面上的元素已經發生變化了,第二次循環的時候還是用刷新前的元素去定位點擊的,自然就會報錯了。
解決方案
1.針對頁面刷新后,之前的元素失效問題,在for循環體里面可以重新定位一次,覆蓋掉之前舊的就行了。
2.第一次獲取全部元素后,通過len函數獲取總個數
3.for循環的時候不要循環定位元素的list對象,換成range函數去循環
4.參考代碼如下:
# coding:utf-8
from selenium import webdriver
import time
driver = webdriver.Firefox()
driver.get("https://www.cnblogs.com/yoyoketang/")
all = driver.find_elements_by_css_selector(".postTitle2")
s = len(all)
print(u"獲取總個數:%s"%s)
for i in range(s):
all[i].click()
time.sleep(2)
url = driver.current_url
print(u"獲取當前頁面url:%s"%url)
driver.back() # 點完之后返回
# 重新獲取一次元素
all = driver.find_elements_by_css_selector(".postTitle2")
運行結果: