4. 基于选择器的UI元素定位:CSS选择器、XPath选择器、UI Automation选择器
说到UI元素定位,选择器这东西,我刚开始做RPA时也踩过不少坑。你想想看,一个按钮在页面上,你怎么告诉程序「就是它」?靠坐标?那换个分辨率就完蛋。靠图片?换个主题就认不出来了。所以,选择器才是正道。
这一章,我重点讲三种最常用的选择器:CSS选择器、XPath选择器,还有Windows桌面端专用的UI Automation选择器。每种我都会结合自己的实战经验来讲。
4.1 CSS选择器:Web自动化的首选
CSS选择器,说白了就是通过HTML元素的样式特征来定位。我个人习惯在Web自动化中优先用它,为什么?因为浏览器对CSS的解析速度最快,而且写法简洁。
核心要点:CSS选择器基于元素的id、class、标签名、属性等特征进行匹配。
举个例子,假设页面上有个登录按钮:
<button id="loginBtn" class="btn-primary" data-action="login">登录</button>
用CSS选择器定位它,可以这样写:
#loginBtn // 通过id定位
.btn-primary // 通过class定位
button[data-action="login"] // 通过属性定位
button.btn-primary // 标签+class组合
我在项目中遇到过一个问题:一个页面有几十个按钮,class都差不多,唯独data属性不同。用CSS的属性选择器,一行代码就搞定了,比XPath快得多。
我的小技巧:在Chrome开发者工具里,按Ctrl+F,输入CSS选择器,能实时验证是否匹配到目标元素。这招我用了好多年,效率极高。
4.2 XPath选择器:复杂场景的救星
XPath,说实话,一开始我觉得它挺啰嗦的。但后来发现,有些场景非它不可。比如,你要找一个「包含某段文本」的元素,或者要定位「某个元素后面的兄弟元素」,CSS就力不从心了。
XPath有两种写法,我简单说一下:
| 类型 | 写法 | 特点 |
|---|---|---|
| 绝对路径 | /html/body/div[1]/button | 从根节点开始,一写就长,一改就废 |
| 相对路径 | //button[@id='loginBtn'] | 从任意位置开始,灵活,我推荐用这个 |
举个例子,你要找一个文本为「确认删除」的按钮:
//button[text()='确认删除']
或者找一个包含「删除」二字的:
//button[contains(text(), '删除')]
注意:我曾经因为XPath写得太绝对,结果页面结构一改,脚本全崩了。后来我养成了习惯:能用相对路径,绝不用绝对路径。能用id或class,就别依赖文本内容。
还有一个坑,我提一下:XPath的索引是从1开始的,不是0。我第一次用的时候,写了个[0],找了半天找不到元素,后来才反应过来。嗯,这个细节容易忽略。
4.3 UI Automation选择器:桌面应用的利器
做RPA,不可能只跟网页打交道。Windows桌面应用怎么办?这时候就要用UI Automation(UIA)选择器了。
UIA是微软提供的一套UI自动化框架。它把每个界面元素都抽象成一个「控件」,每个控件都有一些属性,比如Name、AutomationId、ControlType等。
举个例子,一个记事本的菜单项「文件」:
<MenuItem Name="文件" AutomationId="MenuItemFile" ControlType="MenuItem"/>
用UIA选择器定位,可以这样写:
ControlType=MenuItem;Name=文件
ControlType=MenuItem;AutomationId=MenuItemFile
我建议你用AutomationId来定位,因为它通常不会变。Name可能会因为语言切换而变化,比如中文系统叫「文件」,英文系统叫「File」,那就麻烦了。
避坑指南:我曾经做一个财务软件的自动化,那个软件的所有按钮都没有AutomationId,Name还经常变。后来我用了一个工具叫Inspect.exe(Windows SDK自带的),把整个UI树扒下来,发现可以用ControlType+Index组合来定位。虽然麻烦点,但至少稳定。
4.4 三种选择器的对比与选择
说了这么多,到底什么时候用哪种?我整理了一个表格,你一看就明白:
| 场景 | 推荐选择器 | 原因 |
|---|---|---|
| Web页面,元素有id或class | CSS选择器 | 速度快,写法简单 |
| Web页面,需要根据文本定位 | XPath | CSS不支持文本匹配 |
| Web页面,需要定位父/子/兄弟元素 | XPath | 轴操作(parent/child/following-sibling)很强大 |
| Windows桌面应用 | UI Automation | 专门为桌面UI设计的 |
| 跨平台(Web+桌面混合) | 根据具体平台切换 | 没有万能药,灵活切换才是王道 |
你想想看,如果每个场景都用同一种选择器,那肯定会有力不从心的时候。我个人的习惯是:Web优先CSS,搞不定再上XPath;桌面应用就用UIA,实在不行再考虑图像识别。
总结一下:选择器没有好坏之分,只有合不合适。关键是理解每种选择器的原理和适用场景,然后根据实际情况灵活选用。嗯,这一章的内容就到这里,下一章我们聊聊动态元素的处理技巧。