• Selenium学习(2) 元素定位


    元素的定位是自动化测试的核心,想要操作一个元素,首先应该识别这个元素。
    webdriver提供一个一系列的元素定位方法,常用的有以下几种:
    id
    name
    class name
    link text
    partial link text
    tag name
    xpath
    css selector
    Frame 嵌套页面元素定位
    By
    元素定位:id、name、class_name


    示例:
    from selenium import webdriver
    from time import sleep

    driver = webdriver.Chrome()

    driver.get("www.baidu.com")
    sleep(2)

    #driver.find_element_by_id("kw").send_keys("测试一")
    #driver.find_element_by_name("wd").send_keys("测试二")
    driver.find_element_by_class_name("s_ipt").send_keys("测试三")
    sleep(3)
    driver.find_element_by_id("su").click()
    sleep(3)

    driver.quit()

    元素定位:link_text
    示例:
    from selenium import webdriver
    from time import sleep

    driver = webdriver.Chrome()

    driver.get("www.baidu.com")
    sleep(2)

    driver.find_element_by_link_text("新闻").click()
    sleep(2)
    driver.find_element_by_link_text("汽车").click()
    sleep(3)

    driver.quit()

    元素定位:tag_name
    示例:
    from selenium import webdriver
    from time import sleep

    driver = webdriver.Chrome()

    driver.get("www.baidu.comt")
    sleep(2)

    #driver.find_element_by_tag_name("input").send_keys("test")
    driver.find_elements_by_tag_name("input")[0].send_keys("test")
    sleep(3)

    driver.quit()
    元素定位:xpath
    ---绝对与相对路径
    from selenium import webdriver
    from time import sleep

    driver = webdriver.Chrome()

    driver.get("https://www.baidu.com")
    sleep(2)

    # 绝对路径定位,不建议使用
    #driver.find_element_by_xpath("/html/body/div/[1]/div/div[3]/div/div/from/span/input").send_keys("test")

    # 利用元素熟悉定位--定位到标签id、namne、class中的kw、wd、s_ipt元素
    driver.find_element_by_xpath("//input[@id='kw']").send_keys("test1")
    sleep(2)
    driver.find_element_by_xpath("//input[@name='wd']").send_keys("test2")
    sleep(2)
    driver.find_element_by_xpath("//input[@class='s_ipt']").send_keys("test3")
    sleep(2)
    driver.find_element_by_id("su").click()
    sleep(2)
    driver.quit()

    ---层级与逻辑组合
    from selenium import webdriver
    from time import sleep
    driver = webdriver.Chrome()
    driver.get("www.baidu.com")
    sleep(2)

    # 层级和属性结合定位
    # // 代表当前页面
    # [1]代表第一个元素,和数组不一样
    driver.find_element_by_xpath("//form[@id='loginForm']/ul/input[1]").send_keys("name1")
    sleep(2)
    driver.find_element_by_xpath("//form[@id='loginForm']/ul/input[2]").send_keys("password")
    sleep(2)

    # 逻辑运算组合定位
    driver.find_element_by_xpath("//input[@class='loinp' and @name='username']").send_keys("name2")
    sleep(2)
    driver.quit()


    Css定位

    推荐使用CSS定位,而不是Xpath来定位元素,原因是CSS定位比XPath定位速度快,语法也更加简洁。

    语法:find_element_by_css_selector()
    #id id选择器根据 id 属性来定位元素()
    .class class选择器,根据class属性值来定位元素
    [attribute='vlaue'] 根据属性来定位元素
    element>element 根据元素层级来定位 父元素>子元素

    示例:
    from selenium import webdriver
    from time import sleep

    driver = webdriver.Chrome()

    driver.get("www.baidu.com")
    sleep(2)

    # 根据 id 来定位
    driver.find_element_by_css_selector("#kw").send_keys("test1")
    # 根据 class 来定位
    driver.find_element_by_css_selector(".s_ipt").send_keys("test2")
    # 根据 属性 来定位
    driver.find_element_by_css_selector("[autocomplete='off']").send_keys("test3")
    sleep(2)

    driver.find_element_by_id('su').click


    driver.get("www.baidu.com")
    sleep(2)

    # 通过元素层级来定位
    driver.find_element_by_css_selector("form#loginForm>ul>input").send_keys("test")
    sleep(2)

    driver.quit()


    Frame嵌套页面元素定位

    找到页面也中的 frame

    # search 是 frame中的id值
    使用命令: driver.switch.to.frame("search")

    然后进行元素定位

    元素定位:By
    示例:
    from selenium import webdriver
    from time import sleep
    from selenium.webdriver.common.by import By
    driver = webdriver.Chrome()
    driver.get("www.baidu.com")
    sleep(2)
    driver.find_element(By.ID,"kw").send_keys("测试一")
    sleep(2)
    driver.find_element(By.NAME,"wd").send_keys("测试二")
    sleep(2)
    driver.find_element(By.CLASS_NAME,"s_ipt").send_keys("测试三")
    sleep(3)
    driver.find_element(By.XPATH,"//[@class='s_ipt']").send_keys("测试三")
    sleep(3)
    driver.find_element(By.ID,"su").click()
    sleep(3)

    driver.quit()

    By.xpath()
    driver.quit()

    这个方法是非常强大的元素查找方式,使用这种方法几乎可以定位到页面上的任意元素。在正式开始使用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']"));
    也可以写成:

    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方式。

  • 相关阅读:
    mongoTemplate.aggregate()聚合查询
    解决ElasticSearch5.x中@Field注解之IK分词不能用的问题
    Mybatis中使用Enum传参
    过滤,去重filter,去重reduce
    自己写的数组 方法的组合使用
    uni-app 使用vuex的方法
    uni-app实战写法
    vue的bug问题
    vuex
    vue webapp的基本功能实现方法
  • 原文地址:https://www.cnblogs.com/peng-lan/p/9604603.html
Copyright © 2020-2023  润新知