>[info]WebUI自动化,**首先需要定位元素**,然后再进行各种事件操作。
WebDriver 提供了一系列的API,提供给我们方便得定位元素。
WebDriver类的源码位置:`selenium\webdirver\remote\webdirver.py`
通过源码分析,WebDriver中有一系列以`find_`开头的方法,都是用于元素定位。下面我们一一介绍这些定位的方法。
[TOC]
这里,初学者可以根据下面的实例来一一了解如何进行元素的定位。
## 环境准备
首先创建一个hello.html页面,用于下面的演示
```html
<!DOCTYPE html>
<html lang="zh-CN">
<body>
<h1 class="head_title">你好,<span id="world">世界!</span></h1>
<a href="https://www.kancloud.cn/@guanfuchang" target="_blank">我的看云首页</a>
<br/>
<br/>
<div id="login_form" class="login">
用户名:<input name="username" class="ptqa user_name" placeholder="用户名" value="Milton" required/>
密码:<input type="text" name="password" class="ptqa pwd" placeholder="密码" value="ptqa" required/>
地区:
<select class="city">
<option value="gz">广州</option>
<option value="fs">佛山</option>
<option value="mm">茂名</option>
<option value="hb">襄樊</option>
</select>
<br>
<br>
<button>提交</button>
<br>
</div>
</body>
</html>
```
在同个目录下创建一个`find_location.py`文件,初始化工作
```python
from selenium import webdriver
import os
# 创建Chrome驱动实例
driver = webdriver.Chrome()
# 启动浏览器并且导航到指定URL
# 这里为了覆盖更多的元素定位,我自己编写了一个本地的hello.html文件。
file_path = 'file:///' + os.path.abspath('hello.html')
driver.get(file_path)
```
## 元素定位
### 通过class定位
`find_element_by_class_name(self, name):`
`find_elements_by_class_name(self, name):`
```python
# 定位class名称为“head_title"的元素
head_title = driver.find_element_by_class_name("head_title")
print(head_title.text)
```
### 通过id定位
`find_element_by_id(self, id_):`
`find_elements_by_id(self, id_):`
```python
# 定位id为“world”的元素
world = driver.find_element_by_id("world")
print(world.text)
```
### 通过name属性定位
`find_element_by_name(self, name):`
`find_elements_by_name(self, name):`
```python
# 定位name为“username”的元素
username = driver.find_element_by_name("username")
print(username.get_attribute("value"))
```
### 通过标签名定位
`find_element_by_tag_name(self, name):`
`find_elements_by_tag_name(self, name):`
```python
# 定位标签为<button>的元素
submit_btn = driver.find_element_by_tag_name("button")
print(submit_btn.text)
```
### 通过链接文本定位
`find_element_by_link_text(self, link_text):`
`find_element_by_partial_link_text(self, link_text):`
```python
# 定位链接文本完全匹配“我的看云首页”的元素
kancloud = driver.find_element_by_link_text("我的看云首页")
print(kancloud.get_attribute("href"))
```
```python
# 定位链接文本部分匹配“看云首页”的元素
kancloud = driver.find_element_by_partial_link_text("看云首页")
print(kancloud.get_attribute("href"))
```
### 通过xpath定位
`find_element_by_xpath(self, xpath):`
`find_elements_by_xpath(self, xpath):`
```python
# xpath定位,相对路径定位用户名输入框
username = driver.find_element_by_xpath("//body/div/input")
print(username.get_attribute("value"))
```
```python
# xpath定位,相对路径与属性结合 定位密码输入框
password = driver.find_element_by_xpath("//input[@name='password']")
print(password.get_attribute("value"))
```
```python
# xpath定位,多个属性结合 定位密码输入框
password = driver.find_element_by_xpath("//input[@name='password'][@type='text']")
print(password.get_attribute("value"))
```
### 通过css选择器定位
`find_element_by_css_selector(self, css_selector):`
`find_elements_by_css_selector(self, css_selector):`
![](https://box.kancloud.cn/bebdb84407c7fc1b64c5b0617ad530a0_979x175.jpg)
```python
# css选择器,标签+属性 定位用户名输入框
username = driver.find_element_by_css_selector("input[name='username']")
print(username.get_attribute("value"))
```
```python
# css选择器,标签+class类名 定位用户名输入框
username = driver.find_element_by_css_selector("input.user_name")
print(username.get_attribute("value"))
```
```python
# css选择器,标签+多个class类名,定位密码输入框,注意不要空格,空格代表下一级子元素
password = driver.find_element_by_css_selector("input.ptqa.pwd")
print(password.get_attribute("value"))
```
```python
# css选择器,id+多个class类名,定位密码输入框
password = driver.find_element_by_css_selector("#login_form .ptqa.pwd")
print(password.get_attribute("value"))
```
```python
# css选择器,多级class类名,定位密码输入框
password = driver.find_element_by_css_selector(".login .ptqa.pwd")
print(password.get_attribute("value"))
```
```python
# css选择器,class类名+属性,定位密码输入框
password = driver.find_element_by_css_selector(".login .ptqa[name='password']")
print(password.get_attribute("value"))
```
```python
#css 选择器,根据父子关系,定位密码输入框
password = driver.find_element_by_css_selector("div[id='login_form']>input[name='password']")
print(password.get_attribute("value"))
```
```python
# css 选择器,根据兄弟关系,定位密码输入框
password = driver.find_element_by_css_selector("input[name='username']+input")
print(password.get_attribute("value"))
```
上面的定位元素方法,都列出了两个,其中一个是 **find_elements_by_xxx**,这个方法用在获取结果有多个元素的情况,例如下面获取下拉列表选项
```python
# 用find_element_by_css_selector 获取的是单个元素
mm = driver.find_element_by_class_name("city").find_element_by_css_selector("option[value='mm']")
print(mm.text)
print("-"*20)
# 用find_elements_by_css_selector获取的是元素组列表
cities = driver.find_elements_by_css_selector(".city option")
print(type(cities))
for city in cities:
print(city.text)
```
运行结果为:
```cmd
茂名
--------------------
<class 'list'>
广州
佛山
茂名
襄樊
```
### 通用的终极定位语法
上面的所有元素定位 `find_element_by_xxx`和`find_elements_by_xxx`调用的结果,实际上都是在调用以下两种方法,我们也可以直接调用一下两种方法即可。
`find_element(self, by=By.ID, value=None):`
`find_elements(self, by=By.ID, value=None):`
```python
class By(object):
"""
Set of supported locator strategies.
"""
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"
```
例如:
```python
from selenium.webdriver.common.by import By
# 根据id,定位id为“world”的元素
world = driver.find_element(By.ID,"world")
print(world.text)
```
```python
# xpath定位,相对路径与属性结合 定位密码输入框
password = driver.find_element(By.XPATH,"//input[@name='password']")
print(password.get_attribute("value"))
```
```python
# css选择器,标签+属性 定位用户名输入框
username = driver.find_element(By.CSS_SELECTOR,"input[name='username']")
print(username.get_attribute("value"))
```
## 定位总结
通过本节,我们需要数量掌握以下几种元素定位方法
* 通过id定位
* 通过class定位
* 通过name属性定位
* 通过标签名定位
* 通过链接文本定位
* 通过xpath定位
* 通过css选择器定位
我最喜欢的定位方式,优先是id,如果没有id找class,如果class不好定位,找css选择器。我觉得css选择器是最灵活也是最强大的定位方式。使用xpath定位切记不要用绝对路径,最好结合相对路径与属性。
<hr style="margin-top:50px">
<section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="margin: 40px 0% 10px;box-sizing: border-box;"><section class="" style="display: inline-block;width: 100%;border-width: 5px;border-style: double;border-color: rgb(23, 22, 24);padding: 10px;border-radius: 2px;box-sizing: border-box;"><section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="transform: translate3d(20px, 0px, 0px);-webkit-transform: translate3d(20px, 0px, 0px);-moz-transform: translate3d(20px, 0px, 0px);-o-transform: translate3d(20px, 0px, 0px);font-size: 11px;margin: -50px 0% 0px;box-sizing: border-box;"><section class="" style="box-sizing: border-box;width: 7em;height: 7em;display: inline-block;vertical-align: bottom;border-radius: 100%;border-width: 4px;border-style: double;border-color: rgb(23, 22, 24);background-position: center center;background-repeat: no-repeat;background-size: cover;background-image: url("http://pav7h2emv.bkt.clouddn.com/FnD-fHkNDLN1-b02XmnMvsz6ld-n");"><section class="" style="width: 100%;height: 100%;overflow: hidden;box-sizing: border-box;"><img class="" data-ratio="0.6012024" data-w="499" data-src="http://pav7h2emv.bkt.clouddn.com/FnD-fHkNDLN1-b02XmnMvsz6ld-n" style="opacity: 0; box-sizing: border-box; width: 100% !important; height: auto !important; visibility: visible !important;" width="100%" data-type="jpeg" _width="100%" src="http://pav7h2emv.bkt.clouddn.com/FnD-fHkNDLN1-b02XmnMvsz6ld-n" data-fail="0"></section></section></section></section><section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="margin: -30px 0% 30px;box-sizing: border-box;"><section class="" style="display: inline-block;vertical-align: top;width: 61.8%;padding: 0px 15px;box-sizing: border-box;"><section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="margin: 40px 0% 0px;box-sizing: border-box;"><section class="" style="color: rgb(160, 160, 160);box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">微信公众号:</p><p style="margin: 0px;padding: 0px;box-sizing: border-box;">python测试开发圈</p><p style="margin: 0px;padding: 0px;box-sizing: border-box;"><br style="box-sizing: border-box;"></p></section></section></section></section><section class="" style="display: inline-block;vertical-align: top;width: 38.2%;box-sizing: border-box;"><section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="text-align: center;margin: 10px 0% 0px;box-sizing: border-box;"><section class="" style="max-width: 100%;vertical-align: middle;display: inline-block;border-width: 0px;border-radius: 0px;box-shadow: rgb(0, 0, 0) 0px 0px 0px;width: 90%;overflow: hidden !important;box-sizing: border-box;"><img data-ratio="1" data-w="430" data-src="http://pav7h2emv.bkt.clouddn.com/FibGgIJSMfHtehzeWOOzjdQKSMx5" style="vertical-align: middle; max-width: 100%; box-sizing: border-box; width: 100% !important; height: auto !important; visibility: visible !important;" width="100%" data-type="jpeg" _width="100%" class="" src="http://pav7h2emv.bkt.clouddn.com/FibGgIJSMfHtehzeWOOzjdQKSMx5" data-fail="0"></section></section></section></section></section></section><section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="margin: -30px 0% 0px;box-sizing: border-box;"><section class="" style="display: inline-block;vertical-align: top;width: 61.8%;padding: 0px 15px;box-sizing: border-box;"><section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="transform: translate3d(5px, 0px, 0px);-webkit-transform: translate3d(5px, 0px, 0px);-moz-transform: translate3d(5px, 0px, 0px);-o-transform: translate3d(5px, 0px, 0px);box-sizing: border-box;"><section class="" style="color: rgb(160, 160, 160);font-size: 14px;box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">一起分享学习与成长路线</p></section></section></section></section><section class="" style="display: inline-block;vertical-align: top;width: 38.2%;box-sizing: border-box;"><section class="" style="box-sizing: border-box;" powered-by="xiumi.us"><section class="" style="transform: translate3d(10px, 0px, 0px);-webkit-transform: translate3d(10px, 0px, 0px);-moz-transform: translate3d(10px, 0px, 0px);-o-transform: translate3d(10px, 0px, 0px);box-sizing: border-box;"><section class="" style="color: rgb(160, 160, 160);font-size: 14px;box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">长按(或扫描)二维码关注</p></section></section></section></section></section></section></section></section></section>