4.Selenium Python元素定位


元素定位

我们有许多方法对页面的元素进行定位,你可以根据自己的需要选择最合适的一种。Selenium提供了下面的方法进行元素定位: find_element_by_id find_element_by_name find_element_by_xpath find_element_by_link_text find_element_by_partial_link_text find_element_by_tag_name find_element_by_class_name find_element_by_css_selector

寻找多个元素(下列方法会返回一个list,其余使用方式相同):find_elements_by_name find_elements_by_xpath find_elements_by_link_text find_elements_by_partial_link_text find_elements_by_tag_name find_elements_by_class_name * find_elements_by_css_selector

除了上面这些公有的方法,我们还有2个私有的方法来帮助页页面对象的定位。这两个方法就是find_elementfind_elements:

from selenium.webdriver.common.by import By

driver.find_element(By.XPATH,'//button[text()="Some Text"]')
driver.find_elements(By.XPATH,'//button')

By类的可用属性如下:

ID = "id"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
NAME = "name"
TAG_NAME = "tag_name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"

根据Id定位

如果你知道元素的id属性,那么就使用id定位吧。在id定位里,会返回第一个id属性匹配的元素,如果没有元素匹配,会抛出NoSuchElementException异常。

举个例子,我们来看一个页面:

<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
  </form>
 </body>
<html>

我们可以这样定位表单元素form:

login_form = driver.find_element_by_id('loginForm')

根据 Name 定位

如果你知道元素的name属性,那么就用这个定位吧。在name定位里,会返回第一个name属性匹配的元素,如果没有元素匹配,会抛出NoSuchElementException异常。

举例我们再来看一个页面:

<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
   <input name="continue" type="button" value="Clear" />
  </form>
</body>
<html>

username 和 password元素 可以这样定位:

username = driver.find_element_by_name('username')
password = driver.find_element_by_name('password')

下面这个操作会返回Login按钮,因为它在Clear按钮的前面:

continue = driver.find_element_by_name('continue')

XPath定位

XPath是用来定位XML文档节点的语言。不过HTML可以看成是XML(XHTML)的一种实现。Selenium用户可以使用这个强力的语言来瞄准Web应用的元素。 XPath延伸了用id或者name属性来定位的单一方法,开创了许多可能性,例如定位页面的第三个复选框

用XPath的主要理由之一,就是你想定位的元素没有合适的id或者name属性的时候,你可以用XPath来对元素进行绝对定位(不推荐)或者把这个元素和另外一个有确定id或者name的元素关联起来(即相对定位)。XPath定位器也可以用来找出那些具有id,name以外属性的元素。

绝对的XPath定位包含了从HTML根节点起的所有元素,并且一些轻微的改变就会失效。而用id或者name属性来找到一个靠近的元素(比较理想的是父元素),这样你就可以依靠他们的相对关系来确定目标元素的位置。这种情况改变的可能就小了很多了,我们写的测试程序也会更可靠。

再来看一个实例:

<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
   <input name="continue" type="button" value="Clear" />
  </form>
</body>
<html>

form元素可以这样定位:

  1. login_form = driver.find_element_by_xpath("/html/body/form[1]")
  2. login_form = driver.find_element_by_xpath("//form[1]")
  3. login_form = driver.find_element_by_xpath("//form[@id='loginForm']")

(译者注:这里下标看起来应该是从1开始的)

  1. 绝对路径(如果HTML有细微的改变就会失效)
  2. HTML的第一个form元素
  3. id属性为'loginForm'的form元素

username元素可以这样定位:

username = driver.find_element_by_xpath("//from[input/@name='username']")
username = driver.find_element_by_xpath("//form[@id='loginForm']/input[1]")
username = driver.find_element_by_xpath("//input[@name='username']")
  1. 第一个form元素的 name属性是'username'的input子元素
  2. id属性为'loginForm'的form元素的第一个input子元素
  3. name属性为'username'的第一个input元素

'clear'按钮可以这样定位:

clear_button = driver.find_element_by_xpath("//input[@name='continue'][@type='button']")
clear_button = driver.find_element_by_xpath("//form[@id='loginForm']/input[4]")
  1. type属性为'button',name属性为'continue'的第一个input元素
  2. id为'loginForm'的表单的第四个input子元素

这些例子只覆盖了一些基本的使用情况,如果想学习更具体的,推荐下面这些地方: W3School XPath Tutorial W3C XPath Recommendation * XPath Tutorial

还有几个很有用的插件可以帮助我们测试: XPath Checker (Firefox浏览器)提供XPath的建议,并且可以测试XPath的结果 Firebug 提供XPath的建议只是这个插件很有用的功能之一 * XPath Helper Google Chrome浏览器

用链接文本定位超链接

如果你知道一个锚标签使用了什么文本,那么就使用这种方法。在超链接定位里,会返回第一个文本属性匹配的链接,如果没有元素匹配,会抛出NoSuchElementException异常。

实例:

<html>
 <body>
  <p>Are you sure you want to do this?</p>
  <a href="continue.html">Continue</a>
  <a href="cancel.html">Cancel</a>
</body>
<html>

可以这样定位 continue.html链接:

continue_link = driver.find_element_by_link_text('Continue')
continue_link = driver.find_element_by_partial_link_text('Conti')

(waiting注:find_element_by_partial_link_text使用的应该是子串匹配,只要输入自字符串即可匹配,读者最好自行测试)

标签名定位

知道元素标签名就使用这个定位,如果没有元素匹配,会抛出NoSuchElementException异常。

实例:

<html>
 <body>
  <h1>Welcome</h1>
  <p>Site content goes here.</p>
</body>
<html>

可以这样定位标题元素(h1):

heading1 = driver.find_element_by_tag_name('h1')

class定位

知道class就使用这个定位,只返回匹配的第一个,无元素匹配,会抛出NoSuchElementException异常。

实例:

<html>
 <body>
  <p class="content">Site content goes here.</p>
</body>
<html>

定位p元素:

content = driver.find_element_by_class_name('content')

css选择器定位

如果你能用css选择器的语法来表述一个元素,那么就选这个,只返回匹配的第一个,无元素匹配,会抛出NoSuchElementException异常。

实例:

<html>
 <body>
  <p class="content">Site content goes here.</p>
</body>
<html>

定位p元素:

content = driver.find_element_by_css_selector('p.content')