我们在使用selenium进行自动化测试中,如果想要操作web页面的元素,首先需要定位元素的位置,下面开始学习在selenium中如何进行元素的定位。
1.定位方法详细说明
(1)使用id定位
每一个HTML页面中每一个ID值都是唯一的,使用此方法可以唯一定位到元素的位置,如下代码片段是百度搜索框中代码,我们可以通过id属性定位搜索框。
<span class="bg s_ipt_wr quickdelete-wrap"> <span class="soutu-btn"></span> <input id="kw" class="s_ipt" autocomplete="off" maxlength="255" value="" name="wd"> <a id="quickdelete" class="quickdelete" href="javascript:;" title="清空" style="top: 0px; right: 0px; display: none;"></a> </span> <span class="bg s_btn_wr"> <input id="su" class="bg s_btn" type="submit" value="百度一下"> </span>
使用如下程序进行定位百度搜索输入框:
driver.find_element_by_id("kw").send_keys("selenium") # 在百度搜索文本框中输入selenium
(2)使用name定位
在HTML页面中用name属性来设置属性的名称,使用此方法定位元素,定位到的元素可能不唯一,因为每一个HTML页面中,会有多个相同的name值,如我们可以使用name属性定位百度搜索输入框:
1 driver.find_element_by_name("wd").send_keys("selenium") # 在百度搜索文本框中输入selenium
(3)使用class定位
在HTML页面中用class属性来设置类名,使用此方法定位元素,定位到的元素可能不唯一,因为每一个HTML页面中,会有多个相同的class值,如我们可以使用class属性定位百度搜索输入框:
1 driver.find_element_by_class_name("s_ipt").send_keys("selenium") # 在百度搜索文本框中输入selenium
(4)使用链接的全部文字定位
如下代码为百度首页右上角的HTML片段:
通过元素标签中间的文本定位元素:
1 driver.find_element_by_link_text("新闻").click() # 点击新闻链接
该方法主要用来定位文本链接。
(5)使用链接的部分文字定位元素
有时元素标签中间的文本比较多,我们可以选择部分文字内容进行定位:
1 driver.find_element_by_partial_link_text("新").click() # 点击新闻链接
(6)使用标签名定位
此种方法定位的元素可能不止一个,实际使用中要主要,使用如下代码定位百度搜索输入框:
1 driver.find_element_by_tag_name("input").send_keys('selenium') # 百度搜索输入框中输入selenium
(7)使用cssSelector选择器定位元素(推荐)
WebDriver提供了find_element_by_css_selector方法,该方法使我们可以使用css定位网页元素,与xpath表达式定位元素相比,css表达式定位元素效率更高。
选择器 | 例子 | 描述 |
.class | .intro | class 选择器,选择class="intro"的所有元素 |
#id | #firstname | id 选择器,选择id="firstname"的所有元素 |
* | * | 选择所有元素 |
element | p | 选择所有<p>元素 |
element > element | div > input | 选择父元素为<div>的所有<input> 元素 |
element + element | div + input | 选择同一级中紧接在<div> 元素之后的所有<input> 元素 |
[attribute=value] | [target=_blank] | 选择 target="_blank" 的所有元素 |
a.使用绝对路径定位
按照html的根节点,一层一层的寻找,直到找到定位的元素位置,如想要定位type属性为button的input标签,该标签在html>body>div下,可以通过如下的Python定位语句进行定位:
1 driver.find_element_by_css_selector("html>body>div>input[type='button']")
b.使用相对路径定位
在实际的使用过程中,绝对定位比较冗长,使用比较多的还是相对路径定位,如我们想要定位type属性为button的input标签,可以使用如下Python定位语句进行定位:
1 driver.find_element_by_css_selector("input[type='button']")
但是上面的css表达式定位出来的元素可能有多个,我们只能获取到第一个,为了更准确的定位元素,我们可以结合该元素的其他属性来实现精确定位的目的:
1、结合id来定位,driver.find_element_by_css_selector("input#kw"),在标签与id之间使用#连接,另外该方法也可简写为driver.find_element_by_css_selector("#kw"), 有点儿类似于id选择器。
2、结合class定位,driver.find_element_by_css_selector("input.s_ipt"),在标签名与class名之间使用.连接。
3、使用元素的任何属性来定位元素,driver.find_element_by_css_selector("标签名[属性名=属性值]")。
4、匹配部分属性值
符号 | 示例 | 说明 |
^ | driver.find_element_by_css_selector("标签名[属性名^=XXX]") | 匹配属性值以xxx开头的元素 |
$ | driver.find_element_by_css_selector("标签名[属性名$=XXX]") | 匹配属性值以xxx结尾的元素 |
* | driver.find_element_by_css_selector("标签名[属性名*=XXX]") | 匹配属性值包含xxx的元素 |
driver.find_element_by_css_selector("input[id='kw']").send_keys("selenium") # 百度搜索输入矿中输入selenium driver.find_element_by_css_selector("input[value^='百度']").click() # 点击百度搜索按钮,使用匹配部分属性值,value属性值以"百度"开头
driver.find_element_by_css_selector("input[id='kw']").send_keys("selenium") # 百度搜索输入矿中输入selenium driver.find_element_by_css_selector("input[value$='一下']").click() # 点击百度搜索按钮,使用匹配部分属性值,value属性值以一下结尾
driver.find_element_by_css_selector("input[id='kw']").send_keys("selenium") # 百度搜索输入矿中输入selenium driver.find_element_by_css_selector("input[value*='度一']").click() # 点击百度搜索按钮,使用匹配部分属性值,value属性值包含度一
c.使用相对路径和绝对路径并用的方法
driver.find_element_by_css_selector("div#password>input"), 该方法中“div#password>input” 首先通过相对路径定位到id为password的div元素,然后查找其子元素input(绝对路径)。
d.使用伪类定位元素
driver.find_element_by_css_selector("div#div1 :first-child") //查找id属性值为div1的div元素下的第一个元素,:first-child表示查找某个元素里面的第一个元素 driver.find_element_by_css_selector("div#div1 :nth-child(2)") //查找id属性值为div1的div元素下的第二个元素,:nth-child(2)表示查找某个元素里面的第二个子元素 driver.find_element_by_css_selector("div#div1 :last-child") //查找id属性值为div1的div元素下的最后一个元素,:last-child表示查找某个元素里面的最后一个子元素
注意:这3个CSS实例表达式“:”前面一定要加一个空格。
e.查找同级兄弟页面元素
driver.find_element_by_css_selector("div#div1 > input + a") //在id属性值为div1的div元素下,查找input元素后面的同级链接元素 driver.find_element_by_css_selector("div#div1 > input + a + img") //在id属性值为div1的div元素下,查找input元素和链接元素后面的同级图片元素 driver.find_element_by_css_selector("div#div1 > input+ * + img") //在id属性值为div1的div元素下,查找input元素和某种类型页面元素后面的同级图片元素,*表示任意类型元素
(8)使用xpath定位元素
xpath表达式与css表达式定位元素相比,性能较低,其中/代表绝对路径,//代表相对定位。当XPath的路径以/开头时,表示让XPath解析引擎从文档的根节点开始解析。当XPath路径以//开头时,则表示让XPath引擎从文档的任意符合的元素节点开始进行解析。而当/出现在XPath路径中时,则表示寻找父节点的直接子节点,当//出现在XPath路径中时,表示寻找父节点下任意符合条件的子节点,不管嵌套了多少层级。
a.使用绝对路径来定位元素
Python定位语句:driver.find_element_by_xpath("/html/body/div/input[@value='查询']") # 在html/body/div下,查找value属性值为"查询"的input元素。
b.使用相对路径来定位元素
Python定位语句:driver.find_element_by_xpath("//input[@value='查询']") #查找value属性值为"查询"的input元素。
说明:实际的工作中,绝对路径用的比较少,用的多的是相对路径定位元素。
c.使用索引号进行定位
Python定位语句:driver.find_element_by_xpath("//div[2]/input[2]") # 查找页面中第二个div元素下的第二个input元素。
d.使用页面元素的属性值定位元素
Python定位语句:driver.find_element_by_xpath("//img[@alt='img1'") # 查找alt属性值为img1的图片元素。
e.使用模糊的属性定位元素
XPath函数 |
定位表达式实例 |
表达式解释 |
starts-with() |
//img[starts-with(@alt,’div1’)] |
查找alt属性以"div1"开始的图片元素 |
contains() |
//img[contains(@alt,’g1’)] |
查找alt属性包含“g1”关键字的图片元素 |
f.使用元素的文本来定位元素
text()函数可以定位到包含某些关键字的元素。
xpath表达式:
a)//a[text()='百度搜索']
b)//a[contains(text(),'百度')]
c)//a[contains(text(),'百度')]/preceding::div
说明:
a) 表示要查找包含“百度搜索”的链接元素,使用的是精确匹配方式,一个字不能多,一个字不能少。
b) 表示搜索包含“百度”两个字的链接元素,实现了根据部分文字内容进行匹配。
c) 表示在包含“百度”两个字的链接元素的前面查找div元素。
g.使用逻辑运算符
driver.find_element_by_xpath("//input[@id='username' and @name='userid']")
h.使用任意属性值匹配元素
driver.find_element_by_xpath("//input[@*='username']")
(9)用By 定位元素
针对前面介绍的8种定位方法,WebDriver 还提供了另外一套写法,即统一调用find_element()方法,通过By 来声明定位,并且传入对应定位方法的定位参数,具体如下。
find_element(By.ID,"kw") find_element(By.NAME,"wd") find_element(By.CLASS_NAME,"s_ipt") find_element(By.TAG_NAME,"input") find_element(By.LINK_TEXT,"新闻") find_element(By.PARTIAL_LINK_TEXT,"新") find_element(By.XPATH,"//*[@class='bg s_btn']") find_element(By.CSS_SELECTOR,"span.bg s_btn_wr>input#su")
find_element()方法只用于定位元素,它需要两个参数。第一个参数是定位的类型,由By提供;第二个参数是定位的值,在使用By之前需要先导入:
from selenium.webdriver.common.by import By
通过查看 WebDriver 的底层实现代码可以发现,它们其实是一回事儿。