元素定位
操作页面元素之前,首先要对元素进行定位,所以定位是自动化脚本编写的开始。
通常使用find_element或find_elements方法来定位元素。
1、find_element使用给定的方法定位和查找一个元素
2、find_elements使用给定的方法定位和查找所有元素list
常用定位方式共八种:
1.当页面元素有id属性时,最好尽量用by_id来定位。
2.XPath很强悍,但定位性能不是很好,所以还是尽量少用。如果确实少数元素不好定位,那还是选择XPath或cssSelector。
3.当有链接需要定位时,可以考虑使用by_link_text或by_partial_link_text。
现分别介绍如下。
1、by_id
当所定位的元素具有id属性的时候我们可以通过by_id来定位该元素。
例如打开百度首页,定位搜索框后输入Selenium。
搜索框页面源代码:属性id值为kw
脚本代码:
代码语言:javascript复制#!/usr/bin/env python
# -*- coding: utf-8 -*-
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
element = driver.find_element_by_id("kw")
element.send_keys("Selenium")
2、by_name
当所定位的元素具有name属性的时候我们可以通过by_name来定位该元素。
例如打开百度首页,定位搜索框后输入Selenium。
搜索框页面源代码:属性name值为wd
脚本代码:
代码语言:javascript复制#!/usr/bin/env python
# -*- coding: utf-8 -*-
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
element = driver.find_element_by_name("wd")
element.send_keys("Selenium")
3、by_class_name
当所定位的元素具有class属性的时候我们可以通过by_class_name来定位该元素。
例如打开百度首页,定位搜索框后输入Selenium。
搜索框页面源代码:属性class值为s_ipt
脚本代码:
代码语言:javascript复制#!/usr/bin/env python
# -*- coding: utf-8 -*-
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
element = driver.find_element_by_class_name("s_ipt")
element.send_keys("Selenium")
4、by_tag_name
by_tag_name方法可以通过元素的标签名来查找元素。由于搜索到的标签名通常不止一个,所以一般结合使用find_elements方法来使用。
例如打开百度首页,获取超链接地图的文本信息。从图中可以看到标签名为a的很多,无法精确定位,需要结合name属性才能过滤出我们要的元素。
超链接地图源代码:标签名为a,属性name值为tj_trmap
<< span="">a class="mnav" name="tj_trmap" href="http://map.baidu.com">地图a>
脚本代码:
代码语言:javascript复制#!/usr/bin/env python
# -*- coding: utf-8 -*-
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
a = driver.find_elements_by_tag_name("a")
# 打印标签名为a的个数
print(len(a))
for e in a:
if e.get_attribute("name") == "tj_trmap":
# 打印标签名为a,name属性值为tj_trmap的文本信息
print(e.text)
5、by_link_text
by_link_text通过超文本链接上的文字信息来定位元素,这种方式一般专门用于定位页面上的超文本链接。
例如打开百度首页,定位点击超链接地图。
超链接地图源代码:链接文本值为”地图”
<< span="">a class="mnav" name="tj_trmap" href="http://map.baidu.com">地图a>
脚本代码:
代码语言:javascript复制#!/usr/bin/env python
# -*- coding: utf-8 -*-
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
element = driver.find_element_by_link_text("地图")
element.click()
6、by_partial_link_text
当你不能准确知道超链接上的文本信息或者只想通过一些关键字进行匹配时,可以使用by_partial_link_text这个方法来通过部分链接文字进行匹配。
例如打开百度首页,定位点击超链接地图。
超链接地图源代码:链接文本值为”地图”,在代码里用”地”进行匹配
<< span="">a class="mnav" name="tj_trmap" href="http://map.baidu.com">地图a>
脚本代码:
代码语言:javascript复制#!/usr/bin/env python
# -*- coding: utf-8 -*-
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
element = driver.find_element_by_partial_link_text("地")
element.click()
7、by_css_selector
by_css_selector通过CSS查找元素,这种元素定位方式跟by_xpath比较类似,Selenium官网的Document里极力推荐使用CSS locator,而不是XPath来定位元素,原因是CSS locator比XPath locator速度快,特别是在IE下比XPath更高效更准确更易编写,对各种浏览器支持也很好。
by_css_selector常用定位:
1、根据tagName
driver.find_element_by_css_selector("input") html标签
2、根据ID
driver.find_element_by_css_selector("input#username") html标签和#id
driver.find_element_by_css_selector("#username") #id
3、根据className
单一class:driver.find_element_by_css_selector(".username") .class
复合class:driver.find_element_by_css_selector(".username.**.***") .classA.classB.classC
4、根据元素属性
1)精准匹配:
driver.find_element_by_css_selector("input[name=username]") 属性名=属性值,id、class等都可以写成这种形式
driver.find_element_by_css_selector("img[alt]") 存在属性。例如img元素存在alt属性
driver.find_element_by_css_selector("input[type='submit'][value='Login']") 多属性
2)模糊匹配(正则表达式匹配属性):
^= driver.find_element_by_css_selector("input[id ^='ctrl']") 匹配到id头部,如ctrl_12
= driver.find_element_by_css_selector("input[id
*= driver.find_element_by_css_selector("input[id *= 'ctrl']") 匹配到id中间,如1_ctrl_12
5、查询子元素,如图所示html
1)子元素 A>B
myInput = driver.find_element_by_css_selector("form>span>input") 搜索输入框
2)后代元素 A空格B
myInput = driver.find_element_by_css_selector("form input") 搜索输入框
3)第一个后代元素 :first-child
mySpan = driver.find_element_by_css_selector("form :first-child") 冒号前有空格,定位到form下所有级别的第一个子元素,可定位到三个元素:
mySpan = driver.find_element_by_css_selector("form input:first-child") 冒号前无空格,定位到form下所有级别的第一个input元素,可定位到两个元素:
mySpan = driver.find_element_by_css_selector("form>span:first-child") 冒号前无空格,定位到form直接子元素中的第一个span元素,可定位到一个元素:
4)最后一个子元素 :last-child [类同:first-child]
userName = driver.find_element_by_css_selector("form :last-child") 冒号前有空格,定位到form下所有级别的第一个子元素
5)第N个子元素 :nth-child(N) [类同:first-child]
userName = driver.find_element_by_css_selector("form#form :nth-child(2)") 冒号前有空格,定位到form下所有级别的第二个子元素
6、查询兄弟元素
driver.find_element_by_css_selector("form#form span span") 定位到a 再定位到和它相邻的b
简单示例:打开百度首页,定位搜索框后输入Selenium。打开Firefox后,开启FirePath,选择CSS对元素进行定位。
搜索框页面源代码:
脚本代码:
代码语言:javascript复制#!/usr/bin/env python
# -*- coding: utf-8 -*-
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
element = driver.find_element_by_css_selector("#kw")
element.send_keys("Selenium")
cssSelector教程可访问官网:http://www.w3.org/TR/css3-selectors/
或者可以查看本书的cssSelector参考手册章节
8、by_xpath
by_xpath这个方法是非常强大的元素查找方式,使用这种方法几乎可以定位到页面上的任意元素。什么是XPath?XPath是XML Path的简称,是一门在XML文档中查找信息的语言,由于HTML文档本身就是一个标准的XML页面,所以XPath在XML文档中通过元素和属性进行导航。
下图页面源码示例,来讲解XPath语法:
绝对路径写法(只有一种),写法如下:
引用页面上的form元素(即源码中的第3行):/html/body/form[1]
注意:
1.元素的XPath绝对路径可通过Firefox的FirePath直接查询。
2.一般不推荐使用绝对路径的写法,因为一旦页面结构发生变化,该路径也随之失效,必须重新写。
3.绝对路径以单/号表示,而下面要讲的相对路径则以//表示,这个区别非常重要。
4.当XPath的路径以/开头时,表示让XPath解析引擎从文档的根节点开始解析。当XPath路径以//开头时,则表示让XPath引擎从文档的任意符合的元素节点开始进行解析。而当/出现在XPath路径中时,则表示寻找父节点的直接子节点,当//出现在XPath路径中时,表示寻找父节点下任意符合条件的子节点,不管嵌套了多少层级。弄清这个原则,就可以理解其实XPath的路径可以绝对路径和相对路径混合在一起来进行表示。
下面是相对路径的写法:
查找页面根元素://
查找页面上所有的input元素://input
查找页面上第一个form元素://form[1]
查找页面上第一个form元素内的第一个子input元素://form[1]/input[1]
查找页面上第一个form元素内的所有子input元素://form[1]//input
查找页面上id为formID的form元素://form[@id='formID']
查找页面上具有name属性为nameaaa的input元素://input[@name='nameaaa']
查找页面上id为formID的form元素下的第一个input元素://form[@id='formID']/input[1]
查找页面具有name属性为nameddd并且type属性为button的input元素://input[@name='nameddd'][@type='button']
查找页面上id为formID的form元素下第4个input元素://form[@id='formID']/input[4]
前面讲的都是XPath中基于准确元素属性的定位,其实XPath也可以用于模糊匹配。
如下面源码示例:
这段代码中的“订餐”这个超链接,没有标准id元素,只有一个rel和href,不是很好定位。接下来使用XPath的几种模糊匹配模式来定位它吧,主要有三种方式:
1.用contains关键字,定位代码如下:
driver.find_element_by_xpath("//a[contains(@href, 'order')]")
这句话的意思是寻找页面中href属性值包含有order这个单词的所有a元素,由于这个“订餐”按钮的href属性里肯定会包含order,所以这种方式是可行的,也会经常用到。其中@后面可以跟该元素任意的属性名。
2.用start-with,定位代码如下:
driver.find_element_by_xpath("//a[starts-with(@rel, 'mi')]")
这句的意思是寻找rel属性以mi开头的a元素。其中@后面的rel可以替换成元素的任意其他属性。
3.用Text关键字,定位代码如下:
driver.find_element_by_xpath("//*[text()='茶']")
直接查找页面中所有的“茶”,根本就不用知道它是个li元素。这种方法也经常用于纯文字的查找。
另外,也可以用contains关键字进行模糊匹配,比如查找“咖啡”
driver.find_element_by_xpath("//li[contains(text(), '咖')]")
实际项目上用到的示例:
代码语言:javascript复制driver.find_element_by_xpath("//a[@name='tj_trmap' and ancestor::div[@id='u1']]")
driver.find_element_by_xpath("//input[preceding-sibling::input[@name='f']]")
driver.find_element_by_xpath("//input[following-sibling::input[@name='f']]")
driver.find_element_by_xpath("//span[contains(text(),'删 除') and ancestor::div[@id='_dvModuleContainer_mbox.ListModule_0']]")
driver.find_element_by_xpath("//span[contains(text(),'删 除') and ancestor::div[contains(@id, '_dvModuleContainer_mbox.ListModule')]]")
driver.find_element_by_xpath("//div[preceding-sibling::div/div/a[contains(text(),'苹果')]]/a[text()='删除']")
driver.find_element_by_xpath("//span[text()='平台(人工岛)基础信息维护']")
driver.find_element_by_xpath("//li[descendant::div[preceding-sibling::div[contains(text(), 'Chaturbate')]]][last()-2]//div[contains(text(),'Someone you')]")
driver.find_element_by_xpath("//b[@title='未读']/preceding-sibling::label/span/b") 向前找
driver.find_element_by_xpath("//span[text()='u6536u4EF6u7BB1']/following-sibling::strong") 向后找
driver.find_element_by_xpath("//span[contains(text(),'种类')]/following::a[contains(text(),'查看')]")
driver.find_element_by_xpath("//span[last()-1]")
driver.find_element_by_xpath("//span[2]") 索引
driver.find_element_by_xpath("//span[substring(@name,3,5)='bruce']") 返回第一个参数中从第二个参数指定的位置开始、第三个参数指定的长度的子字符串
简单示例:打开百度首页,定位搜索框后输入Selenium。打开Firefox后,开启FirePath,选择XPath对元素进行定位。
搜索框页面源代码:
脚本代码:
代码语言:javascript复制#!/usr/bin/env python
# -*- coding: utf-8 -*-
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
element = driver.find_element_by_xpath(".//*[@id='kw']")
element.send_keys("Selenium")
最后,关于XPath这种定位方式,Selenium会将整个页面的所有元素进行扫描以定位我们所需要的元素,所以这是一个非常费时的操作,如果你的脚本中大量使用XPath做元素定位的话,将导致你的脚本执行速度大大降低,所以请慎用。
XPath教程可访问:http://www.w3school.com.cn/xpath/index.asp
或者可以查看本书的XPath参考手册章节
- End -