UI自动化(七)selenium元素定位

一、基本元素定位方式

find_element_by_id()        id属性定位

find_element_by_name()        name属性定位

find_element_by_class_name()        class_name属性定位

find_element_by_xpath()        元素路径定位

find_element_by_css_selector()       css定位 

find_element_by_tag_name()        tag_name定位

find_element_by_link_text()        完整的超链接文字定位

find_element_by_partial_link_text()        部分超链接文字定位

1、find_element_by_id()、find_element_by_name()、find_element_by_class_name()

在前端代码中,id、name和class一般都至少会有其中的一种

2、find_element_by_xpath()  

xpath是XML路径语言,它可以用来确定xml文档中的元素位置,通过元素的路径来完成对元素的查找。HTML就是XML的一种实现方式。

xpath也分几种不同类型的定位方法。

(1)绝对路径定位

这种定位方式是利用html标签名的层级关系来定位元素的绝对路径,一般从<html>标签开始依次往下进行查找。

百度搜索框的绝对路径xpath定位可以是这样的:find_element_by_xpath("/html/body/div[1]/div[1]/div/div[1]/div/form/span[1]/input")

(2)利用元素属性定位

例如:find_element_by_xpath("//input[@id='kw']")

其中的标签名input也可以用*来代替,而且只要是在该标签内,任意属性都可以,比如搜索框的maxlength属性:find_element_by_xpath("//input[@maxlength='255']")

(3)绝对路径+元素属性定位

有的时候我们会发现绝对路径定位路径太长,而且光凭路径完全不可以猜测到其指向的具体页面元素,如果只有单纯的元素属性不一定可以每次查找的元素都可以又唯一的属性去方便定位,这个时候我们可以将这两种定位方式结合起来使用。

比如查找搜索框的时候发现其上级元素form有唯一的id属性进行定位,就可以先查找到form元素然后依次往下写路径:find_element_by_xpath("//form[@id='form']/span/input")

这种定位方式的使用过程中,如果元素的单个属性无法确定其唯一性,可以用and连接多个属性去确定。例如:find_element_by_xpath("//form[@id='form'and@classname='form']/span/input")

***xpath常用函数

sibling 提取指定元素的所有同级元素

child 选取当前节点的所有子节点

parent 选取当前节点的父节点

descendant 选取当前节点的所有后代节点

ancestor 选取当前节点的所有先辈节点

descendant-or-self 选取当前节点的所有后代节点及当前节点本身

ancestor-or-self 选取当前节点所有先辈节点及当前节点本身

preceding-sibling 选取当前节点之前的所有同级节点

following-sibling 选取当前节点之后的所有同级节点

preceding 选取当前节点的开始标签之前的所有节点

following 选去当前节点的开始标签之后的所有节点

self 选取当前节点

attribute 选取当前节点的所有属性

namespace 选取当前节点的所有命名空间节点

例如:driver.find_element_by_xpath(u"//div/a[contains(text(), '%s')]/following-sibling::*"%u"新闻")

3、find_element_by_css_selector()  

CSS属性定位可以比较灵活地选择控件的任意属性,定位方式也会比xpath快。例如:

driver.find_element_by_css_selector(".s_ipt").send_keys("selenium")

driver.find_element_by_css_selector("#su").click()

一般class是用.标记,id是用#标记,标签名直接写具体标签名即可。使用该定位建议了解一下CSS的基础选择器知识。

css定位里面也可以通过属性或者组合方式定位。例如:

driver.find_element_by_css_selector("input[autocomplete='off']").send_keys("Python")

driver.find_element_by_css_selector("span.bg.s_btn_wr>input#su").click()

分析一下第二个定位:这样写的定位顺序是这样的,先定位到一个class名为bg s_btn_wr的span标签,在这个标签下面有一个id为su的input标签。值得注意的是,在css里面下级标签元素用>连接,如果class里面有空格,空格用.进行连接。

4、find_element_by_tag_name()

通过标签名去定位的方式一般是这样的: find_element_by_tag_name("input")

一般一种标签在一个页面里面会出现不止一次甚至大量出现,这种定位方式需要分场景使用,一般很少使用。

5、find_element_by_link_text()、find_element_by_partial_link_text()

这两种定位方式是专门用于定位超链接的,也就是对应html页面中的<a>标签,括号里传的值就是a标签中的超链接文字,两者的区别在于一个是完整的超链接文字,一个是可以只写部分超链接文字。例如:

driver.find_element_by_link_text("新闻").click()

driver.find_element_by_partial_link_text("闻").click()

二、By定位方式

find_element(By.ID,"kw")

find_element(By.NAME,"wd")

find_element(By.CLASS_NAME,"s_ipt")

find_element(By.TAG_NAME,"input")

find_element(By.LINK_TEXT,u"新闻 ")

find_element(By.PARTIAL_LINK_TEXT,u"新 ")

find_element(By.XPATH,"//*[@class='bg s_btn']")

find_element(By.CSS_SELECTOR,"span.bg s_btn_wr>input#su")

上面这些使用的前提是需要导入By类:from selenium.webdriver.common.by import By 

By定位其实就是基本元素定位的一个封装,使用By定位的好处在于PO模式的再封装不需要罗列大量的基本元素定位方法。

其中By.ID = "id",这种转换可以在代码中进行打印验证。

也就是说find_element(By.ID,"kw")其实可以直接写成find_element("id","kw")

三、elements复数定位

以上所有的定位方式element未加s,得到的其实是单个元素对象,所有的定位方式加上s均可得到元素对象列表,通过下标进行提取。例如:driver.find_elements("css selector",".mnav")[6].click()

四、JS定位方式

id定位:document.getElementById()

name定位:document.getElementsByName()

tag定位:document.getElementsByTagName()

class定位:document.getElementsByClassName()

css定位:document.querySelectorAll()

为了应对有的时候出现的一些诡异的定位失效或者定位到了点击失效的问题,这个时候如果用js进行直接执行该事件,往往就可以解决那些诡异的事情,虽然这样有些不符合自动化的理念,但是不失为一种非常有效的方式。

需要注意的是:其中只有id对象用的是Element返回是单个对象,其他都是Elements返回的是一个list,具体用法和上面的webdriver基础定位一样。先写好对应的js语句,可以先赋值给一个变量,然后后调用execute_script进行执行一下js即可。例如:

search_js = "document.getElementsByName('wd')[0].value='selenium';"

search_js2 = "document.querySelectorAll('.s_ipt')[0].value='selenium';"

button_js = "document.getElementById('su').click();"

button_js2 = "document.getElementsByClassName('s_btn')[0].click()"

driver.execute_script(search_js2)

driver.execute_script(button_js2)

五、jQuery定位

jQuery语法是为HTML元素的选取编制的,可以对元素执行一些具体的操作。

基础语法是  $(selector).action()    $符号定义jQuery,selector选择器用来查询具体的HTML元素,通过action()来执行对元素的具体操作。

※ action()操作举例说明:

$(selector).val('input_value')     其中input_value表示要输入的文本的值

$(selector).val('')     如果为空,则执行后是清空的意思

$(selector).click()     点击操作

Python中执行该语句与js定位方法相同,如下:

inputTest="$(':text').val('测试中')"

driver.execute_script(inputTest)

jQuery的选择器基本可以分为四大类:基本选择器(basic)、层次选择器(level)、过滤选择器(filter)、表单选择器(form)

1、基本选择器

举例说明:

$("*")     选取所有元素

$("#lastname”)    选取id="lastname"的元素

:$(".intro”)    选取所有class=“intro"的元素

$(“p")    选取所有<p>元素

$(".intro.demo”)    选取所有 class="intro"且class="demo”的元素.(交集).

selector1, selector2, …, selectorN, 将每一个选择器匹配到的元素合并后一起返回.(并集).

除了#id选择器返回单个元素外,其他选择器返回的都是元素集合。因为HTML规范里面id应该是唯一的,所以重复id的元素没有被考虑,如果多个元素的id相同,取这个id也只能获取第一个元素.即获取的jQuery对象的length属性是1。如果要匹配的元素不存在,则返回一个空的jQuery对象.

基本选择器之间可以组合,用逗号分隔,结果取所有条件的结果的并集。当没有用逗号分隔时,应该是所有条件都满足的交集。

2、层次选择器

举例说明:

$(“div span”)    选取<div>里的所有的<span>元素,多个<div>下面的<span>都会被选择

$(“div>span”)    选取<div>元素下元素名是<span>的子元素,只有直接子元素被选取.其他后代元素不包括

$(“.one+div”)    选取class为one的元素层级的下一个div元素(同一层级)

$(“#two~div”)    选取id为two的元素后面的所有<div>兄弟元素(同一层级)

等价方法:

$(“.one+div”)  等价于方法 $(“.one”).next(“div”) 

$(“#two~div”)  等价于方法 $(“#two”).nextAll(“div”)

$(“prev”).sublings(“next”)方法选取与prev同辈的所有next元素,与前后位置无关

3、过滤选择器

过滤选择器这个大类又分为六个子类:基本过滤、内容过滤、可见性过滤、属性过滤、子元素过滤、表单对象属性过滤。

(1)基本过滤

举例说明:

:first    $(“div:first”)     选取所有<div>元素中的第一个元素

:last    $(“div:last”)     选取所有<div>元素中的最后一个元素

:not(selector)    $(“input:not(.myClass)”)     选取class属性不是.myClass的<input>元素

:even     $(“input:even”)    选取索引是偶数的<input>元素

:odd     $(“input:odd”)    选取索引是奇数的<input>元素

:eq(index)     $(“input:eq(1)”)    选取索引等于1的<input>元素

:gt(index)     $(“input:gt(1)”)    选取索引大于1的<input>元素

:lt(index)     $(“input:lt(1)”)    选取索引小于1的<input>元素

:header     $(“:header”)    选取网页中所有的<h1><h2><h3>...标题元素

:animated     $(“div:animated”)    选取网页中所有正在执行动画的<div>元素

(2)内容过滤

举例说明:

:contains(text)     $(“div:contains("定位")”)    选取所有含有文本“定位” 的元素

:empty    $(“div:empty”)     选取所有不包含子元素(包括文本元素)的<div>空元素对象

:parent    $(“div:parent”) 选取所有包含子元素(包括文本元素)的<div>元素对象

:has(selector)    $(“div:has(p)”)    选取含有<p>元素的<div>元素

(3)可见性过滤

举例说明:

:hidden    $(“input :hidden”)    选取所有不可见的元素,包括<input type="hidden"/>、 <input style="display:none;">、<input style="visibility:hidden;">等元素

:visible    $(“div:visible”)    选取所有可见的div元素

(4)属性过滤

举例说明:

[attribute]    $(“div[id]”)    选取拥有属性id的元素

[attribute=value]    $(“div[title=test]”)    选取属性title为“test”的元素

[attribute!=value]    $(“div[title!=test]”)    选取属性title不为“test”的元素,没有title属性也会被选取

[attribute^=value]    $(“div[title^=test]”)    选取属性title以“test”开头的元素

[attribute$=value]    $(“div[title$=test]”)    选取属性title以“test”结尾的元素

[attribute*=value]    $(“div[title*=test]”)    选取属性title包含“test”的元素

[slector1][slector2]...[slectorN]    $(“div[id][title*=test]”)    选取拥有属性id,且属性title包含“test”的元素

(5)子元素过滤

:nth-child(index/even/odd/equation)    选取每个父元素下的第index个元素或者奇偶元素(index从1算起)

:first-child    选取每个父元素的第一个子元素

:last-child    选取每个父元素的最后一个子元素

:only-child    选取某个父元素的唯一子元素,如果父元素含有其他子元素则不会被选取

(6)表单对象属性过滤

举例说明

:enabled    $(“#from1 :enabled”)     选取id为from1的表单内的所有可用元素

:disabled    $(“#from1 :disabled”)     选取id为from1的表单内的所有不可用元素

:checked    $(“input :checked”)     选取所有被选中的<input>元素(单选框、复选框)

:selected    $(“select :selected”)     选取所有被选中的选项元素(下拉列表)

4、表单选择器

:input    选取所有的<input>、<textarea>、<select>和<button>元素

:text    选取所有的单行文本框

:password    选取所有的密码框

:radio    选取所有的单选框

:checkbox    选取所有的多选框

:submit    选取所有的提交按钮

:image    选取所有的图像按钮

:reset    选取所有的重置按钮

:button    选取所有的按钮

:file    选取所有的上传域

:hidden    选取所有不可见元素

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容