> 在使用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