需求:如今有一个网站的页面,我但愿用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继续点击下一个跳转连接。