【基于Python的Selenium2自动化测试】02 -Webdriver之元素定位

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013003827/article/details/85858927


说明:

WebDriver属于Selenium体系中用来操作浏览器的一套API,同时,WebDriver也是Python的一个用于实现Web自动化的第三方库。

首先来看一下百度首页的Web页面,如下:
在这里插入图片描述

在这张web页面上,我们看到有 输入框、按钮和文字链接,还有图片、页面底部的文字等。自动化要做的就是模拟鼠标和键盘来操作这些元素,或单击,或输入,或鼠标悬停等操作。

操作这些页面元素的前提就是要找到它们,自动化工具不可能像人一样可以通过肉眼就可以分辨这些元素,并且知道它们是干什么用的,那么自动化工具如何找到它们呢?

接下来我们通过前端工具来看一下这些元素的真实面目。

对于谷歌浏览器,我们只需要按 F12 就可以启用开发者工具查看页面元素,如下:
在这里插入图片描述
我们可以看到页面上的元素都是由一行行的代码组成的,它们之间是层级关系组织起来的,每个元素有不同的标签名和属性值。WebDriver就是通过这些信息来找到不同的元素的。

WebDriver提供了8种元素定位方法,在Python中,其对应的方法如下:

元素 方法
id name
class name tag name
link text partial link text
xpath css selector
find_element_by_id() find_element_by_name()
find_element_by_class_name() find_element_by_tag_name()
find_element_by_link_text() find_element_by_partial_tag_name()
find_element_by_xpath() find_element_by_css_selector()

下面是百度首页的前端代码(Chrome开发者工具查看所得)

<!--STATUS OK-->
<html>
   <head></head>
   <body link=”#0000cc”>
		<div data-for="result" id="swfEveryCookieWrap" style="width: 0px; height: 0px; overflow: hidden;">...</div>
		<script></script>
<div id="wrapper" style="display: block;">
			<script>
if(window.bds&&bds.util&&bds.util.setContainerWidth){bds.util.setContainerWidth();}
</script>
<div id=”head”>
	<div class=”head_wrapper”>
		<div class=”s_form”>
			<div class="s_form_wrapper soutu-env-nomac soutu-env-index">
				<div id="lg">
					<img hidefocus="true" src="//www.baidu.com/img/bd_logo1.png" width="270" height="129">
							</div>
							<a href="/" id="result_logo" onmousedown="return c({'fm':'tab','tab':'logo'})">
								<img src="//www.baidu.com/img/baidu_jgylogo3.gif" alt="到百度首页" title="到百度首页">
							</a>
							<form id="form" name="f" action="/s" class="fm">
								<input type="hidden" name="ie" value="utf-8">
								<input type="hidden" name="f" value="8">
								<input type="hidden" name="rsv_bp" value="0">
								<input type="hidden" name="rsv_idx" value="1">
								<input type="hidden" name="ch" value="">
								<input type="hidden" name="tn" value="baidu">
								<input type="hidden" name="bar" value="">
								<span class="bg s_ipt_wr quickdelete-wrap"> 
									<span class="soutu-btn"></span>
									<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">
									<a href="javascript:;" id="quickdelete" title="清空" class="quickdelete" style="top: 0px; right: 0px; display: none;"></a>
								</span>
								<span class="bg s_btn_wr">
									<input type="submit" id="su" value="百度一下" class="bg s_btn">
								</span>
……
	</body>
<html>

从上面的代码我们可以看到

  • 它们都是由标签组成:
<html></html>
<body></body>
<div></div>
<form></form>
……
  • 标签有各种属性
<div id=”head” class=”s_down”>
<from class=”well”>
<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">

就像人也会有各种属性一样,如身份证(id)、姓名(name)、职业(class)等

  • 标签对之间可以有文本数据:
<a>新闻</a>
<a>地图</a>
<a>视频</a>
<a>贴吧</a>
  • 标签有层级关系
<html>
	<body>
	</body>
</html>
<div>
	<form>
		<input />
	</form>
</div>

2.1 id定位

HTML规定id属性在HTML文档中必须是唯一的,这类似于公民的身份证号,具有很强的唯一性。
Webdriver提供的id定位方法就是通过元素的id属性来查找元素。

例如:通过id定位百度输入框与百度搜索按钮,
在这里插入图片描述

用法如下:

find_element_by_id(“kw”)
find_element_by_id(“su”)

说明: find_element_by_id()方法通过id属性来定位元素。

2.2 name定位

HTML规定name来指定元素的名称,因此它的作用就像是人的姓名。
name的属性值在当前页中可以不唯一

例如:通过name定位百度输入框,
在这里插入图片描述
用法如下:

find_element_by_name(“wd”)

说明: find_element_by_name()方法通过name属性来定位元素。
注意:由于百度搜索按钮并没有提供name属性,因此就不能通过name属性来定位它。

2.3 class定位

HTML规定class用来指定元素的类名。
例如:通过class属性来定位百度输入框和搜索按钮,
在这里插入图片描述

用法如下:

find_element_by_class_name(“s_ipt”)
find_element_by_class_name(“bg s_btn”)

说明: find_element_by_class_name()方法通过class属性来定位元素。

2.4 tag定位

HTML的本质就是通过tag来定义实现不同的功能,每个元素本质上就是一个tag
因为一个tag往往用来定义一类功能,所以通过tag识别某个元素的概率很低。

例如,我们打开任意一个页面,查看前端都会发现有大量的<div>、<input>、<a>tag,所以很难通过tag name去区分不同的元素。

例如:通过tag name去定位百度的输入框和搜索按钮,你会发现它们完全一样
在这里插入图片描述

用法如下:

find_element_by_tag_name(input)

说明: find_element_by_tag_name()方法通过元素的tag name来定位元素。

2.5 link定位

link专门用来定位文本链接。

例如:百度首页上的几个文本链接如下
在这里插入图片描述

其文本链接的代码如下:

<a href="http://news.baidu.com" name="tj_trnews" class="mnav">新闻</a>
<a href="http://www.hao123.com" name="tj_trhao123" class="mnav">hao123</a>
<a href="http://map.baidu.com" name="tj_trmap" class="mnav">地图</a>
<a href="http://v.baidu.com" name="tj_trvideo" class="mnav">视频</a>
<a href="http://tieba.baidu.com" name="tj_trtieba" class="mnav">贴吧</a>
<a href="http://xueshu.baidu.com" name="tj_trxueshu" class="mnav">学术</a>

根据上面的代码,我们发现,其实通过name属性来定位是一个更好的选择。不过这里为了演示link定位的使用,用法如下:

find_element_by_link_text(“新闻”)
find_element_by_link_text(“hao123”)
find_element_by_link_text(“地图”)
find_element_by_link_text(“视频”)
find_element_by_link_text(“贴吧”)
find_element_by_link_text(“学术”)

说明: find_element_by_link_text()方法通过元素标签对之间的文本信息来定位元素。

2.6 partial link定位

partial link定位是对link定位的一种补充,有些文本链接较长,这个时候可以取文本链接的一部分进行定位,只要这部分信息可以唯一的标识这个链接即可。
例如:

<a class="mnav" name=”tj_long” href=”#”>一个很长的文本链接</a>

通过partial link定位如下:

find_element_by_partial_link_text(“一个很长的”)
find_element_by_partial_link_text(“文本链接”)

说明: find_element_by_partial_link_text()方法通过元素标签对之间的部分文本信息来定位元素。

2.7 XPath定位

XPath是一种在XML文档中定位元素的语言。因为HTML可以看做XML的一种实现,所以Selenium用户可以使用XPath在web应用中来定位元素。

  • 方法1:绝对路径定位
    参考前面的前端展示的代码,我们可以通过下面的方法来定位到百度输入框和百度搜索按钮
find_element_by_xpath(/html/body/div/div/div/div/div/form/span/input)
find_element_by_xpath(/html/body/div/div/div/div/div/form/span[2]/input)

说明: find_element_by_xpath()方法使用XPath语言来定位元素。

XPath主要用标签名的层级关系来定位元素的绝对路径,最外层的是html语言。然后在body文本内,一级一级往下查找,如果一个层级下有多个相同的标签名,那么就按照上下顺序确定是第几个,例如span[2]表示当前层级下的第2个span标签。

  • 方法2:利用元素属性定位

同样以百度输入框和百度搜索按钮为例,用法如下:

find_element_by_xpath(//input[@id=’kw’])
find_element_by_xpath(//input[@id=’su’])

说明:
//表示当前页面下某个目录,input表示定位元素的标签名,[@id=’kw’]表示这个元素的id属性值等于kw

下面通过idnameclass属性值来定位,方法如下:

find_element_by_xpath(//input[@id=’kw’])
find_element_by_xpath(//input[@name=’wd’])
find_element_by_xpath(//input[@class=’s_ipt’])
find_element_by_xpath(//input[@class=’bg s_btn’])

说明: 如果不指定标签名,则也可以使用星号(*)来代替。
使用XPath不局限于idnameclass这三个属性值,元素的任意属性值都可以使用,只要它能唯一的标识这个元素。

例如:

find_element_by_xpath(//input[@maxlength=255])
find_element_by_xpath(//input[@autocomplete=’off’])
find_element_by_xpath(//input[@type=’submit’])
  • 方法3:层级与属性结合

如果一个元素本身没有可以唯一标识这个元素的属性值,那么我们可以找其上一级元素,如果它的上一级元素有可以唯一标识的属性值,也可以拿来使用。

还是以定位百度输入框和百度搜索按钮为例,用法如下:

find_element_by_xpath(//span [@class=’bg s_ipt_wr’]/input)
find_element_by_xpath(//span [@class=’bg s_btn_wr’]/input)

说明: span [@class=’bg s_ipt_wr’]通过class元素定位到父元素,后面的/input就是父元素下面的子元素。如果父元素没有可利用的属性值,那么可以继续向上找“爷爷”元素,如:

find_element_by_xpath(//form [@id=’form’]/span/input)
find_element_by_xpath(//form [@id=’form’]/span[2]/input)
  • 方法4:使用逻辑运算符
    如果一个属性不能唯一区分一个元素,我们可以使用逻辑运算符连接多个属性来定位元素。
…….
		<input id=”kw” class=”su” name=”ie”>
		<input id=”kw” class=”aa” name=”ie”>
		<input id=”bb” class=”su” name=”ie”>
…….

如上面的三行元素,假设我们现在要定位第一行的元素,如果使用id将会与第二行元素重名,如果使用class将会与第三行元素重名,而如果同时使用idclass就会唯一的标识第一行元素,这个时候就可以通过逻辑运算符“and”来连接这两个条件,用法如下:

find_element_by_xpath(//input[@id=’kw’ and class=’su’])

2.8 CSS定位

CSS(Cascading Style Sheets)是一种语言,它用来描述HTML和XML文档的表现。CSS使用选择器来为页面元素绑定属性。

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”的所有元素

下面同样以百度输入框和百度搜索按钮为例介绍CSS定位的用法

……
     <span class="bg s_ipt_wr quickdelete-wrap"> 
			<span class="soutu-btn"></span>
			<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">
			<a href="javascript:;" id="quickdelete" title="清空" class="quickdelete" style="top: 0px; right: 0px; display: none;"></a>
		</span>
		<span class="bg s_btn_wr">
			<input type="submit" id="su" value="百度一下" class="bg s_btn">
		</span>
……

1)通过class属性定位
find_element_by_css_selector(“.s_ipt”) //选择class=“s_ipt”的元素,即百度输入框
find_element_by_css_selector(“.bg s_btn”) //选择class=“bg s_btn”的元素,即百度搜索按钮

2)通过id属性定位
find_element_by_css_selector(“#kw”)//选择id=“kw”的元素,即百度输入框
find_element_by_css_selector(“#su”) //选择id=“su”的元素,即百度搜索按钮

3)通过标签名定位

find_element_by_css_selector(“input”)

说明:
在CSS中,用标签名定位元素不需要任何标识符号,直接使用标签名即可。但我们在前面已经了解到,标签名重复的概率非常大,所以直接通过标签名定位的方式很难准确找到我们想要的元素。

4)通过父子关系定位

find_element_by_css_selector(“span>input”)

说明:
上面的写法表示有父元素,其父元素的标签名为span,查找它的所有标签名为input的子元素。

5)通过属性定位

find_element_by_css_selector([autocomplete=off])
find_element_by_css_selector([name=’kw’])
find_element_by_css_selector([type=”submit”])

说明:
在CSS中,对于属性值来说,可加引号,也可以不加引号,但注意和整个字符串的引号进行区分。

6)组合定位
组合定位就是将前面的定位方式组合起来使用

find_element_by_css_selector(“form.fm>span>input.s_ipt”)
find_element_by_css_selector(“form#form>span>input#kw”)

说明:
对于第一行,我们要找的这个元素的标签名为input,这个元素的class属性值为s_ipt;并且它有一个父元素,其标签名为span,它的父元素还有父元素,其标签名为form,而且form元素的class属性值为fm

对于第二行,我们要找的这个元素的标签名为input,这个元素的id属性值为kw;并且它有一个父元素,其标签名为span,它的父元素还有父元素,其标签名为form,而且form元素的id属性值为form

从上面的两行描述,我们看到我们要找的这个元素就是百度输入框。

2.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.SELECTOR,”span.bg s_btn_wr>input#su”)

说明:
find_element()方法只用于定位元素。它需要两个参数,第一个参数是定位的类型,由By提供;第二个参数是定位的具体方式。

在使用By之前需要导入By类,如下:

from selenium.webdriver.common.by import By

最后我们以定位百度输入框为例,写一段代码如下:

#coding=utf-8

from selenium import webdriver
import time

driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
time.sleep(2)

#########百度输入框的定位方式##########

#通过id方式定位
driver.find_element_by_id("kw").send_keys("python ")

#通过name方式定位
driver.find_element_by_name("wd").send_keys("selenium ")

#通过class name 方式定位
driver.find_element_by_class_name("s_ipt").send_keys("java ")

#通过CSS方式定位
driver.find_element_by_css_selector("#kw").send_keys("C++ ")

#通过xpath方式定位
driver.find_element_by_xpath("//input[@id='kw']").send_keys("JavaScript ")

driver.find_element_by_id("su").click()
time.sleep(10)
driver.quit()

运行结果如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/u013003827/article/details/85858927