> 在使用selenium webdriver进行元素定位时,通常使用findElement或findElements方法结合By类返回的元素句柄来定位元素。其中By类的常用定位方式共八种,现分别介绍如下。
[TOC]
#### 1. WebDriverBy::id()
> 通过ID属性定位元素
~~~
//HTML代码
//<input id="kw" name="wd" class="s_ipt" maxlength="255" autocomplete="off" />
<?php
$driver = RemoteWebDriver::create($host, DesiredCapabilities::chrome(), 5000);
$driver->get('https://www.baidu.com/');
$element = $driver->findElement(WebDriverBy::id('kw'));
?>
~~~
#### 2. WebDriverBy::name()
> 通过name属性定位元素。如果查找多个,则使用findElements进行定位
~~~
//HTML代码
//<input id="kw" name="wd" class="s_ipt" maxlength="255" autocomplete="off" />
<?php
$driver = RemoteWebDriver::create($host, DesiredCapabilities::chrome(), 5000);
$driver->get('https://www.baidu.com/');
$element = $driver->findElement(WebDriverBy::name('wd'));
foreach($elements as $elem){ //有时候多个元素时,想找出某个特定元素,可根据attribute或text进行判断过滤
echo $elem->getAttribute('type');
echo $elem->getText();
}
?>
~~~
#### 3. WebDriverBy::tagName()
> 通过标签进行定位元素。如果查找多个,则使用findElements进行定位,具体参考WebDriverBy::name()的代码
~~~
//HTML代码
//<input type="hidden" name="rsv_bp" value="0" />
//<input id="kw" name="wd" class="s_ipt" maxlength="255" autocomplete="off" />
//.....
<?php
$driver = RemoteWebDriver::create($host, DesiredCapabilities::chrome(), 5000);
$driver->get('https://www.baidu.com/');
$element = $driver->findElement(WebDriverBy::tagName('input'));
?>
~~~
#### 4. WebDriverBy::className()
> 通过css类进行定位元素。如果查找多个,则使用findElements进行定位,具体参考WebDriverBy::name()的代码
~~~
//HTML代码
//<input id="kw" name="wd" class="s_ipt" maxlength="255" autocomplete="off" />
<?php
$driver = RemoteWebDriver::create($host, DesiredCapabilities::chrome(), 5000);
$driver->get('https://www.baidu.com/');
$element = $driver->findElement(WebDriverBy::className('s_ipt'));
?>
~~~
#### 5. WebDriverBy::linkText()
> 通过超文本链接上的文字信息来定位元素。如果查找多个,则使用findElements进行定位,具体参考WebDriverBy::name()的代码
~~~
//HTML代码
//<a href="http://news.baidu.com" name="tj_trnews" class="mnav">新闻</a>
<?php
$driver = RemoteWebDriver::create($host, DesiredCapabilities::chrome(), 5000);
$driver->get('https://www.baidu.com/');
$element = $driver->findElement(WebDriverBy::linkText('新闻'));
?>
~~~
#### 6. WebDriverBy::partialLinkText()
> 这个方法是上一个方法的扩展。当你不能准确知道超链接上的文本信息或者只想通过一些关键字进行匹配时,可以使用这个方法来通过部分链接文字进行匹配。如果查找多个,则使用findElements进行定位,具体参考WebDriverBy::name()的代码
~~~
//HTML代码
//<a href="http://news.baidu.com" name="tj_trnews" class="mnav">新闻</a>
<?php
$driver = RemoteWebDriver::create($host, DesiredCapabilities::chrome(), 5000);
$driver->get('https://www.baidu.com/');
$element = $driver->findElement(WebDriverBy::partialLinkText('新'));
?>
~~~
#### 7. WebDriverBy::xpath()
> 这个方法是非常强大的元素查找方式,使用这种方法几乎可以定位到页面上的任意元素。在正式开始使用XPath进行定位前,我们先了解下什么是XPath。XPath是XML Path的简称,由于HTML文档本身就是一个标准的XML页面,所以我们可以使用XPath的语法来定位页面元素。更多详细的定位资料,参考页脚链接地址。
XPath语法如下:
~~~
<?php
$element = $driver->findElement(WebDriverBy::xpath("//*[@id='J_login_form']/dl/dt/input[@id='J_password']"));
?>
~~~
#### 8. WebDriverBy::cssSelector()
> cssSelector这种元素定位方式跟xpath比较类似,但执行速度较快,而且各种浏览器对它的支持都相当到位,所以功能比较强大。
下面是一些常见的cssSelector的定位方式:
定位id为flrs的div元素,可以写成:#flrs 注:相当于xpath语法的//div[@id='flrs']
定位id为flrs下的a元素,可以写成 #flrs > a 注:相当于xpath语法的//div[@id='flrs']/a
定位id为flrs下的href属性值为/forexample/about.html的元素,可以写成: #flrs > a[href="/forexample/about.html"]
如果需要指定多个属性值时,可以逐一加在后面,如#flrs > input[name="username"][type="text"]。
明白基本语法后,我们来尝试用cssSelector方式来层级关系定位,代码如下:
~~~
//HTML代码
//<a href="http://news.baidu.com" name="tj_trnews" class="mnav">新闻</a>
<?php
$element = $driver->findElement(WebDriverBy::cssSelector("#J_login_form>dl>dt>input[id='J_password']"));
?>
~~~
cssSelector还有一个用处是定位使用了复合样式表的元素,之前在第4种方式className里面提到过。现在我们就来看看如何通过cssSelector来引用到第4种方式中提到的那个button。button代码如下:
~~~
//HTML代码
//<button id="J_sidebar_login" class="btn btn_big btn_submit" type="submit">登录</button>
<?php
$element = $driver->findElement(WebDriverBy::cssSelector("button.btn.btn_big.btn_submit"));
?>
~~~
此外,cssSelector还有一些高级用法,如果熟练后可以更加方便地帮助我们定位元素,如我们可以利用^用于匹配一个前缀,$用于匹配一个后缀,*用于匹配任意字符。例如:
>匹配一个有id属性,并且id属性是以”id_prefix_”开头的超链接元素:a[id^='id_prefix_']
匹配一个有id属性,并且id属性是以”_id_sufix”结尾的超链接元素:a[id$='_id_sufix']
匹配一个有id属性,并且id属性中包含”id_pattern”字符的超链接元素:a[id*='id_pattern']
#### 9. 判断定位的元素是否存在
> selenium找元素时,如果超出timeout时间后,还未找到元素,则会报异常,我们则可以利用这样的方式进行判断元素是否存在。不过这种方式对于及时性要求不高的情况下使用,如果要求及时性的话,建议还是获取到page source后,用htmlparser或正则判断即可。
~~~
<?php
if(isElementExsit($driver, WebDriverBy::linkText('新闻'))){
echo '找到元素啦';
}else{
echo '没有找到元素';
}
/**
* 判断元素是否存在
* @param WebDriver $driver
* @param WebDriverBy $locator
*/
function isElementExsit($driver,$locator){
try {
$nextbtn = $driver->findElement($locator);
return true;
} catch (\Exception $e) {
echo 'element is not found!';
return false;
}
}
?>
~~~
更多参考资料:
1.https://saucelabs.com/resources/articles/selenium-tips-css-selectors