草庐IT

selenium中元素定位——Xpath的高级用法

看看云129 2023-10-23 原文

1.Xpath简介

Xpath(XML Path Language):XML路径语言。XML不是用来取代HTML的,而是对HTML的一种补充,用来与HTML协同工作的一种语言。XML是元标记语言,元标记:指的是可以从标记(标记可以理解为 HTML中的标签)上面可以看出来描述的内容本身是什么。XML中的标记与HTML中的标签的区别:HTML中的标签是已经定义好的 input 、span、div 。XML中的标记是自定义的。Xpath使用路径表达式来选取XML文档中的节点(指的是就是单个元素)或者节点集合(指的是使用某个表达式匹配到了多个元素)。其中路径分为绝对路径和相对路径。

2.使用绝对路径定位元素

从最顶层的HTML开始往下找,像在文件夹中找文件是一样的。例如在文件夹中找某个文件的绝对路径:‪D:\IT\lianxi\123.css

/   表示从根节点选取,也就是当前节点的最顶层(默认情况下当前节点的最顶层就是 HTML ,如果要从某个元素开始查找,则当前节点就是此元素)。

driver.find_element_by_xpath("html/body/form/span/input")

缺点:定位表达式比较长,而且一旦页面结构发生改变,那么使用绝对路径定位元素很可能失效。

3.使用相对路径定位元素

//   表示从匹配选取的当前节点,向下选择文档中的节点,不需要考虑他们所在的位置(即不需要考虑要定位的元素是当前节点子元素还是 孙子元素 或者是 孙子的儿子等元素)。

driver.find_element_by_xpath('html//input')

. (一个点) 表示选取当前节点自己。 一个点 很少使用。

driver.find_element_by_xpath("html//input/.")

..  (两个点)  表示选取当前节点的父节点。

driver.find_element_by_xpath('html//input/..')

4.索引定位

索引与列表中的索引不一样的,不是从0开始计算,而是从1开始计算。

//input[2]     表示选取 任意一个节点下(因为使用了 // )的 第二个 input 标签(只关注 要定位的标签)。不是查找 所有的 input标签中的 第二个 input 标签。

driver.find_element_by_xpath('html//a[2]')

(//input)[2]      表示从匹配到的所有 input 标签中去找第二个 input 标签。 加了括号以后,就把所有的input标签看作是一个整体。

driver.find_element_by_xpath('(//input)[10]')

上述的两个索引可以 结合使用,例如:(//input[1])[1]

5.属性值定位

5.1全部属性值定位

语法格式://标签名[@属性名=”属性值”]
//标签名   这个表达式是在相对路径定位的一种补充延申,就类似于使用如下的SQL语句(select * from 表名)查询数据,查询的结果有多个。怎么样让(select * from 表名)是唯一的,则需要加上 where 条件。[@属性名=”属性值”] 这个表达式就类似于 SQL 语句 中的 where 条件。
//input[@value="123"] 表达式的含义:要匹配任意一个节点下的input标签,这个input 标签具有一个value属性,而且这个value属性的值是 123 。

driver.find_element(By.XPATH, '//input[@value="123"]')

5.2部分属性值定位

有时要定位的元素的属性值特别长,如果使用这个全部属性值来定位元素,则表达式会特别长,此时就可以使用部分属性来定位元素。使用部分属性来定位元素会使用到一些函数来定位元素。
①contains()  表示包含的意思。
 语法格式: //标签名[contains(@属性名 , “部分属性值”)]

driver.find_element(By.XPATH, '//input[contains(@description, "R")]')

②starts-with() 表示 属性值以什么内容开头,匹配的是属性值的开头部分
语法格式:    //标签名[starts-with(@属性名 , “属性值的开头部分的值”)]

driver.find_element(By.XPATH, '//input[starts-with(@description, "D")]')

③ends-with()    表示 属性值 以 什么内容 结尾,匹配的是属性值的结尾部分
语法格式:  //标签名[ends-with(@属性名 , “属性值的结尾部分的值”)]
无法使用 ends-with() 匹配到某个元素的原因: 因为ends-with() 函数 是xpath 2.0 的语法,目前浏览器还不支持。

6.文本内容定位

link_text和partial_link_text这两种方法只是针对 a 标签来说的。文本内容定位元素可以适用于任何一个具有文本内容的元素。
双标签(容器标签:既有开始标签又有结束标签)就有文本内容,单标签的文本内容永远都是一个空字符串。
使用文本内容定位元素需要使用到一个text()这个函数:用来获取标签的文本内容的。

6.1使用全部文本内容定位

语法格式: //标签名[text()=”全部的文本内容”]

driver.find_element_by_xpath('//a[text()="天上一轮才捧出,"]')

6.2使用部分文本内容定位

①contains()  表示要匹配的是某一部分文本内容
语法格式://标签名[contains(text() , “部分文本内容”)]

driver.find_element_by_xpath('//marquee[contains(text(), "部分")]')

②starts-with() 表示要匹配元素的文本内容的开头部分的值
语法格式://标签名[starts-with(text() , “文本内容的开头部分”)]

driver.find_element_by_xpath('//a[starts-with(text(), "时")]')

③ends-with()    表示要匹配文本内容结尾部分的值。
例如:  //a[ends-with(text(), "圆,")]
无法使用 ends-with() 匹配到某个元素的原因:因为ends-with()函数是xpath2.0的语法,目前浏览器还不支持。

7.轴定位

与css中的伪类的使用的场景是类似的。
轴: 表示当前节点与其他节点的关系,用于在XML文档中定位与当前节点有关系的节点。
Xpath中轴定位的使用场景:当某个元素的各个属性以及其组合都不足以唯一定位元素时,那么此时就可以利用兄弟元素或者父元素、子元素等各种与当前节点有关系的节点来定位元素。
使用的语法:  轴名称::标签   
标签指的是 可以通过xpath定位表达式 定位的元素,不是单纯指的是标签名。

①parent::   表示选取当前节点的父节点。  与 .. (两个点)的作用是一样的。

driver.find_element_by_xpath('//a[@id="title6"]/parent::span/parent::form[@id="form"]')

②ancestor::    表示当前节点的直系先辈(父、祖父等)元素,不包含叔叔伯伯。

driver.find_element_by_xpath('//a[@id="hongloumeng"]/br/ancestor::form')

③descendant::    表示选取当前节点的所有的 直系 后代(孙子、儿子、孙子的儿子等)元素。

#通过元素定位表达式找到其中的一个a标签
driver.find_element_by_xpath('//form[@id="form"]/descendant::a[@id="title6"]')
#通过索引找到了所有的a标签中的第一个a标签
driver.find_element_by_xpath('//form[@id="form"]/descendant::a[1]') 

④preceding::   表示选取当前节点的开始标签之前的所有的节点。
更加通俗的描述:要定位的元素的结束标签需要在当前标签的开始标签之前。
哪些元素使用 preceding:: 这个轴名称一定要定位不到??? 所有的直系 先辈 元素 使用 preceding:: 一定定位不到,因为所有的直系先辈元素的结束标签一定是在当前元素的后面。
对于非直系先辈来说,如果它是当前节点的父元素的前面的元素,则可以定位到,如果是后面的则无法定位到。
如果对于 preceding:: 这个轴名称来说,要使用索引,则索引是从 当前元素 开始往前找,遇到的第一个满足条件的元素的索引是1,遇到的第二个满足条件的元素的索引为2 ;以此类推。

driver.find_element_by_xpath('//input[@value="123"]/preceding::a[3]')

⑤preceding-sibling::    sibling表示兄弟姐妹的意思。表示选取当前节点开始标签之前的所有的同级元素。
如果当前元素是某一个元素下的第一个子元素,则无法使用preceding-sibling:: 定位到任何一个元素。
如果对于preceding-sibling:: 这个轴名称来说,要使用索引,则索引是从当前元素开始往前找,遇到的第一个满足条件的元素的索引是 1,遇到的第二个满足条件的元素的索引为2 ;以此类推。

driver.find_element_by_xpath('//input[@value="123"]/preceding-sibling::a[1]')

⑥following::     表示选取当前节点的结束标签之后的所有的元素。
如果要使用索引,则索引是从当前节点开始往后数。与 preceding::查找逻辑一致,方向相反

driver.find_element_by_xpath('//input[@value="123"]/following::span[1]')

⑦following-sibling::    表示选取当前节点结束标签之后的   所有的同级标签。
与preceding-sibling::查找逻辑一致,方向相反。

driver.find_element_by_xpath('//input[@value="123"]/following-sibling::span')

7.1逻辑运算符

①and        这个and表示要同时满足多个条件。使用较多。
例如:  //input[@id="IamID" and  @name="first"].

driver.find_element_by_xpath('//input[@id="IamID" and  @name="first"]')

②or  表示或者的关系。
例如:   //input[@id="IamID" or  @name="first"]

③not()          表示否定。
例如:   //input[not(@id="IamID" and  @name="first")

7.2路径通配符

* 表示路径的通配符,一般用来替代元素定位表达式中的标签名。
//标签名   就可以 使用 * (路径通配符)给替代了  //*
例如://*[@value="123"]

driver.find_element_by_xpath('//*[@value="123"]')

8.总结

以上几种定位方法在实际使用过程中通常会结合一起使用,因此需要全部掌握并融会贯通。

有关selenium中元素定位——Xpath的高级用法的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby-on-rails - Nokogiri:使用 XPath 搜索 <div> - 2

    我使用Nokogiri(Rubygem)css搜索寻找某些在我的html里面。看起来Nokogiri的css搜索不喜欢正则表达式。我想切换到Nokogiri的xpath搜索,因为这似乎支持搜索字符串中的正则表达式。如何在xpath搜索中实现下面提到的(伪)css搜索?require'rubygems'require'nokogiri'value=Nokogiri::HTML.parse(ABBlaCD3"HTML_END#my_blockisgivenmy_bl="1"#my_eqcorrespondstothisregexmy_eq="\/[0-9]+\/"#FIXMEThefoll

  3. ruby-on-rails - capybara ::ElementNotFound:无法找到 xpath "/html" - 2

    我正在学习http://ruby.railstutorial.org/chapters/static-pages上的RubyonRails教程并遇到以下错误StaticPagesHomepageshouldhavethecontent'SampleApp'Failure/Error:page.shouldhave_content('SampleApp')Capybara::ElementNotFound:Unabletofindxpath"/html"#(eval):2:in`text'#./spec/requests/static_pages_spec.rb:7:in`(root)'

  4. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

  5. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  6. ruby - 下载位置 Selenium-webdriver Cucumber Chrome - 2

    我将Cucumber与Ruby结合使用。通过Selenium-Webdriver在Chrome中运行测试时,我想将下载位置更改为测试文件夹而不是用户下载文件夹。我当前的chrome驱动程序是这样设置的:Capybara.default_driver=:seleniumCapybara.register_driver:seleniumdo|app|Capybara::Selenium::Driver.new(app,:browser=>:chrome,desired_capabilities:{'chromeOptions'=>{'args'=>%w{window-size=1920,1

  7. ruby - 有人可以解释一下在 Ruby 中注入(inject)的真实、通俗易懂的用法吗? - 2

    我正在学习Ruby,遇到了inject。我正处于理解它的风口浪尖,但当我是那种需要真实世界的例子来学习一些东西的人时。我遇到的最常见的例子是人们使用inject来添加一个(1..10)范围的总和,我不太关心这个。这是一个任意的例子。在实际程序中我会用它做什么?我正在学习,所以我可以继续使用Rails,但我不必有一个以Web为中心的示例。我只需要一些我可以全神贯注的目标。谢谢大家。 最佳答案 inject有时可以通过它的“其他”名称reduce更好地理解。它是一个对Enumerable进行操作(迭代一次)并返回单个值的函数。它有许多有

  8. ruby - 如何从 nokogiri 对象获取标识符(例如 xpath)? - 2

    遍历nokogiri并使用xpath选择元素相当容易。我需要这个反之亦然,意思是:我需要例如在nokogiri节点上调用.to_xpath以获取元素的完整xpath以将其存储在记录中。有人知道这样做的方法吗? 最佳答案 我能想到的最简单的方法是:Nokogiri::CSS.xpath_fornode.css_path编辑:您也可以尝试使用path方法。 关于ruby-如何从nokogiri对象获取标识符(例如xpath)?,我们在StackOverflow上找到一个类似的问题:

  9. ruby - 使用法拉第上传文件 - 2

    我在尝试使用Faraday将文件上传到网络服务时遇到问题。我的代码:conn=Faraday.new('http://myapi')do|f|f.request:multipartendpayload={:file=>Faraday::UploadIO.new('...','image/jpeg')}conn.post('/',payload)尝试发布后似乎没有任何反应。当我检查响应时this是我所看到的:#:post,:body=>#,#,@opts={}>,#],@index=0>>,#>],@ios=[#,#,@opts={}>,#],@index=0>,#],@index=0>

  10. ruby - rspec: raise_error 用法来匹配错误信息 - 2

    我使用raise(ConfigurationError.new(msg))引发错误我试着用rspec测试一下:expect{Base.configuration.username}.toraise_error(ConfigurationError,message)但这行不通。我该如何测试呢?目标是匹配message。 最佳答案 您可以使用正则表达式匹配错误消息:it{expect{Foo.bar}.toraise_error(NoMethodError,/private/)}这将检查NoMethodError是否由privateme

随机推荐