UI 自动化,简要来说就两大问题:“如何定位元素”、“如何操作元素”。这篇主要写一下如何使用CSS 选择器(CSS Selector)定位元素。

根据 tag 选择元素

选择器

tag_name

直接写上标签名就是了,试着找一下页面顶端这个菜单栏,元素如下:

<nav class="head-menu">...</nav>

这个元素是被标签nav包裹的;

在这个界面按下F12,或者右键 -> 审查元素/检查打开开发者工具条,然后使用快捷键 ctrl + F 打开查找框,输入 nav ,查找到一个元素(1 of 1,如果页面中有多个nav标签,那么也会被一并查找出来)。

根据 class 选择元素

选择器

.class_name /* 点 + class_name */

接着找这个页面顶端的菜单,元素如下:

<nav class="head-menu">...</nav>

这个元素的class名是head-menu,那么用class找的话,选择器就是 .head-name,直接在查找框输入,也可以被定位到。

根据 id 查找元素

选择器

#id /* # + id */

这回来找一下这小节的标题,它的元素如下:

<h2 id="title-3" tabindex="-1">根据 id 查找元素</h2>

这个元素的id为title-3,那么用id找,选择器就是#title-3,在查找框输入,发现找到了两个,那是因为右侧目录对应的标题元素为:

<a href="#title-3" class="item-3">根据 id 查找元素</a>

而查找框是按字符串、选择器或xPath查找的,所以把它找出来了,那么有没有一种方法只使用css选择器,方便验证自己写的css选择器是否正确呢?此时可以切换到控制台/console,使用$$("选择器")的方式验证;试一下,在控制台输入$$("#title-2"),回车。

$$("选择器") //返回所有满足选择器的结果
$("选择器") //返回第一条满足选择器的结果

根据其他属性定位

像上种情况,如果我就是要定位目录里的标题怎么办?元素如下:

<a href="#title-4" class="item-3">根据其他属性定位</a>

怎么以href="#title-4"来定位?这个就简单粗暴了,一切的属性都可用如下形式来做定位:

[attribute] /* 选择器用于选取带有指定属性的元素 */
[attribute="value"] /* 选择器用于选取带有指定属性和值的元素 */
[attribute~="value"] /* 选择器选取属性值包含指定词的元素 */
[attribute*="value"] /* 选择器选取属性值包含指定词的元素,值不必是完整单词 */
[attribute|="value"] /* 选择器用于选取指定属性以指定值开头的元素,值必须是完整或单独的单词 */
[attribute^="value"] /* 选择器用于选取指定属性以指定值开头的元素,值不必是完整或单独的单词 */
[attribute$="value"] /* 选择器用于选取指定属性以指定值结尾的元素,值不必是完整单词 */

那么这里就可以使用 [href="#title-4"] 来定位这个元素。

组合使用

假设有这么一个页面,只想取第二个元素,任何单一的定位都会取到两个;那么,就可以将特性组合起来使用:

<a class="item-3">第一个元素</a>
<a class="item-1">第二个元素</a>
<div class="item-3">第三个元素</div>
<div class="item-1">第四个元素</div>

a 有两个,.item-1也有两个,但是组合起来a.item-1就只有一个了。

只要需要,可以将多个定位条件组合在一起 tag.class[attribute="value"]

那如果想要选择第二个和第三个元素怎么选?可以用,将条件连接起来,这样只要满足其中一个条件就能被选中。

所以使用 a.item-1 , div.item-3 就可以了。

,不止可以连接两个,n个也是阔以的。

后代元素定位

如果要定位这个页面下方的博主寄语<p>部分,直接使用 p 会将文中所有段落都选到,那么此时可以使用空格 来表示后代 或使用 > 来表示子代;

<section class="post-author">
    <figure class="author-avatar">
        <img src="https://cdn.sep.cc/avatar/e2d1f9c5da125994d7bf02c691e3124a?s=256&amp;d=identiconBB%80%E4%B9%88-8644c1b2773d404cac8c8c299106949c.jpg" alt="阑珊">
    </figure>
    <div class="author-info">
        <h4>阑珊</h4>
        <p>本站未注明转载的文章均为原创,并采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank" rel="nofollow">CC BY-NC-SA 4.0</a> 授权协议,<span style="color: #E91E63">转载请注明来源</span>,谢谢!如本站内容对你有所帮助的话,不妨在评论区、留言板留下你的足迹。&gt;</p>
    </div>
</section>

这里的 <p><section> 下的 <div> 里,那么用选择器来表示就是:

section > div > p /* 选择 section 子代 div 子代中的 p,> 表示子代 */
section div p /* 选择 section 后代 div 后代中的 p ,空格表示后代 */

/* 如果只有这里的p是在section下的,那么也可以一步到位 */
section p /* 选择 section 后代中的 p */

那如果子代元素属性都一样,那还可以使用 nth-child 按次序来选取元素,假设你就要找现在这段话。这段话是这篇文章的第44个<p>元素,文章的 class=post-content,那么这段话的位置就在:

.post-content > p:nth-child(44) /* 选择的是 .post-content 下子代 <p> 中的第 44 个 */

倒序则可以使用 nth-last-child(1),意为倒数第1个

兄弟节点的定位

如果需要选择紧接在另一个元素后的元素,而且二者有相同的父元素,可以使用相邻兄弟选择器(Adjacent sibling selector)。

例如我要定位每一个在h2标题下的第一段,元素特征如下:

<article class="post-content">
    <h2 id="title-n" tabindex="-1">H2标题</h2>
    <p>第一段内容</p>
<article>

就可以使用如下选择器:

h2 + p /* 使用加号 + 表示选择紧接在 h2 元素后出现的段落,h1 和 p 元素拥有共同的父元素 */