webdriver 定位form元素_webdriver中鼠标悬浮到元素上出现的元素定位不到 - CSDN
精华内容
参与话题
  • selenium webdriver by xpath 定位元素

    千次阅读 2016-11-16 16:51:16
    这个方法是非常强大的元素查找方式,使用这种方法几乎可以定位到页面上的任意元素。在正式开始使用XPath进行定位前,我们先了解下什么是XPath。XPath是XML Path的简称,由于HTML文档本身就是一个标准的XML页面,所以...

    转自:http://www.cnblogs.com/qingchunjun/p/4208159.html

    By.xpath()

    这个方法是非常强大的元素查找方式,使用这种方法几乎可以定位到页面上的任意元素。在正式开始使用XPath进行定位前,我们先了解下什么是XPath。XPath是XML Path的简称,由于HTML文档本身就是一个标准的XML页面,所以我们可以使用XPath的语法来定位页面元素。

    假设我们现在以图(2)所示HTML代码为例,要引用对应的对象,XPath语法如下:

     

    图(2)

    绝对路径写法(只有一种),写法如下:

    引用页面上的form元素(即源码中的第3行):/html/body/form[1]

    注意:1. 元素的xpath绝对路径可通过firebug直接查询。2. 一般不推荐使用绝对路径的写法,因为一旦页面结构发生变化,该路径也随之失效,必须重新写。3. 绝对路径以单/号表示,而下面要讲的相对路径则以//表示,这个区别非常重要。另外需要多说一句的是,当xpath的路径以/开头时,表示让Xpath解析引擎从文档的根节点开始解析。当xpath路径以//开头时,则表示让xpath引擎从文档的任意符合的元素节点开始进行解析。而当/出现在xpath路径中时,则表示寻找父节点的直接子节点,当//出现在xpath路径中时,表示寻找父节点下任意符合条件的子节点,不管嵌套了多少层级(这些下面都有例子,大家可以参照来试验)。弄清这个原则,就可以理解其实xpath的路径可以绝对路径和相对路径混合在一起来进行表示,想怎么玩就怎么玩

     

    下面是相对路径的引用写法:

    查找页面根元素://

    查找页面上所有的input元素://input

    查找页面上第一个form元素内的直接子input元素(即只包括form元素的下一级input元素,使用绝对路径表示,单/号)://form[1]/input

    查找页面上第一个form元素内的所有子input元素(只要在form元素内的input都算,不管还嵌套了多少个其他标签,使用相对路径表示,双//号)://form[1]//input

    查找页面上第一个form元素://form[1]

    查找页面上id为loginForm的form元素://form[@id='loginForm']

    查找页面上具有name属性为username的input元素://input[@name='username']

    查找页面上id为loginForm的form元素下的第一个input元素://form[@id='loginForm']/input[1]

    查找页面具有name属性为contiune并且type属性为button的input元素://input[@name='continue'][@type='button']

    查找页面上id为loginForm的form元素下第4个input元素://form[@id='loginForm']/input[4]

    Xpath功能很强大,所以也可以写得更加复杂一些,如下面图(3)的HTML源码。

     

    图(3)

    如果我们现在要引用id为“J_password”的input元素,该怎么写呢?我们可以像下面这样写:

    WebElement password = driver.findElement(By.xpath("//*[@id='J_login_form']/dl/dt/input[@id='J_password']"));

    也可以写成:

    WebElement password = driver.findElement(By.xpath("//*[@id='J_login_form']/*/*/input[@id='J_password']"));

    这里解释一下,其中//*[@id=’ J_login_form’]这一段是指在根元素下查找任意id为J_login_form的元素,此时相当于引用到了form元素。后面的路径必须按照源码的层级依次往下写。按照图(3)所示代码中,我们要找的input元素包含在一个dt标签内,而dt又包含在dl标签内,所以中间必须写上dl和dt两层,才到input这层。当然我们也可以用*号省略具体的标签名称,但元素的层级关系必须体现出来,比如我们不能写成//*[@id='J_login_form']/input[@id='J_password'],这样肯定会报错的。

     

    前面讲的都是xpath中基于准确元素属性的定位,其实xpath作为定位神器也可以用于模糊匹配。比如下面图(4)所示代码:

     

    图(4)

    这段代码中的“退出”这个超链接,没有标准id元素,只有一个rel和href,不是很好定位。不妨我们就用xpath的几种模糊匹配模式来定位它吧,主要有三种方式,举例如下。

    a. 用contains关键字,定位代码如下:

    1 driver.findElement(By.xpath(“//a[contains(@href, ‘logout’)]”));

    这句话的意思是寻找页面中href属性值包含有logout这个单词的所有a元素,由于这个退出按钮的href属性里肯定会包含logout,所以这种方式是可行的,也会经常用到。其中@后面可以跟该元素任意的属性名。

    b. 用start-with,定位代码如下:

    1 driver.findElement(By.xpath(“//a[starts-with(@rel, ‘nofo’)]));

    这句的意思是寻找rel属性以nofo开头的a元素。其中@后面的rel可以替换成元素的任意其他属性。

    c. 用Text关键字,定位代码如下:

    1 driver.findElement(By.xpath(“//*[text()=’退出’]));

    这个方法可谓相当霸气啊。直接查找页面当中所有的退出二字,根本就不用知道它是个a元素了。这种方法也经常用于纯文字的查找。

    另外,如果知道超链接元素的文本内容,也可以用

    1 driver.findElement(By.xpath(“//a[contains(text(), ’退出’)]));

    这种方式一般用于知道超链接上显示的部分或全部文本信息时,可以使用。

     

    最后,关于xpath这种定位方式,webdriver会将整个页面的所有元素进行扫描以定位我们所需要的元素,所以这是一个非常费时的操作,如果你的脚本中大量使用xpath做元素定位的话,将导致你的脚本执行速度大大降低,所以请慎用。

     

    By.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方式来引用图(3)中选中的那个input对象,代码如下:

    WebElement password = driver.findElement(By.cssSelector("#J_login_form>dl>dt>input[id=’ J_password’]"));

    同样必须注意层级关系,这个不能省略。

     

    cssSelector还有一个用处是定位使用了复合样式表的元素,之前在第4种方式className里面提到过。现在我们就来看看如何通过cssSelector来引用到第4种方式中提到的那个button。button代码如下:

    <button id="J_sidebar_login" class="btn btn_big btn_submit" type="submit">登录</button>

    cssSelector引用元素代码如下:

    driver.findElement(By.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']

     

    最后再总结一下,各种方式在选择的时候应该怎么选择:

    1. 当页面元素有id属性时,最好尽量用id来定位。但由于现实项目中很多程序员其实写的代码并不规范,会缺少很多标准属性,这时就只有选择其他定位方法。

    2. xpath很强悍,但定位性能不是很好,所以还是尽量少用。如果确实少数元素不好定位,可以选择xpath或cssSelector。

    3. 当要定位一组元素相同元素时,可以考虑用tagName或name。

    4. 当有链接需要定位时,可以考虑linkText或partialLinkText方式。


    官网:

    http://selenium-python.readthedocs.io/locating-elements.html


    Locating by XPath

    XPath is the language used for locating nodes in an XML document. As HTML can be an implementation of XML (XHTML), Selenium users can leverage this powerful language to target elements in their web applications. XPath extends beyond (as well as supporting) the simple methods of locating by id or name attributes, and opens up all sorts of new possibilities such as locating the third checkbox on the page.

    One of the main reasons for using XPath is when you don’t have a suitable id or name attribute for the element you wish to locate. You can use XPath to either locate the element in absolute terms (not advised), or relative to an element that does have an id or name attribute. XPath locators can also be used to specify elements via attributes other than id and name.

    Absolute XPaths contain the location of all elements from the root (html) and as a result are likely to fail with only the slightest adjustment to the application. By finding a nearby element with an id or name attribute (ideally a parent element) you can locate your target element based on the relationship. This is much less likely to change and can make your tests more robust.

    For instance, consider this page source:

    <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>
    

    The form elements can be located like this:

    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']")
    
    1. Absolute path (would break if the HTML was changed only slightly)
    2. First form element in the HTML
    3. The form element with attribute named id and the value loginForm

    The username element can be located like this:

    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']")
    
    1. First form element with an input child element with attribute named name and the valueusername
    2. First input child element of the form element with attribute named id and the value loginForm
    3. First input element with attribute named ‘name’ and the value username

    The “Clear” button element can be located like this:

    clear_button = driver.find_element_by_xpath("//input[@name='continue'][@type='button']")
    clear_button = driver.find_element_by_xpath("//form[@id='loginForm']/input[4]")
    
    1. Input with attribute named name and the value continue and attribute named type and the valuebutton
    2. Fourth input child element of the form element with attribute named id and value loginForm

    展开全文
  • 在使用selenium webdriver进行元素定位时,通常使用findElement或findElements方法结合By类返回的元素句柄来定位元素。其中By类的常用定位方式共八种,现分别介绍如下: 1. By.name() 假设我们要测试的页面源码如下...

    如果你只是想快速实现控件抓取,而不急于了解其原理,可直接看:

    http://blog.csdn.net/kaka1121/article/details/51878346

    如果你想学习web端自动化,或者更快速地完成更稳定的前端自动化,不妨尝试点击:

    Web自动化框架LazyUI使用手册(1)--框架简介


    在使用selenium webdriver进行元素定位时,通常使用findElement或findElements方法结合By类返回的元素句柄来定位元素。其中By类的常用定位方式共八种,现分别介绍如下:

    1. By.name()

    假设我们要测试的页面源码如下:

    <button id="gbqfba" aria-label="Google Search" name="btnK" class="gbqfba"><span id="gbqfsa">Google Search</span></button>

    当我们要用name属性来引用这个button并点击它时,代码如下:

    public class SearchButtonByName {
            public static void main(String[] args){
                   WebDriver driver = new FirefoxDriver();
                   driver.get("http://www.forexample.com");
                   WebElement searchBox = driver.findElement(By.name("btnK"));
                   searchBox.click();
            }
    }

    2. By.id()

    页面源码如下:

     <button id="gbqfba" aria-label="Google Search" name="btnK" class="gbqfba"><span id="gbqfsa">Google Search</span></button>

    要引用该button并点击它时,代码如下:

    public class SearchButtonById {
    
            public static void main(String[] args){
                WebDriver driver = new FirefoxDriver();
                driver.get("http://www.forexample.com");
                WebElement searchBox = driver.findElement(By.id("gbqfba"));
                searchBox.click();
    
            }
    
    }

    3. By.tagName()

    该方法可以通过元素的标签名称来查找元素。该方法跟之前两个方法的区别是,这个方法搜索到的元素通常不止一个,所以一般建议结合使用findElements方法来使用。比如我们现在要查找页面上有多少个button,就可以用button这个tagName来进行查找,代码如下:

    public class SearchPageByTagName{
    
         public static void main(String[] args){
                WebDriver driver = new FirefoxDriver();
                driver.get("http://www.forexample.com");
                List<WebElement> buttons = driver.findElements(By.tagName("button"));
                System.out.println(buttons.size());  //打印出button的个数
    
        }
    
    }

    在使用tagName方法进行定位时,有些HTML元素的tagName是相同的,比如单选框、复选框、文本框和密码框的元素标签都是input,此时单靠tagName无法准确地得到我们想要的元素,需要结合type属性才能过滤出我们要的元素。

    4. By.className()

    className属性是利用元素的css样式表所引用的伪类名称来进行元素查找的方法。对于任何HTML页面的元素来说,一般程序员或页面设计师会给元素直接赋予一个样式属性或者利用css文件里的伪类来定义元素样式,使元素在页面上显示时能够更加美观。一般css样式表可能会长成下面这个样子:

    .buttonStyle{
    
        width: 50px;
        height: 50px;
        border-radius: 50%;
        margin: 0% 2%;
    
    }

    定义好后,就可以在页面元素中引用上述定义好的样式,如下:

     <button name="sampleBtnName" id="sampleBtnId" class="buttonStyle">I'm Button</button>
    如果此时我们要通过className属性来查找该button并操作它的话,就可以使用className属性了,代码如下:

    public class SearchElementsByClassName{
    
        public static void main(String[] args){
            WebDriver driver = new FirefoxDriver();
            driver.get("http://www.forexample.com");
            WebElement searchBox =  driver.findElement(By.className("buttonStyle"));
            searchBox.sendKeys("Hello, world");
        }
    }
    注意:使用className来进行元素定位时,有时会碰到一个元素指定了若干个class属性值的“复合样式”的情况,如下面这个button:<button id="J_sidebar_login" class="btn btn_big btn_submit" type="submit">登录</button>。这个button元素指定了三个不同的css伪类名作为它的样式属性值,此时就必须结合后面要介绍的cssSelector方法来定位了,稍后会有详细例子。


    5. By.linkText()

    这个方法比较直接,即通过超文本链接上的文字信息来定位元素,这种方式一般专门用于定位页面上的超文本链接。通常一个超文本链接会长成这个样子:

     <a href="/intl/en/about.html">About Google</a>
    我们定位这个元素时,可以使用下面的代码进行操作:

    public class SearchElementsByLinkText{
        public static void main(String[] args){
            WebDriver driver = new FirefoxDriver();
            driver.get("http://www.forexample.com");
            WebElement aboutLink = driver.findElement(By.linkText("About Google"));
            aboutLink.click();
        }
    }

    6. By.partialLinkText()

    这个方法是上一个方法的扩展。当你不能准确知道超链接上的文本信息或者只想通过一些关键字进行匹配时,可以使用这个方法来通过部分链接文字进行匹配。代码如下:

    public class SearchElementsByPartialLinkText{
        public static void main(String[] args){
            WebDriver driver = new FirefoxDriver();
            driver.get("http://www.forexample.com");
            WebElement aboutLink = driver.findElement(By.partialLinkText("About"));
            aboutLink.click();
        }
    }

    注意:使用这种方法进行定位时,可能会引起的问题是,当你的页面中不止一个超链接包含About时,findElement方法只会返回第一个查找到的元素,而不会返回所有符合条件的元素。如果你要想获得所有符合条件的元素,还是只能使用findElements方法。


    7. By.xpath()

    这个方法是非常强大的元素查找方式,使用这种方法几乎可以定位到页面上的任意元素。在正式开始使用XPath进行定位前,我们先了解下什么是XPath。XPath是XML Path的简称,由于HTML文档本身就是一个标准的XML页面,所以我们可以使用XPath的语法来定位页面元素。

    假设我们现在以图(2)所示HTML代码为例,要引用对应的对象,XPath语法如下:


    绝对路径写法(只有一种),写法如下:

    引用页面上的form元素(即源码中的第3行):/html/body/form[1]

    注意:1. 元素的xpath绝对路径可通过firebug直接查询。2. 一般不推荐使用绝对路径的写法,因为一旦页面结构发生变化,该路径也随之失效,必须重新写。3. 绝对路径以单/号表示,而下面要讲的相对路径则以//表示,这个区别非常重要。另外需要多说一句的是,当xpath的路径以/开头时,表示让Xpath解析引擎从文档的根节点开始解析。当xpath路径以//开头时,则表示让xpath引擎从文档的任意符合的元素节点开始进行解析。而当/出现在xpath路径中时,则表示寻找父节点的直接子节点,当//出现在xpath路径中时,表示寻找父节点下任意符合条件的子节点,不管嵌套了多少层级(这些下面都有例子,大家可以参照来试验)。弄清这个原则,就可以理解其实xpath的路径可以绝对路径和相对路径混合在一起来进行表示,想怎么玩就怎么玩

     

    下面是相对路径的引用写法:

    查找页面根元素://

    查找页面上所有的input元素://input

    查找页面上第一个form元素内的直接子input元素(即只包括form元素的下一级input元素,使用绝对路径表示,单/号)://form[1]/input

    查找页面上第一个form元素内的所有子input元素(只要在form元素内的input都算,不管还嵌套了多少个其他标签,使用相对路径表示,双//号)://form[1]//input

    查找页面上第一个form元素://form[1]

    查找页面上id为loginForm的form元素://form[@id='loginForm']

    查找页面上具有name属性为username的input元素://input[@name='username']

    查找页面上id为loginForm的form元素下的第一个input元素://form[@id='loginForm']/input[1]

    查找页面具有name属性为contiune并且type属性为button的input元素://input[@name='continue'][@type='button']

    查找页面上id为loginForm的form元素下第4个input元素://form[@id='loginForm']/input[4]

    Xpath功能很强大,所以也可以写得更加复杂一些,如下面图(3)的HTML源码。

     

    如果我们现在要引用id为“J_password”的input元素,该怎么写呢?我们可以像下面这样写:

    WebElement password = driver.findElement(By.xpath("//*[@id='J_login_form']/dl/dt/input[@id='J_password']"));

    前面讲的都是xpath中基于准确元素属性的定位,其实xpath作为定位神器也可以用于模糊匹配。比如下面图(4)所示代码:


    这段代码中的“退出”这个超链接,没有标准id元素,只有一个rel和href,不是很好定位。不妨我们就用xpath的几种模糊匹配模式来定位它吧,主要有三种方式,举例如下

    a. 用contains关键字,定位代码如下:

    driver.findElement(By.xpath(“//a[contains(@href, ‘logout’)]”));

    这句话的意思是寻找页面中href属性值包含有logout这个单词的所有a元素,由于这个退出按钮的href属性里肯定会包含logout,所以这种方式是可行的,也会经常用到。其中@后面可以跟该元素任意的属性名。

    b. 用start-with,定位代码如下:

    driver.findElement(By.xpath(“//a[starts-with(@rel, ‘nofo’)]));

    这句的意思是寻找rel属性以nofo开头的a元素。其中@后面的rel可以替换成元素的任意其他属性。

    c. 用Text关键字,定位代码如下:

    driver.findElement(By.xpath(“//*[text()=’退出’]));

    这个方法可谓相当霸气啊。直接查找页面当中所有的退出二字,根本就不用知道它是个a元素了。这种方法也经常用于纯文字的查找。

    另外,如果知道超链接元素的文本内容,也可以用

    driver.findElement(By.xpath(“//a[contains(text(), ’退出’)]));

    这种方式一般用于知道超链接上显示的部分或全部文本信息时,可以使用。

     

    最后,关于xpath这种定位方式,webdriver会将整个页面的所有元素进行扫描以定位我们所需要的元素,所以这是一个非常费时的操作,如果你的脚本中大量使用xpath做元素定位的话,将导致你的脚本执行速度大大降低,所以请慎用。


    8. By.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方式来引用图(3)中选中的那个input对象,代码如下:

    WebElement password = driver.findElement(By.cssSelector("#J_login_form>dl>dt>input[id=’ J_password’]"));

    同样必须注意层级关系,这个不能省略。

     

    cssSelector还有一个用处是定位使用了复合样式表的元素,之前在第4种方式className里面提到过。现在我们就来看看如何通过cssSelector来引用到第4种方式中提到的那个button。button代码如下:

    <button id="J_sidebar_login" class="btn btn_big btn_submit" type="submit">登录</button>


    cssSelector引用元素代码如下:

    driver.findElement(By.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']

     

    最后再总结一下,各种方式在选择的时候应该怎么选择:

    1. 当页面元素有id属性时,最好尽量用id来定位。但由于现实项目中很多程序员其实写的代码并不规范,会缺少很多标准属性,这时就只有选择其他定位方法。

    2. xpath很强悍,但定位性能不是很好,所以还是尽量少用。如果确实少数元素不好定位,可以选择xpath或cssSelector。

    3. 当要定位一组元素相同元素时,可以考虑用tagName或name。

    4. 当有链接需要定位时,可以考虑linkText或partialLinkText方式。


    展开全文
  • Selenium Webdriver元素定位的八种常用方式

    万次阅读 多人点赞 2015-01-10 10:31:37
    在使用selenium webdriver进行元素定位时,通常使用findElement或findElements方法结合By类返回的元素句柄来定位元素。其中By类的常用定位方式共八种,现分别介绍如下。 1. By.name() 页面源码如下: <...

    楼主原创,分享不易,转载请注明,谢谢。

     

    在使用selenium webdriver进行元素定位时,通常使用findElement或findElements方法结合By类返回的元素句柄来定位元素。其中By类的常用定位方式共八种,现分别介绍如下。

     

    1. By.name()

    页面源码如下:

    <button id="gbqfba"aria-label="Google Search" name="btnK" class="gbqfba"><spanid="gbqfsa">Google Search</span></button>

     

    当我们要用name属性来引用这个button并点击它时,代码如下:

     

    public class SearchButtonByName {
    
        public static void main(String[] args){
    
            WebDriver driver = new FirefoxDriver();
    
            driver.get("http://www.forexample.com");
    
            WebElement searchBox =driver.findElement(By.name("btnK"));
    
            searchBox.click();
    
        }
    
    }

     

    2. By.id()

     

    页面源码如下:

    <button id="gbqfba" aria-label="GoogleSearch" name="btnK" class="gbqfba"><spanid="gbqfsa">Google Search</span></button>

     

    要引用该button并点击它时,代码如下:

     

    public class SearchButtonById {
    
        public static void main(String[] args){
    
            WebDriver driver = new FirefoxDriver();
    
            driver.get("http://www.forexample.com");
    
            WebElement searchBox =driver.findElement(By.id("gbqfba"));
    
            searchBox.click();
    
        }
    
    }

     

    3. By.tagName()

     

    该方法可以通过元素的标签名称来查找元素。该方法跟之前两个方法的区别是,这个方法搜索到的元素通常不止一个,所以一般建议结合使用findElements方法来使用。比如我们现在要查找页面上有多少个button,就可以用button这个tagName来进行查找,代码如下:

    public class SearchPageByTagName{
    
        public static void main(String[] args){
    
            WebDriver driver = new FirefoxDriver();
    
            driver.get("http://www.forexample.com");
    
            List<WebElement> buttons =driver.findElements(By.tagName("button"));
    
            System.out.println(buttons.size());  //打印出button的个数
    
        }
    
    }

     

    另外,在使用tagName方法进行定位时,还有一个地方需要注意的是,通常有些HTML元素的tagName是相同的,如下图(1)所示。

     

    图(1)

     

    从图中我们可以看到,单选框、复选框、文本框和密码框的元素标签都是input,此时单靠tagName无法准确地得到我们想要的元素,需要结合type属性才能过滤出我们要的元素。示例代码如下:

    public class SearchElementsByTagName{
    
        public static void main(String[] args){
    
            WebDriver driver = new FirefoxDriver();
    
            driver.get("http://www.forexample.com");
    
            List<WebElement> allInputs =driver.findElements(By.tagName("input"));
    
            //只打印所有文本框的值
    
            for(WebElement e: allInputs){
    
               if(e.getAttribute(“type”).equals(“text”)){
    
                    System.out.println(e.getText().toString());  //打印出每个文本框里的值
    
            }
    
       }
    
    }
    
    }

     

     

    4. By.className()

     

     

    className属性是利用元素的css样式表所引用的伪类名称来进行元素查找的方法。对于任何HTML页面的元素来说,一般程序员或页面设计师会给元素直接赋予一个样式属性或者利用css文件里的伪类来定义元素样式,使元素在页面上显示时能够更加美观。一般css样式表可能会长成下面这个样子:

    .buttonStyle{
        width: 50px;
        height: 50px;
        border-radius: 50%;
        margin: 0% 2%;
    }

     

    定义好后,就可以在页面元素中引用上述定义好的样式,如下:

     

     

    <buttonname="sampleBtnName" id="sampleBtnId" class="buttonStyle">I'mButton</button>

     

     

     

    如果此时我们要通过className属性来查找该button并操作它的话,就可以使用className属性了,代码如下:

    public class SearchElementsByClassName{
    
        public static void main(String[] args){
    
            WebDriver driver = new FirefoxDriver();
    
            driver.get("http://www.forexample.com");
    
            WebElement searchBox =driver.findElement(By.className("buttonStyle"));
    
            searchBox.sendKeys("Hello, world");
    
        }
    
    }

     

    注意:使用className来进行元素定位时,有时会碰到一个元素指定了若干个class属性值的“复合样式”的情况,如下面这个button:

     

    <button id="J_sidebar_login" class="btn btn_bigbtn_submit" type="submit">登录</button>

    这个button元素指定了三个不同的css伪类名作为它的样式属性值,此时就必须结合后面要介绍的cssSelector方法来定位了,稍后会有详细例子。

     

     

    5. By.linkText()

    这个方法比较直接,即通过超文本链接上的文字信息来定位元素,这种方式一般专门用于定位页面上的超文本链接。通常一个超文本链接会长成这个样子:<a href="/intl/en/about.html">About Google</a>。我们定位这个元素时,可以使用下面的代码进行操作:

    public class SearchElementsByLinkText{
    
        public static void main(String[] args){
    
            WebDriver driver = new FirefoxDriver();
    
            driver.get("http://www.forexample.com");
    
            WebElement aboutLink = driver.findElement(By.linkText("AboutGoogle"));
    
            aboutLink.click();
    
        }
    
    }

     

    6. By.partialLinkText()

     

    这个方法是上一个方法的扩展。当你不能准确知道超链接上的文本信息或者只想通过一些关键字进行匹配时,可以使用这个方法来通过部分链接文字进行匹配。代码如下:

    public class SearchElementsByPartialLinkText{
    
        public static void main(String[] args){
    
            WebDriver driver = new FirefoxDriver();
    
            driver.get("http://www.forexample.com");
    
            WebElement aboutLink = driver.findElement(By.partialLinkText("About"));
    
            aboutLink.click();
    
        }
    
    }

     

    注意:使用这种方法进行定位时,可能会引起的问题是,当你的页面中不止一个超链接包含About时,findElement方法只会返回第一个查找到的元素,而不会返回所有符合条件的元素。如果你要想获得所有符合条件的元素,还是只能使用findElements方法。

     

     

    7. By.xpath()

    这个方法是非常强大的元素查找方式,使用这种方法几乎可以定位到页面上的任意元素。在正式开始使用XPath进行定位前,我们先了解下什么是XPath。XPath是XML Path的简称,由于HTML文档本身就是一个标准的XML页面,所以我们可以使用XPath的语法来定位页面元素。

    假设我们现在以图(2)所示HTML代码为例,要引用对应的对象,XPath语法如下:

    图(2)

    绝对路径写法(只有一种),写法如下:

    引用页面上的form元素(即源码中的第3行):/html/body/form[1]

    这里要注意以下几点:

    1. 元素的xpath绝对路径可通过firebug直接查询,一般不需要你手工去写。

    2. 一般不推荐使用绝对路径的写法,因为一旦页面结构发生变化,该路径也随之失效,必须重新写。

    3. 绝对路径以单/号表示,而下面要讲的相对路径则以//表示,这个区别非常重要。另外需要多说一句的是,当xpath的路径以/开头时,表示让Xpath解析引擎从文档的根节点开始解析。当xpath路径以//开头时,则表示让xpath引擎从文档的任意符合的元素节点开始进行解析。而当/出现在xpath路径中时,则表示寻找父节点的直接子节点,当//出现在xpath路径中时,表示寻找父节点下任意符合条件的子节点,不管嵌套了多少层级(这些下面都有例子,大家可以参照来试验)。弄清这个原则,就可以理解其实xpath的路径可以绝对路径和相对路径混合在一起来进行表示,想怎么玩就怎么玩。

     

    下面是相对路径的引用写法:

    查找页面根元素://

    查找页面上所有的input元素://input

    查找页面上第一个form元素内的直接子input元素(即只包括form元素的下一级input元素,使用绝对路径表示,单/号)://form[1]/input

    查找页面上第一个form元素内的所有子input元素(只要在form元素内的input都算,不管还嵌套了多少个其他标签,使用相对路径表示,双//号)://form[1]//input

    查找页面上第一个form元素内的最后一个input元素://form[1]//input[last()](注意:在xpath中没有first()这样的方法,用//form[1]//input[1]这种表示法就可以取第一个)

    查找页面上第一个form元素://form[1]

    查找页面上id为loginForm的form元素://form[@id='loginForm']

    查找页面上具有name属性为username的input元素://input[@name='username']

    查找页面上id为loginForm的form元素下的第一个input元素://form[@id='loginForm']/input[1](注意:在xpath中没有第0元素这样的表示方法,都是从1开始)

    查找页面具有name属性为contiune并且type属性为button的input元素://input[@name='continue'][@type='button']

    查找页面上id为loginForm的form元素下第4个input元素://form[@id='loginForm']/input[4]

    Xpath功能很强大,所以也可以写得更加复杂一些,如下面图(3)的HTML源码。

    图(3)

    如果我们现在要引用id为“J_password”的input元素,该怎么写呢?我们可以像下面这样写:

     

    WebElement password = driver.findElement(By.xpath("//*[@id='J_login_form']/dl/dt/input[@id='J_password']"));

     

    也可以写成:

     

    WebElement password =driver.findElement(By.xpath("//*[@id='J_login_form']/*/*/input[@id='J_password']"));

     

    这里解释一下,其中//*[@id=’J_login_form’]这一段是指在根元素下查找任意id为J_login_form的元素,此时相当于引用到了form元素。后面的路径必须按照源码的层级依次往下写。因为我们要找的input元素包含在一个dt标签内,而dt又包含在dl标签内,所以中间必须写上dl和dt两层,才到input这层。当然我们也可以用*号省略具体的标签名称,但元素的层级关系必须体现出来,比如我们不能写成//*[@id='J_login_form']/input[@id='J_password'],这样肯定会报错的。

     

    前面讲的都是xpath中基于准确元素属性的定位,其实xpath作为定位神器也可以用于模糊匹配。比如下面图(4)所示代码:

    图(4)

    这段代码中的“退出”这个超链接,没有标准id元素,只有一个rel和href,不是很好定位。不妨我们就用xpath的几种模糊匹配模式来定位它吧,主要有三种方式,举例如下。

    a. 用contains关键字,定位代码如下:

     

    driver.findElement(By.xpath(“//a[contains(@href,‘logout’)]”));

     

    这句话的意思是寻找页面中href属性值包含有logout这个单词的所有a元素,由于这个退出按钮的href属性里肯定会包含logout,所以这种方式是可行的,也会经常用到。其中@后面可以跟该元素任意的属性名。

     

    b. 用start-with,定位代码如下:

     

    driver.findElement(By.xpath(“//a[starts-with(@rel, ‘nofo’)]));

     

    这句的意思是寻找rel属性以nofo开头的a元素。其中@后面的rel可以替换成元素的任意其他属性。

     

    c. 用Text关键字,定位代码如下:

     

    driver.findElement(By.xpath(“//*[text()=’退出’]));

     

    这个方法可谓相当霸气啊。直接查找页面当中所有的退出二字,根本就不用知道它是个a元素了。这种方法也经常用于纯文字的查找。

    另外,如果知道超链接元素的文本内容,也可以用

    driver.findElement(By.xpath(“//a[contains(text(), ’退出’)])); 

     

    这种方式一般用于知道超链接上显示的部分或全部文本信息时,可以使用。

     

    最后,关于xpath这种定位方式,webdriver会将整个页面的所有元素进行扫描以定位我们所需要的元素,所以这是一个非常费时的操作,如果你的脚本中大量使用xpath做元素定位的话,将导致你的脚本执行速度大大降低,所以请慎用。

     

    8. By.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方式来引用图(3)中选中的那个input对象,代码如下:

     

    WebElement password =driver.findElement(By.cssSelector("#J_login_form>dl>dt>input[id=’J_password’]"));

     

    同样必须注意层级关系,这个不能省略。

     

    cssSelector还有一个用处是定位使用了复合样式表的元素,之前在第4种方式className里面提到过。现在我们就来看看如何通过cssSelector来引用到第4种方式中提到的那个button。button代码如下:

     

    <button id="J_sidebar_login"class="btn btn_big btn_submit" type="submit">登录</button>

     

    cssSelector引用元素代码如下:

     

    driver.findElement(By.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']

     

    最后再总结一下,各种方式在选择的时候应该怎么选择:

    1. 当页面元素有id属性时,最好尽量用id来定位。但由于现实项目中很多程序员其实写的代码并不规范,会缺少很多标准属性,这时就只有选择其他定位方法。

    2. xpath很强悍,但定位性能不是很好,所以还是尽量少用。如果确实少数元素不好定位,可以选择xpath或cssSelector。

    3. 当要定位一组元素相同元素时,可以考虑用tagName或name。

    4. 当有链接需要定位时,可以考虑linkText或partialLinkText方式。

     

    参考资料:

    《Selenium Webdriver PracticalGuide》

    https://saucelabs.com/resources/selenium/css-selectors

    欢迎大家关注我的公众号:Python极客栈

    公众号二维码

    展开全文
  • 进行Web页面自动化测试,对页面上的元素进行定位和操作是核心。而操作又有时以定位为前提的,因此,...webdriver就是利用元素的这些属性来进行定位的。 可以用于定位的常用的元素属性: idnameclass nametag namelin

    进行Web页面自动化测试,对页面上的元素进行定位和操作是核心。而操作又是以定位为前提的,因此,对页面元素的定位是进行自动化测试的基础。

    页面上的元素就像人一样,有各种属性,比如元素名字,元素id,元素属性(class属性,name属性)等等。webdriver就是利用元素的这些属性来进行定位的。

    可以用于定位的常用的元素属性:

    • id
    • name
    • class name
    • tag name
    • link text
    • partial link text
    • xpath
    • css selector
    对应于webdriver中的定位方法分别是:
    • driver.find_element_by_name()——最常用,简单
    • driver.find_element_by_id()——最常用,简单
    • driver.find_element_by_class_name()
    • driver.find_element_by_tag_name()——最不靠谱
    • driver.find_element_by_link_text()——定位文字连接好用
    • driver.find_element_by_partial_link_text()——定位文字连接好用
    • driver.find_element_by_xpath()——最灵活,万能
    • driver.find_element_by_css_selector()
    上面是定位一个元素的方法,相应的webdriver也有定位一组元素的方法:
    • driver.find_elements_by_name()
    • driver.find_elements_by_id()
    • driver.find_elements_by_class_name()
    • driver.find_elements_by_tag_name()
    • driver.find_elements_by_link_text()
    • driver.find_elements_by_partial_link_text()
    • driver.find_elements_by_xpath()
    • driver.find_elements_by_css_selector()
    那么问题来了?怎么查看元素的name,id,class,tag,text,xpath,css选择器呢?可以借助firefox浏览器的firebug插件(需要手动安装)中firepath工具或者chrome的开发者工具(chrome自带)。
    • Friebug
    打开firefox 浏览器的firebug 插件,点击插件左上角的鼠标箭头,再点击页面上的元素,firebug插件的HTML 标签页将看到页面代码,鼠标移动到元素的标签上点击一下。例如我们点击百度首页的“百度一下”按钮:

    从FirePath中可以看到该元素的id,tag,class等属性。

    • Chrome开发者工具(F12)
    打开Chrome浏览器,按下键盘的F12,即可以打开开发者工具。从开发者工具中可以得到和FirePath相同的结果:


    那么问题又来了,这么多属性都可以用来定位,那么我们选择哪种呢?其实,定位元素的方法没有好坏之分,不同的场景有不同的适用方法,只要定位的唯一的一个元素的方法都是可以使用的。
    • id 和name 定位
    这是简单的高效的方法。
    比如定位百度首页文本框的方法,我们可以使用id来定位(该元素提供的id属性,可以唯一定位到它):
    driver.find_element_by_id('kw')
    定位百度首页右上角的“设置”链接,我们可以使用name来定位(该元素提供的name属性,可以唯一定位到它):
    driver.find_element_by_name('tj_trnews')
    • class name和tag name定位
    不是所有的前端开发人员都喜欢为每一个元素添加id 和name 两个属性,但除此之外你一定发现了一个元素不单单只有id 和name,它还有class 属性;而且每个元素都会有tag标签。
    还是定位百度首页的文本框,除了用id方法定位之外,我们还可以用class name来定位(该元素提供的class属性,也可以唯一定位到它)。
    driver.find_element_by_class_name("s_ipt")
    tag name 定位应该是所有定位方式中最不靠谱的一种了,因为在一个页面中具有相同tag name 的元素极其容易出现,很少具有唯一性。不用学习它了。
    • link text 与partial link text 定位
    有时候需要操作的元素是一个文字链接,那么我们可以通过link text 或partial link text 进行元素定位。
    比如,定位百度首页右上角的“新闻”,“hao123”,。。。。等等这些文字连接。就可以使用link text和partail link text定位方式。可以先使用FireBug看下网页源码:


    通过linx text定位:
    find_element_by_link_text("新闻")
    find_element_by_link_text("贴吧")
    通过partail link text定位:
    find_element_by_link_text("新")
    find_element_by_link_text("贴")
    • XPath 定位
    XPath是一种文档定位语言。因为HTML可以看做是XML的一种实现,所以selenium用户可使用这种强大的语言在web应用中定位。
    绝对路径方法:
    从根元素写起,当元素层级很深的时候,路径写的会很长,阅读性不好,也很难维护。不建议使绝对路径这样的方法。
    相对路径方法:
    通过Firebug很容易得到相对路径的xpath,打开Firebug插件,在页面上的搜索文本框,就可以显示出xpath了:
    <pre name="code" class="python">driver.find_element_by_xpath("//*[@id='kw']").click()
    
    上面的写法可以理解为,通过xpath寻找,任意(*代表)id属性为’kw‘的元素。当然我们也可以把*替换成input,即:
    driver.find_element_by_xpath("//input[@id='kw']").click()
    这种写法可以理解为,通过xpath寻找,任意id属性为’kw‘的input元素。
    有的时候,需要根据上级目录的属性来定位当前元素:
    find_element_by_xpath("//span[@id=’input-container’]/input") #通过上一级目录的id 属性定位
    find_element_by_xpath("//div[@id=’hd’]/form/span/input") #通过上三级目录的id 属性定位
    find_element_by_xpath("//div[@name=’q’]/form/span/input")#通过上三级目录的name 属性定位
    • CSS定位
    这种定位方法是比较难理解的。TBD,当前工作中也没有遇到,必须使用这种方式才能定位到元素的情况。

    • 关于自动化的定位问题
    自动化测试的元素定位一直是困扰自动化测试新手的一个障碍,因为我们在自动化实施过程中会碰到各式各样的对象元素。虽然XPath 和CSS 可以定位到复杂且比较难定位的元素,但相比较用id 和name 来说增加了维护成本和学习成本,相比较来说id/name 的定位方式更直观和可维护,有新的成员加入的自动化时也增加了人员的学习成本。所以,测试人员在实施自动化测试时一定要做好沟通,规范前端开发人员对元素添加id/name 属性,或者自己有修改HTML 代码的权限。

    展开全文
  • Selenium webdriver 元素定位方法总结

    千次阅读 2016-07-01 13:46:29
    input id="kw" class="s_ipt" autocomplete="off" maxlength="255" value="" name="wd"/> 新闻板块 ...from selenium import webdriver 1. find_element_by_id("kw") 2. find_element_by_name(
  • webdriver定位页面元素的8种方式 find_element_by_id() find_element_by_name() find_element_by_class_name() find_element_by_tag_name() #标签 find_element_by_link_text() #文本链接 find_element_by_partial_...
  • 在使用selenium webdriver进行元素定位时,通常使用findElement或findElements方法结合By类返回的元素句柄来定位元素。其中By类的常用定位方式共八种,现分别介绍如下。 1. By.name() 假设我们要测试的页面源码如下...
  • Python+selenium+webdriver元素定位

    千次阅读 2018-07-27 16:24:03
    通过class定位 driver.find_element_by_class_name("") 通过id与name定位 driver.find_element_by_id("") ​ driver.find_element_by_id("") 通过tag_name定位 #定位标签名为...
  • Selenium Webdriver元素定位的方式

    千次阅读 2016-05-12 11:20:09
    Selenium Webdriver元素定位的方式主要就是By类的1、By.name()## html代码如下:<button id="gbqfba" aria-label="Google Search" name="btnK" class="gbqfba"><span id="gbqfsa">Google Search</span></button> 用...
  • 在使用selenium webdriver进行元素定位时,通常使用findElement或findElements方法结合By类返回的元素句柄来定位元素。其中By类的常用定位方式共八种,现分别介绍如下。 1. By.name() 假设我们要测试的页面源码...
  • 定位元素先要掌握基本的HTML语法: http://blog.csdn.net/jojoy_tester/article/details/53222425 http://blog.csdn.net/jojoy_tester/article/details/53228674 webdriver属于selenium体系中设计出来操作浏览器...
  • WebDriver属于Selenium体系中设计出来操作浏览器的一套API,站在WebDriver的角度,因为它针对多种编程语言都实现了一遍这套API,所以它可以支持多种编程语言;站在编程语言的角度,WebDriver是Python的一个用于实现...
  • 版权声明:本文为博主原创文章,欢迎转赞,但请保留作者...而操作又是以定位为前提的,因此,对页面元素定位是进行自动化测试的基础。 页面上的元素就像人一样,有各种属性,比如元素名字,元素id,元素属性(c...
  • webdriver提供了丰富的API,有多种定位策略:id,name,css选择器,xpath等,其中css选择器定位元素效率相比xpath要高些,使用id,name属性定位元素是最可靠,效率最高的一种办法。  1、工具选择:在我们开发测试...
  • webdriver属于Selenium体系中设计出来操作浏览器的一套API,支持多种语言,本文中主要讲解为对元素定位,不涉及具体语言,在某些不同语言中有差异性的地方,本文使用python语言作为示例(比如xpath中的部分语句)...
  • 在使用selenium webdriver进行元素定位时,通常使用findElement或findElements方法结合By类返回的元素句柄来定位元素。其中By类的常用定位方式共八种,现分别介绍如下。 1. By.name() 假设我们要测试的页面...
1 2 3 4 5 ... 20
收藏数 2,722
精华内容 1,088
关键字:

webdriver 定位form元素