feat(抓取): 选择器优先语义化(同 id 多实例用 @text 限定,而非序号)+ 修掉两类"死选择器"

语义消歧(B 项):主属性在整棵树里重复时,先找第二个属性把目标单独圈出来 ——
  //*[@resource-id="x" and @text="我"]   (次属性 text > content-desc > class,
                                        单个不够就两两组合)
标 semantic:true + via;只有组合也分不开(列表里同 id 同文字)才退回
  (//*[@resource-id="x"])[k]            (标 indexed,前端黄标提醒脆弱)
抖音底部导航正是这个场景:tab 个数随灰度版本变(4 个 ↔ 3 个),序号必然错位。

顺带修掉两个结构性缺陷(给上面做验证时逐条 lxml 求值发现的,均非本次引入):
1. 结构步进把 class 当标签名 —— dump 的 XML 标签**一律是 <node>**,class 在
   @class 上,所以 //FrameLayout[1]/… 这类路径**永远零命中**;改 *[@class="…"][n]
2. 兜底结构路径用 @index 定位兄弟 —— 实测同级 index 会重复(状态栏/内容区/
   导航栏三个兄弟全是 index="0");改按子节点位置 //hierarchy/*[1]/*[2]

前端:抓取列表把 text/content-desc 排到最前并加粗上色(最稳的定位依据);
序号型从蓝标改**黄标 ⚠ 序号 k/n**,语义型给**绿标 ✓ 语义**;属性页新增
「选择器稳定性」一行说明这个选择器靠什么定位、会不会因界面变化失效。

真机实测(192.168.20.100,248 个元素):
  精确命中目标 221 → 247 | 死选择器 26 → 0 | 语义型 0 → 26(序号型 141 → 115)
  「我」的语义选择器经 /api/steps/test 真机点击 → 命中 ✓

文档:TASK_DEV §5.3/5.4(含两个 XPath 坑)、API §8(suggested 字段表 +
snapshot 行)、research/U2_ELEMENT_SELECTORS §五/§六、backlog ②标记完成。
This commit is contained in:
2026-09-13 22:05:47 +08:00
parent 4ea777a55a
commit 0bc713137d
7 changed files with 203 additions and 47 deletions
+11 -1
View File
@@ -527,10 +527,20 @@
|------|------|---------|
| `GET /api/uiauto/status` | — | uiautodev(:20242)是否在跑,前端据此禁/启用"抓取元素" |
| `GET /api/uiauto/devices` | — | 可选设备列表(uiautodev 设备 + 池内在线补全) |
| `GET /api/uiauto/elements?serial=` | — | 扁平元素列表,每项带 `suggested`(推荐选择器)、`bounds`、`depth` |
| `GET /api/uiauto/elements?serial=` | — | 扁平元素列表(走 uiautodev),每项带 `suggested`、`bounds`、`depth` |
| `GET /api/uiauto/snapshot?serial=` | — | **一次取齐**:截图 + 元素树(原生 u2 同一连接背靠背)→ `{image,width,height,elements,unstable,cost_ms}`;抓取弹窗用这个,失败返回 **502** |
| `GET /api/uiauto/screenshot?serial=` | — | JPEG |
| `POST /api/steps/test` | `{"serial","step":{…}}` | 真机试执行单个步骤 → `命中 / 未找到 / 已执行` |
**`suggested`(推荐选择器)字段**:`{type, value, semantic?, via?, indexed?, occ?, total?, broad?, invalid?, reason?}`
| 字段 | 含义 |
|------|------|
| `semantic` + `via` | **语义选择器**:`//*[@id="x" and @text="y"]`,`via` 是用于限定的第二属性(`text`/`content-desc`/`class` 或 `a+b`)——不依赖同类元素个数,换设备/换版本仍命中 |
| `indexed` + `occ`/`total` | 退化形式 `(//*[@id="x"])[k]`:同 id 且同文字分不开时才用,**界面一变即失配**,前端黄标提醒 |
| `broad` | 结构路径兜底(`//hierarchy/*[i]/*[j]`),最脆 |
| `invalid` + `reason` | 无任何可用属性,前端禁止回填 |
`GET /api/uiauto/elements` 在 uiautodev 不可用时返回 **503**。设备 dump 慢时可能超时(见 [backlog](backlog/TODO.md))。
---