要定位一个页面中的元素有多中策略和方法。你可以根据实际情况选择其中最为合适的。Selenium为定位页面元素提供了下面的这些方法:
-
find_element_by_id
(使用id) -
find_element_by_name
(使用name属性值) -
find_element_by_xpath
(使用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
(使用CSS选择器)
要定位多个元素,除了通过id进行定位,只需将elements
+s
(这些元素将会一个列表的形式返回)
-
find_elements_by_name
(使用name属性值) -
find_elements_by_xpath
(使用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
(使用CSS选择器)
除了上面的通用方法外,在一个页面对象进行访问操作的时候还有两个非常有用的私有方法:find_element
和find_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"
4.1.通过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")
4.2.通过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')
4.3.使用XPath进行定位
XPath是一种用于定位XML文档节点的语法。因为HTML可以是一种XML实现(XHTML),Selenium用户可以使用这种强大的语言工具来定位他们页面应用的元素。XPath扩展了仅仅通过id和name属性进行元素定位的简单方法(XPath也支持),为元素定位开辟了更多的可能。比如定位页面中的第三个单选框。
当你想要定位的元素没有合适的id和name的时候,使用XPath会是一个比较好的选择。你可以使用XPath通过绝对路径或者相对路径定位没有id和name属性的元素(不推荐使用绝对路径)。除了id和name,XPath定位器也可以通过其他属性指定元素。
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
元素可以像下面这样进行定位:
login_form = driver.find_element_by_xpath("/html/body/form[1]")
login_form = driver.find_element_by_xpath("//form[1]")
login_form = driver.find_element_by_xpath("//form[@id='loginForm']")
- 绝对路径(HTML只要稍微变动就会失效)
- HTML中的第一个
form
元素 - id属性值为loginForm的
form
元素
username
元素可以像下面这样定位:
username = driver.find_element_by_xpath("//form[input/@name='username']")
username = driver.find_element_by_xpath("//form[@id='loginForm']/input[1]")
username = driver.find_element_by_xpath("//input[@name='username']")
- 有一个
input
子元素,name属性为username的form
元素 - id属性为loginForm的
form
元素的第一个input
子元素 - 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]")
- name属性为continue,type属性为button的
input
元素 - id属性为loginForm的
form
元素的第四个input
子元素
这些示例只包含一些基础使用,想要了解更详细的相关信息,推荐浏览:
- W3Schools XPath 教程
- W3C XPath 推荐
- XPath 教程 (带有交互示例)
也有一些优秀的浏览器插件可以用来辅助编写定位元素的XPath:
- XPath Checker -XPath提示,也能用于测试XPath结果
- Firebug -XPath提示只是其强大功能的一部分
- XPath Helper -谷歌Chrome插件
4.4.通过链接文本定位超链接
当知道一个锚点标签内使用的链接文本时可以使用本方法。此方法将会返回匹配链接文本的第一个元素。如果没有相匹配的元素,将抛出一个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')
4.5.通过标签名定位元素
当想要通过标签名定位元素时可以使用此方法。使用此方法,将会返回匹配给定标签名的第一个元素。如果没有相匹配的元素,将会抛出一个NoSuchElementException
异常。
举个例子,考虑一下下面的网页源码:
<html>
<body>
<h1>Welcome</h1>
<p>Site content goes here.</p>
</body>
<html>
标题元素(h1)可以像下面这样定位:
heading1 = driver.find_element_by_tag_name('h1')
4.6.通过类名定位元素
当想要通过类名(class)属性定位元素时可以使用此方法。使用此方法,将会返回匹配给类名属性的第一个元素。如果没有相匹配的元素,将会抛出一个NoSuchElementException
异常。
举个例子,考虑下面的网页源码:
<html>
<body>
<p class="content">Site content goes here.</p>
</body>
<html>
p
元素可以像下面这样进行定位:
content = driver.find_element_by_class_name('content')
4.7.使用CSS选择器定位元素
当想要使用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')
Sauce Labs 上有关于 CSS 选择器的优秀文档.