欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Web自动化-Selenium扩展+定位方法

程序员文章站 2022-03-22 16:55:21
...

前言

在我的上一篇Selenium的文章中已经详细介绍了关于安装方面、使用方面的各种经常使用的方法,本篇内容对上篇文章做一些扩展,比如详细的CSS+XPath定位元素的方法,遇见窗口切换等的处理,让你在Selenium的使用上更进一步,最后,如果想了解更仔细的基础知识请点击传送门:《Web自动化-Selenium》

CSS表达式

1.1 属性选择
注意一下,包括上篇文章在内,关于文章中写的那么多classname,
需要注意的是,class是一个属性,而不是指的classname是一个属性,
classname指的仅仅是class对应的那个值!!!

看过上一篇的同志们都知道,在元素定位的方法中有个id定位、还有classname定位,在CSS中,它们也被包含在内了,并且非常简单。举个例子,对id定位的CSS表达式:

	#对id='XXX'的元素进行定位,下面是相应的CSS表达式方法
	driver.find_element_by_css_selector('#XXX')

注意一下,这个driver还是上篇文章中的那个webdriver对象,然后,哈哈哈看到对应表达式了吧,如果不知道CSS的小伙伴是不是很懵,其实你没猜错,对id定位只需要在id对应的值前加个#井号键即可,实际上,包括对classname进行定位:

	#对classname='XXX'的元素进行定位,下面是相应的CSS表达式
	driver.find_element_by_css_seletor('.XXX')

是的,对classname定位只需要在对应值之前加个.点即可,那大家会不会想定位什么就在前加个对应标记就行了,不是这样的,只有id和classname因为出现频率高且比较广泛,所以CSS中专门给出了对应的简单标记,至于其它的,包括嵌套标记等方法,后文细细讲来。
在这里提一点,对于id和classname,它们其实都是HTML中标签里面的属性,当然属性还有很多其它的属性,比如会有style、src、href等等等等,不过有一点是不变的,它们都是属性,那我们会不会有时候找的不是标签内的东西,而是这些属性的对应值,答案是会!那么在Selenium中也提供了一种方法可以直接得到该元素对应属性的值:

get_attribute(attribute name)

没错,就是这么简单粗暴,这是一个方法,使用对象是一个webdriver element对象,也就是driver定位后的元素对象,举个例子:

	#先得到id='XXX'的元素对象
	webdriver_element = driver.find_element_by_id('XXX')
	#打印此对象中'src'属性的值
	print(webdriver_element.get_attribute('src'))

是的,就是这么操作。
前边说了id和classname的相应在CSS中分别用#和.来标记,对于标签名,在CSS中是不标记的,直接没有标记写出来就代表找的是这个的标签:

	#用CSS选择器找到span标签的第一个元素
	driver.find_element_by_css_selector('span')

也就是直接把标签名写进去就代表找的此标签。

1.2 子元素和后代元素
  • 选择子元素后代元素的方法。

我们都知道,HTML是一个标签树一样的形式,节点很多,子节点更多,很多节点被嵌套在一些节点中,有时候某个元素的很多东西都不是唯一的,不能直接定位,那么这个时候就需要使用一整串表达式来定位了。

  • 在CSS表达式中,只需要在两个元素之间加上一个空格,则代表空格后的元素为前一个元素的后代元素,而加上一个>,则代表大于号后的元素为前一个元素的直接子元素。举个例子:
	#选择id='XXX'的元素的所有名为'span'的所有后代元素
	driver.find_elements_by_css_selector('#XXX span')
	#s选择class='XXX'的元素的所有名字'src'的直接子元素
	driver.find_elements_by_css_selector('.XXX>src')

当然,后代元素就不说了,对于选择子元素也支持多层级的原则:

	#选择id='XXX'的元素的子元素名为'span'的子元素'src'
	driver.find_elements_by_css_selector('#XXX>span>src')
1.3 根据属性来选
  • 根据属性来选

在有些时候,我们会发现,有一些子标签,它们的标签名一样,却有些属性不一样,并且包含的东西也不一样,这个时候我们需要获取一些拥有目标属性的标签,如下:

	#获取div标签的后代标签中标签名为a属性为href的元素
	driver.find_elements_by_css_selector('div a[href]')
	#如果想要获取某个固定的元素,只需要下面这样
	driver.find_element_by_css_selector('div a[href='XXX']')
	#也就是说把s给去掉,其实不去掉也没事因为本来也就一个,指定href属性的值即可。
1.4 按照次序选择子节点
  • 按照次序选择子节点

我们可以单独指定选择父元素的第n个子节点,使用的方法是:

:nth-child()

具体使用方法如下:

	#选择id='XXX'的元素的第二个子元素
	driver.find_elements_by_css_selector('#XXX:nth-child(2)')
	#选择所有标签名为src的子元素'中'的元素的第二个子元素
	driver.find_elements_by_css_selector('src :nth-child(2)')
	#选择所有标签元素的第二个子元素
	driver.find_elements_by_css_selector(':nth-child(2)')

也就是说,在冒号前,是已经定位好的元素,然后选择此元素子元素中的第二个。括号内的数字指第几个。

还有一种选择方法,是选择父元素的第几个某种类型的子节点。上文中,可以理解为先指定元素,再从该元素的子元素中找第几个,那么下面这个意思是,先指定元素,然后在该元素的子元素中找第几个某类型的元素。方法:

:nth-of-type()

示例:

	#选择id='XXX'的元素的第三个src类型的子元素,src为标签名
	driver.find_elements_by_css_selector('#XXX>src:nth-of-type(3)')
1.5 奇数节点和偶数节点
  • 奇数节点和偶数节点

这个代表在确定了父元素之后,选择其奇数子元素还是偶数子元素。

:nth-child(even) 选择奇数的话用此参数
:nth-child(odd) 选择偶数的话用此参数

和1.4相比之下,只是参数有限制了,用法是差不多的。

1.6 兄弟节点选择
  • 兄弟节点选择

这个方法呢需要首先确定我们的目标元素,然后再确定兄弟元素,比如:

	#选择span元素后面紧跟的兄弟节点src
	driver.find_elements_by_css_selector('span+src')
	#选择span元素后面跟着的所有兄弟节点src
	driver.find_elements_by_css_selector('span~src')

frame窗口切换

在有些时候,我们需要访问的元素是在一个iframe标签当中,Web自动化-Selenium扩展+定位方法
如此图左上角的iframe,我们发现此标签后面也有head和body,说明这是另一份HTML文档,其实在HTML语法中,frame或者iframe元素的全部会包含一个被嵌入的另一份html文档,简单理解就是我们要定位的目标元素在程序现在操作的html文档之外,如果直接对其操作是不行的,你根本找不到它,此时必须要将操作范围换到目标元素所在的html文档,切换的方法很简单:

driver.switch_to.frame(frame_reference)

其中,frame_reference可以是frame元素的属性或者ID。如图片中的iframe为例,这样切换即可:

	driver.switch_to.frame(0)

浏览器窗口切换

这个大家就比较熟悉了,在很多时候,我们在网页的某个地方点击之后会出现新的网页,也就是点了超链接,此时浏览器里面会有两个窗口,这个时候也是需要切换的,我们可以切换至任意一个我们想要切换到的窗口。那么怎么切换呢,用这个方法:

driver.switch_to.window(handle)

handle是一个句柄,是我们要切换到的窗口的句柄,在Webdirver中有一个属性window_handles,这是一个列表对象,当你调用它的时候,会返回含有所有当前窗口句柄的一个列表,那么怎么从列表中找到我们需要的窗口呢?有如下办法:

	for handle in driver.window_handles:
		#从该列表对象中遍历
		dirver.switch_to.window(handle)
		#上面是切换窗口,然后来判断
		if 'XXX' in driver.title:
			break
		#就是切换到的窗口里面,如果我们需要的窗口的标题在现在的窗口里面,就退出遍历,也就是当前切换到的窗口就是目标窗口了。

冻结界面

在浏览器开发者工具栏的console里面输入:

setTimeout(function(){debugger},10000)

这句话是什么意思呢?这其实是一段JavaScript命令,他将在10000毫秒也就是10秒后冻结浏览器界面,也就是所有元素静止,此时,你就可以为所欲为了,可能你想不到有什么用,不过,你可以先实验一下,改里面的10000成你想要的时间,看看会出现什么,放心吧,你总会用得到的。

总结

值得一提的是,当我们定位元素的时候使用的find_element_by...的时候,也就是element没有加s的时候,如果获取不到路径下的元素,程序会报错,而假如使用的elements的时候,如果获取不到目标元素,不会报错,会返回一个空列表。
另外,使用driver.title会返回当前窗口的标题,使用i.text会返回元素的文本,注意i是一个webdriver element对象。


最后这两篇Selenium的文章到此结束了,本人知识不足难免文中会有错误,如有发现恳请提出,谢谢。如果你已经完全掌握了两篇文章的内容,那么你已经可以做很多一些事情了。其实还有一种定位元素的方法XPath,不过相信很多了解前端的人已经非常熟悉了,本文没有给出方法,如果感觉文章对您有用,还请点个赞支持一下谢谢~