文章目录
前言
在我的上一篇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标签当中,
如此图左上角的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
,不过相信很多了解前端的人已经非常熟悉了,本文没有给出方法,如果感觉文章对您有用,还请点个赞支持一下谢谢~