需求:如今有一個網站的頁面,我但願用python自動化的測試點擊這個頁面上全部的在本窗口跳轉,而且是本站內的連接,前往到連接頁面以後在經過後退返回到原始頁面。python
要完成這個需求就必須實現3點:web
1. 找到原始頁面上面全部的在本窗口內跳轉的連接oop
2. 跳轉到目標頁面以後,「後退」到原始頁面測試
3. 在原始頁面上繼續點擊後續的連接網站
首先,要找到頁面上的全部連接並不困難。selenium爲咱們提供了find_elements_by_tag_name方法。咱們只須要在初始化webdriver以後,調用google
driver.find_elements_by_tag_name("a")
就能找到頁面上的全部a標籤。url
咱們能夠對全部的a標籤進行點擊,可是這樣的話咱們不能保證全部的a標籤所指向的目標頁面都是站內的,有可能目標是其餘的站外網頁;另外這樣也不能保證該跳轉頁面是在本窗口跳轉而不是新開一個窗口。spa
解決辦法:code
使用selenium.webdriver.remote.webelement.WebElement提供的get_attribute方法。blog
經過get_attribute拿到該a標籤的各類屬性,經過判斷找到符合要求的元素進行點擊。
get_attribute("href") 獲得a標籤對應的目標頁面的URL,對URL進行判斷就能夠了解到該頁面是否站內頁面。咱們能夠知道,若是是站內頁面的話這個屬性通常會是一個相對路徑,或者包含了本站域名,但若是是站外頁面的話,那它必定是包含了「http」的一個url。
get_attribute("target")若是target不是"_blank"的話,能夠判斷該頁面是在本窗口跳轉的。
跳轉到下一頁面後如何返回原始頁面呢?
selenium webdriver 提供了back方法能夠輕鬆的達到這個目標:driver.back()
最後,須要在返回了原始頁面以後繼續點擊下一個連接進行測試,這個不用說確定要使用for loop:
for i in range(0, len(driver.find_elements_by_tag_name("a"))):
在python中,若是咱們指定i在range(0, x)中循環時,會以1爲步長來遍歷從0到(x-1)的序列。例如:range(0,5)會獲得[0, 1, 2, 3, 4]。當咱們想更改range的步長時,則須要爲range方法提供第三個參數。例如:range(0,5,2),則會以2爲步長,獲得[0,2,4]這個序列。
另外,咱們也可使用相似C#中foreach的方法:
for targetLink in driver.find_elements_by_tag_name("a"):
這種方法一樣能夠遍歷全部的a標籤集合中的全部元素。
若是使用第二種方法,咱們以爲這個需求能夠簡單的實現爲:
links = driver.find_elements_by_tag_name("a") for link in links: if not "_blank" in link.get_attribute("target") and ("google" in link.et_attribute("href") or not "http" in link.get_attribute("href")): link.click() driver.back()
可是這樣的實如今運行時會拋出異常:
selenium.common.exceptions.StaleElementReferenceException: Message: u'Element not found in the cache - perhaps the page has changed since it was looked up'
異常的說明已經很明顯了:在cache中找不到元素,在元素被找到以後頁面變換了。 這就說明,噹噹前頁面發生跳轉以後,存在cache中的關於這個頁面的元素也被清空了。
所以,咱們須要在每次回到原始頁面以後對咱們感興趣的a標籤元素從新搜索,同時咱們又必須接着上次的點擊到的元素繼續點擊。所以咱們使用第一種遍歷的方法來實現這個for loop:
length = len(driver.find_elements_by_tag_name("a") for i in range(0,length): links = driver.find_elements_by_tag_name("a") link = links[i] if not ("_blank" in link.get_attribute("target") or "http" in link.get_attribute("href")): link.click() driver.back()
這樣,在每次返回頁面以後會從新搜索一遍頁面上的a元素,而後使用cache中的i繼續點擊下一個跳轉連接。