想要操作web页面上的元素,首先必须要定位到这个元素上。每个元素都有他各自的属性,比如id,name,class等,我们就通过这些属性来定位元素。
定位方法
webdriver提供的定位方法如下:
名称 | 定义 | Python用法 |
---|---|---|
ID | 通过ID定位元素 | find_element_by_id() |
NAME | 通过NAME定位元素 | find_element_by_name() |
CLASS_NAME | 通过CLASS_NAME定位元素 | find_element_by_class_name() |
TAG_NAME | 通过TAG_NAME定位元素 | find_element_by_tag_name() |
LINK_TEXT | 通过链接的文字定位元素 | find_element_by_link_text() |
PARTIAL_LINK_TEXT | 通过部分的链接文字定位元素 | find_element_by_partial_link_text() |
XPATH | 通过XPATH定位元素 | find_element_by_xpath() |
CSS_SELECTOR | 通过CSS_SELECTOR定位元素 | find_element_by_css_selector() |
id、name、class name、tag name定位元素
html中,大多数的元素都具备id和name的属性,并且id是唯一的,因此用id和name来定位元素是比较常见的方式。
不过有的元素并不具备id和name属性,我们则可以用class name来定位元素。
当然我还可以用tag name来定位,但是标签名字太容易重复,除非想定位一组相同标签的元素,否则一般不推荐使用。
我们来看一下百度首页的搜索框和搜索按钮的html代码
...
<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>
...
从上面代码我们看到,搜索框具备id=“kw”,name=“wd”,class="s_ipt"的属性,搜索按钮具备id=“su”,class="bg s_btn"的属性,我们分别用这些属性来定位操作搜索框和搜索按钮(为了方便看到结果,每一步我都停止1秒)。
#coding = utf-8
from selenium import webdriver #导入selenium的webdriver包
from time import sleep
driver = webdriver.Chrome() #获得浏览器对象,这里我使用的是chrome
driver.get("https://www.baidu.com") #打开网址
driver.find_element_by_id('kw').send_keys('test1') #使用id定位,在搜索框中输入test1
sleep(1)
driver.find_element_by_name('wd').clear() #使用name定位,删除搜索框中输入的文字
sleep(1)
driver.find_element_by_class_name('s_ipt').send_keys('python')#使用class name定位,再一次在搜索框中输入文字
sleep(1)
driver.find_element_by_id('su').click()#使用id定位,点击‘百度一下’按钮进行搜索
sleep(1)
driver.quit() #关闭浏览器
link text、partial link text定位
对于一个链接,我们可以使用link text和partial link text来定位。
我们先自己写一个html test sample,保存为test.html。这个网页会显示三个指向百度的链接,但每个链接的显示文字不同
<html>
<head>
<title>link Test Html</title>
</head>
<body>
<a href = 'https://www.baidu.com'>baidu</a>
<br>
<a href = 'https://www.baidu.com'>also baidu</a>
<br>
<a href = 'https://www.baidu.com'>still baidu</a>
</body>
</html>
接着我们用link text和partial link text来定位这三个链接,并点击。注意python文件要与上面的html文件在同一个文件夹下
#coding = utf-8
from selenium import webdriver #导入selenium的webdriver包
from time import sleep
import os
driver = webdriver.Chrome()
file_name = 'file:///' + os.path.abspath('test.html')
driver.get(file_name) #打开网址
driver.find_element_by_link_text('baidu').click()#使用link text定位
sleep(1)
driver.back() # 浏览器后退到上一个页面
sleep(1)
driver.find_element_by_link_text('also baidu').click()
sleep(1)
driver.back()
sleep(1)
driver.find_element_by_partial_link_text('still').click()#使用partial link text定位
sleep(1)
driver.quit()
XPATH定位
XPath是XML和Path的缩写,是一种在XML文档中定位元素的语言。与CSS Selector不同,XPath支持向前和向后查找,而CSS Selector只能向前查询。这说明,使用XPATH方法,可以通过子元素定位父元素。
常用的定位方法有以下几种:
- 使用绝对路径定位(当页面发生变化时,绝对路径可能会失败)
- 使用相对路径定位
- 使用索引定位(可与绝对路径相对路径结合使用)
- 使用属性定位(XPATH还支持布尔运算,可以与属性定位结合使用)
#绝对路径,寻找html → body → div → input元素,一层一层定位寻找
find_element_by_xpath('html/body/div/input')
#相对路径,先定位到div,再找到div下的input
find_element_by_xpath('//div/input')
#带索引的绝对路径,寻找body下面第三个div下的span/p
find_element_by_xpath('html/body/div[3]/span/p')
#带索引的相对路径,寻找div下第二个span下面的input
find_element_by_xpath('//div/span[2]/input')
#属性定位
find_element_by_xpath('//span[@id = 'test']/input') #寻找id为test的span下面的input
find_element_by_xpath('//input[@type]') #寻找带有type属性的input
find_element_by_xpath('//input[@name = 'search' and @type = 'text']') #使用布尔运算:寻找name为search并且type为text的input(也可以使用布尔运算or)
find_element_by_xpath('//a[starts-with(@href,'https://www.b')]') #模糊匹配,寻找以https://www.b开头的网址(可以使用ends-with,以结尾、contains包含)
find_element_by_xpath('//a[@*='test']')#定位任意值匹配,所有含有属性test的网址
CSS Selector定位
使用CSS Selector来定位元素,一般比XPATH更快更准确也更容易,但学习它的语法,相对XPATH来说会难一些。我们先来看一下CSS Selector的语法。
以上图片取自W3school,内有详细举例说明,请参照:W3school CSS选择器
这其中比较常用的有以下几种:
选择器 | 例子 | 描述 |
---|---|---|
.class | .intro | class选择器,选择class="intro"的所有元素 |
#id | #first | id选择器,选择id="first"的所有元素 |
* | * | 选择所有元素 |
element | input | 选择所有<input>元素 |
element,element | div,p | 并列选择,所有<div>和所有<p>元素 |
element element | div p | 后代选择,<div>中内部包含的所有<p>元素 |
element>element | div>p | 子元素选择,父元素为<div>的所有<p>元素 换言之,若一个<p>元素是<div>子元素的子元素,则不会被选中 |
element+element | div+p | 相邻选择,紧接<div>的<p>元素(只会选中第一个邻接<p>元素) |
element~element | div~p | 同级选择,在<div>之后的同级<p>元素 |
element[attribute] | a[target] | 选择带有target属性的<a>元素 |
element[attribute=value] | a[target=_blank] | 选择target="_blank"的<a>元素 |
element[attribute~=value] | a[title~=flower] | 选择target属性包含flower的<a>元素 |
element[attribute|=value] | a[target|=to] | 选择target属性值以"to"开头的<a>元素 |
element[attribute^=value] | a[src^=“https”] | 选择src属性以"https"开头的<a>元素 |
element[attribute$=value] | a[src$=".com"] | 选择src属性以".com"结尾的<a>元素 |
element[attribute*=value] | a[src*=“aaa”] | 选择src属性包含"aaa"的<a>元素 |
element:first-of-type | p:first-of-type | 选择元素<p>其父元素的首个<p>元素 同理可推论:last-of-type、:only-of-type使用 |
element:only-child | p:only-child | 选择元素<p>其父元素的唯一子元素<p> |
element:nth-child(n) | p:nth-child(2) | 选择元素<p>其父元素的第二个子元素<p> 同理可推论:nth-last-chiled(n)、:last-child用法 |
:root | :root | 选择根元素 |
element:empty | p:empty | 选择没有子元素的<p>元素 |
使用
分别用XPATH和CSS Selector来定位元素
我们使用下面的test.html来练习。
<!DOCUMENTTYPE html>
<html>
<head>
<title>Test Html</title>
</head>
<body>
<div id='div1'>
<input type='checkbox' name='1'>option1</input>
<input type='checkbox' name='2' >option2</input>
<input type='checkbox' name='3' id='id_option3'>option3</input>
</div>
<input type='checkbox'>option</input>
<div id='div2'>
<input type = 'radio' name = '4'>option4</input>
<input type = 'radio' name = '4'>option5</input>
<input type = 'radio' name = '4'>option6</input>
</div>
</body>
</html>
我们使用XPATH和CSS Selector的几种方法来分别点击几个选项来观察是否实现了定位元素的效果
#coding = utf-8
from selenium import webdriver #导入selenium的webdriver包
from time import sleep
import os
driver = webdriver.Chrome() #获得浏览器对象,这里我使用的是chrome
file_name = 'file:///' + os.path.abspath('inner.html')
driver.get(file_name) #打开网址
driver.find_element_by_xpath("html/body/div/input").click()#xpath绝对路径定位,点击opthon1
sleep(2)
driver.find_element_by_xpath("//div[@id='div1']/input").click()#xpath带属性的相对路径定位,再次点击option1
sleep(2)
driver.find_element_by_xpath("html/body/div[2]/input").click()#xpath带索引的绝对路径定位,点击option4
sleep(2)
driver.find_element_by_xpath("//input[@type='checkbox' and @name='3']").click()#带布尔运算的属性绝对路径定位,点击option3
sleep(2)
driver.find_element_by_css_selector("#id_option3").click()#使用id定位,再次点击option3
sleep(2)
driver.find_element_by_css_selector("div+input").click()#div相邻的input元素,点击option,注意此处input不是div的子元素
sleep(2)
driver.find_element_by_css_selector("#div2>input:nth-child(2)").click()#id为div2下第二个input定位,点击option5
sleep(2)
driver.quit() #关闭浏览器
在实际使用中,我们要定位的情况比例子中要复杂的多,需要大量练习才能得心应手。