第3章 Selenium WebDriver(css选择元素,元素验证)

Python publisher01 39℃

3.4 通过CSS选择器选择

W3CCSS是定义HTML页面样式的语言。它决定页面元素显示的效果,比如一段文本的字体,大小,间距等等。当然,要修饰一个元素,首先它也要指定修饰的是哪个元素。所以CSS规范里面定义一种选择页面元素的语法。正好Selenium可以用它来定位页面元素。CSS选择器就是这种语法的使用。CSS选择器选择功能强大,不仅可以通过上述的属性选择,还可以根据元素的父子兄弟关系,子元素的顺序,其他的任意元素属性的有无或者属性值,输入焦点,等等。总之非常的强大,特别适用于上面方法都不好定位的时候使用。假如有如下的html片段。

  • 根据 tag 名 选择
p {color: red;} #表示选择所有的 p 元素 
  • 根据 id ,前面加个#号
#food {color: blue;} #表示选择ID为 food的 元素 
  • 3.根据class 选择,前面加个“.”
.special  {color: red;}#表示选择class为 special 的 元素 ,

注意有的元素有两个class 值:

<span class="vegetable good">黄瓜</span>

我们可以看到这个calss中间有一个空格,他不是整体是一个class而是说这个元素有两个class属性,是vegetablegood我们可以这样写:

.good  {color: red;}#表示选择class为 good 的所有 元素 
.vegetable {color: blue;} #表示选择所有的 class为 vegetable所有 的元素 

如果要选择class属性同时具有vegetablegood 的,可以这样:

.vegetable.good

假如有如下的html片段:

<div id="food" style="margin-top:10px;color:red">
    <span class="vegetable good">黄瓜</span>
    <span class="meat">牛肉</span>
    <p class="vegetable">南瓜</p>
    <p class="vegetable">青菜</p>
</div>
<div id="food2" style="margin-top:10px">
    <span class="vegetable">黄瓜2</span>
    <span class="meat">牛肉3</span>
</div>
<select id="choose_car">
    <option value="volvo">沃尔沃</option>
    <option value="corolla">卡罗拉</option>
    <option value="fiat">菲亚特</option>
    <option value="audi">奥迪</option>
</select>

通过css选择的方式如下:

  • 根据tag名,选中第一个span节点
find_element_by_css_selector('span')

选中所有的span节点

find_elements_by_css_selector('span')
  • 根据id名
#选中所有id为food2的节点
find_elements_by_css_selector('#food2')

根据class

#选中所有class属性为vegetable的节点
find_elements_by_css_selector('.vegetable')

讲到这里大家会想这些根据id,class,tag去找元素我们之前不是说过吗,比如find_elements_by_id()、find_elements_by_class_name()这只是我们已前知识的另一种用法而已,我们为什么要学它呢?这里就介绍它的强大之处,它有后代选择的能力。

比如大家看这个表达式:

#food p

中间有个空格,刚才有说到空格在css里面不能乱加有特殊的含义,这个空格就是你要找的节点,注意一定是找空格最后一个节点,就是p节点,空格前面是这个节点的上层节点的特性,这个表达式我们可以这样理解:我们要找一个标签名是p的,然后这个标签有一个限制,他是在idfood 元素的内部 ,我们要找idfood 里面的所有p,空格就是后代的意思。

看一个例子:

div span

就是查找所有 div 元素 里面的 span 元素。

发现spandiv的直接子元素, 就算不是直接子元素也可以,只要是内部的就一样可以。


3.4.1子元素选择

前面我们学习了后代选择器,比如后代选择器:#choose_car option。选择 id choose_car 的所有 option子元素,不管它们是否是直接子节点。如果您希望缩小范围,只选择某个元素的直接子节点元素,请使用子元素选择器(Child selector)。

  • 子元(child)选择器
    选择元素的子元素,和后代选择器不同(#food p )比如:
#choose_car > option 大于号表示你最终要选择的option 元素是前面的这个元素的直接子节点
  • 可以是很多级
ul > ol > li > em

方法是可以混合使用的比如div li > #abc这个表达式意思就是div里面tag名为liidabc的直接子元素。

3.4.2 组(group)选择

组选择 同时选择多个元素,逗号隔开,语法:

语法 <s1>,<s2>

比如:
p,button 选择所有的p元素和所有的button元素
#food , .cheese 选择所有idfood的元素和classcheese的元素。

选择 idfood的所有span子元素 和 所有的p(包括非food的子元素)逗号的优先级要比后代的优先级低,逗号是最后算的。

#food > span,p

选择 idfood的 所有span子元素 和 idfood的 所有的p元素:

#food > span ,#food > p

可以这样选择idfood的的所有子元素:

#food > *

*代表所有元素的意思

p buttonp ,button大家能区分清楚吗,p button意思是p元素里面所有的button元素,p ,button意思是所有的p和所有的button

selenium也可以用这样的语法:

eles = driver.find_elements_by_css_selector('p, button')

3.4.3 兄弟节点选择

我们说过了 后代元素选择、子元素选择,现在我们说下相邻兄弟选择器。下面有这样一段html

<div id="food2" style="margin-top:10px">
    <span class="vegetable">黄瓜2</span>
    <span class="meat">牛肉3</span>
</div>
<select id="choose_car">
    <option value="volvo">沃尔沃</option>
    <option value="corolla">卡罗拉</option>
    <option value="fiat">菲亚特</option>
    <option value="audi">奥迪</option>
</select>

选择紧接在另一个元素后的元素,而且二者有相同的父元素。注意:两个条件 紧接在后面、相同父元素 .这个表达式就是找到idfood2紧跟着的兄弟节点select节点:

#food2 + select 

如果我们想选择的 只是在另一个元素后的兄弟元素,不一定要紧挨着,二者有相同的父元素 ,用下面的语法。

#food2 ~ select 

大家注意“+”“~”都是选择后面的元素,#food + div 表示idfood的紧跟着的div,#food ~ div不一定要紧接着,我们可以联合其他语法使用,比如:

#many > div > p.special + p

选择 #many 的子元素 div 里面的 子元素 p (类型为special) 的后面的兄弟节点。最后选中的元素是:


image.png

3.4.4 属性选择

比如:选择所有具有style属性的元素

*[style]

又比如:选择P节点具有spec值为 len2 的元素,加引号一般用在 属性值中间有空格的情况,如果没有空格可以不加引号。这里有个特别要注意的地方,属性选择必须要完全一样

p[spec='len2']

看下面的截图,标红的部分是不会被选中的。


image.png

属性选择还有一种写法,如果要选择只要spec属性包含len2的就被选择那要怎么写呢,在“=”前面加个“*”号就可以

p[spec*='len2']
或者
a[href*="baidu.com"]

len2开头的:

p[spec^='len2']

len2结尾的:

p[spec$='len2']

同时满足两种属性的:

p[class=special][name=p1] 

CSS选择器有很多的语法, 详细的大家可以参考 这里http://www.w3school.com.cn/cssref/css_selectors.asp

我们css选择器还有一种常用的方法:nth-child(n)比如p:nth-child(2)意思是首先选择所有的p节点,冒号表示一个限定,就是p必须是父元素的第二个子元素,这就是nth-child(2),注意不是说第二个p类型的子元素而就是第二个p元素比我我们看个例子:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>定位网页元素</title>
<style>
    #choose_car option {color: blue;}
</style>
</head>
<body>
    <div style="">
      <h3>This is a heading</h3>
      <p>This is a paragraph.</p>
    </div>
    <button name='button'>按钮1</button>
    <button name='button'>按钮2</button>
    <div class="cheese"><span>Cheddar</span></div>
    <div class="cheese"><span>Gouda</span></div>
    <a href="http://www.163.com" id="baidulink">转到百度</a>
    <div id="food" style="margin-top:10px;color:red">
        <span class="vegetable good">黄瓜</span>
        <span class="meat">牛肉</span>
        <p class="vegetable">南瓜</p>
        <p class="vegetable">青菜</p>
    </div>
    <div id="food2" style="margin-top:10px">
        <span class="vegetable">黄瓜2</span>
        <span class="meat">牛肉3</span>
    </div>
    <select id="choose_car">
        <option value="volvo">沃尔沃</option>
        <option value="corolla">卡罗拉</option>
        <option value="fiat">菲亚特</option>
        <option value="audi">奥迪</option>
    </select>
    <footer>
        <div>
            <p>test1</p>
        </div>
    </footer>
    <p>test2</p>
    <div id="many">
        <div>
            <p class="special" name="p1">one</p>
            <p>two</p>
            <p class="special3">three</p>
        </div>
    </div>
    <p spec="len">test3</p>
    <p spec="len2">test4</p>
    <p spec="len2 len3">test5</p>
</body>
</html>

id等于food的下面有几个p元素,是不是2个?

#food > p:nth-child(2)

这个表达式是什么意思呢?属于其父元素的第二个子元素,并且要是p ,我们这里第二个子元素是span,所以上面这个表达式是找不到的。

比如:

#food > p:nth-child(3)

这个表达式的意思是,属于其父元素的第3个子元素,并且要是p,这就可以找到。这是正数第3个我们还可以倒数nth-last-child(n),还有一种按照类型排序的方法nth-of-type()p:nth-of-type()p:nth-child()区别是:p:nth-child(2)必须是父节点的第二个子节点,p:nth-of-type(2)第二个p类型的子节点。

比如:属于其父元素的倒数第二个子元素,并且是p

#food > p:nth-last-child(2) 

找到的是:


image.png

比如:属于其父元素的第二个p 类型的子元素

#food > p:nth-of-type(2) 

找到的是:


image.png

比如:属于其父元素的倒数第二个p 类型的子元素

#food > p:nth-last-of-type(2)

找到的是:


image.png

还有一种选择元素的方式:not(p),选择非 <p> 元素的每个元素。

比如:

#food > :not(p)

找到的是:


image.png

3.4.5 利用浏览器开发工具获取 css seletor

对于不太好找的CSS selector的元素,我们可以通过浏览器开发工具帮助我们定位。在chrom浏览器里,按F12,打开开发工具窗口,点击element标签,然后,在网页窗口里面 点选我们要 选择的元素,开发工具窗口会高亮显示该元素对应的html tag代码。这时,我们可以 用鼠标右键 点击该代码,在弹出的对话框中,依次选择Copy –> Copy selector,如下图所示,这样,该元素的CSS selector就被拷贝到剪贴板了。


image.png

3.4.6 验证css表达式

当我们要写的自动化脚本比较复杂的时候,每次到python代码中调试CSS选择器(看看我们的css选择器是否能选中元素)会非常的麻烦。因为很慢,我们可以利用浏览器的开发工具,直接在浏览器中进行测试,看看我们写的CSS选择器是否能正确找到我们要的web元素。

两种方法, 一种是chrome浏览器,按F12,打开开发窗口,点击元素标签(英文叫Element),按contrl + f,直接输入css选择器即可。选中的元素会高亮显示。


image.png

这种方法优点, 填入内容完全就是 css 选择器, 缺点: 也会做 字符匹配, 让人有点迷糊。

另一种是:
chrome浏览器,按F12,打开开发窗口,点击控制台标签(英文叫console),在里面执行$$(‘css selector’),其中css selector 就是css选择器字符串。chrom界面如下所示:


image.png

如果能找到对象,返回的结果就不是空数组,就表示能找到web元素。而且鼠标放在数组元素上,会高亮显示对应的web元素。这种方法 优点, 不会做 字符串匹配, 很清晰。缺点: 要多输入点内容。

转载请注明:Python量化投资 » 第3章 Selenium WebDriver(css选择元素,元素验证)

喜欢 (0)or分享 (0)