ms-vite-plugin 1.4.41 → 1.4.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/api/node.md +238 -349
- package/docs/apicn/node.md +241 -366
- package/docs/apipython/node.md +184 -288
- package/package.json +1 -1
package/docs/apipython/node.md
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
# 节点模块 (Node)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
用于查找和操作当前界面上的控件节点。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**注意**
|
|
6
6
|
|
|
7
|
-
-
|
|
7
|
+
- 仅支持快点 Agent 模式
|
|
8
|
+
- 通过 `from kuaijs import node` 使用
|
|
9
|
+
|
|
10
|
+
**基本流程**
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
createNodeSelector → 设置筛选条件 → getOneNodeInfo / getNodeInfo
|
|
14
|
+
→ 点击 / 输入 / 设值等
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
8
18
|
|
|
9
19
|
## 类型定义
|
|
10
20
|
|
|
11
21
|
```python
|
|
12
|
-
from typing import List,
|
|
22
|
+
from typing import List, Optional, TypedDict
|
|
13
23
|
|
|
14
24
|
class NodeBounds:
|
|
15
25
|
x: int
|
|
@@ -52,361 +62,247 @@ class NodeInfo:
|
|
|
52
62
|
def nextSiblings(self) -> List["NodeInfo"]: ...
|
|
53
63
|
|
|
54
64
|
class NodeSelectorOptions(TypedDict, total=False):
|
|
55
|
-
maxDepth: int #
|
|
56
|
-
mode: int
|
|
65
|
+
maxDepth: int # 最大层级,默认 50
|
|
66
|
+
mode: int # 抓取模式 1 | 2 | 3,默认 1
|
|
57
67
|
```
|
|
58
68
|
|
|
59
|
-
|
|
69
|
+
---
|
|
60
70
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
### 创建节点选择器
|
|
64
|
-
|
|
65
|
-
#### `createNodeSelector` - 创建节点选择器
|
|
66
|
-
|
|
67
|
-
创建一个新的节点选择器实例。
|
|
71
|
+
## 创建选择器
|
|
68
72
|
|
|
69
73
|
```python
|
|
70
74
|
def createNodeSelector(params: Optional[NodeSelectorOptions] = None) -> NodeSelector
|
|
71
75
|
```
|
|
72
76
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
| `maxDepth` | int | 否 | 50 | 最大层级深度,默认 50 |
|
|
78
|
-
| `mode` | int | 否 | 1 | 抓取模式。支持模式 1、模式 2、模式 3,默认模式 1 |
|
|
79
|
-
|
|
80
|
-
**返回值:** `NodeSelector`
|
|
81
|
-
|
|
82
|
-
**示例:**
|
|
77
|
+
| 参数 | 默认 | 说明 |
|
|
78
|
+
| --- | --- | --- |
|
|
79
|
+
| `maxDepth` | `50` | 抓取深度,深层控件抓不到时可调大 |
|
|
80
|
+
| `mode` | `1` | 抓取模式,可选 `1` / `2` / `3`,默认 `1` |
|
|
83
81
|
|
|
84
82
|
```python
|
|
85
83
|
from kuaijs import node
|
|
86
84
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
"mode": 1 # 默认模式 1
|
|
91
|
-
})
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### 选择器方法
|
|
95
|
-
|
|
96
|
-
#### 获取节点
|
|
97
|
-
|
|
98
|
-
```python
|
|
99
|
-
# 获取当前页面的 XML 字符串
|
|
100
|
-
def xml(timeout: int = 5000) -> Optional[str]
|
|
101
|
-
|
|
102
|
-
# 获取多个节点
|
|
103
|
-
def getNodeInfo(timeout: int = 5000) -> List[NodeInfo]
|
|
104
|
-
|
|
105
|
-
# 获取单个节点
|
|
106
|
-
def getOneNodeInfo(timeout: int = 5000) -> Optional[NodeInfo]
|
|
107
|
-
|
|
108
|
-
# 加载节点数据(通常内部自动调用)
|
|
109
|
-
def loadNode(timeout: int = 5000) -> NodeSelector
|
|
110
|
-
|
|
111
|
-
# 清除所有选择条件
|
|
112
|
-
def clearSelector() -> NodeSelector
|
|
85
|
+
selector = node.createNodeSelector()
|
|
86
|
+
shallow = node.createNodeSelector({"maxDepth": 15})
|
|
87
|
+
list_page = node.createNodeSelector({"mode": 2})
|
|
113
88
|
```
|
|
114
89
|
|
|
115
|
-
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 节点信息
|
|
93
|
+
|
|
94
|
+
### 属性
|
|
95
|
+
|
|
96
|
+
| 字段 | 说明 |
|
|
97
|
+
| --- | --- |
|
|
98
|
+
| `id` | 节点 ID(内部定位用,不要改) |
|
|
99
|
+
| `identifier` | 控件标识符 |
|
|
100
|
+
| `label` | 标签文案 |
|
|
101
|
+
| `type` | 类型,如 `XCUIElementTypeButton` |
|
|
102
|
+
| `value` | 当前值 |
|
|
103
|
+
| `placeholderValue` | 输入框占位文字 |
|
|
104
|
+
| `title` | 标题 |
|
|
105
|
+
| `enabled` | 是否启用 |
|
|
106
|
+
| `bounds` | 位置大小 |
|
|
107
|
+
| `depth` / `index` | 层级 / 序号 |
|
|
108
|
+
| `parentId` / `childCount` | 父节点 ID / 子节点数 |
|
|
109
|
+
|
|
110
|
+
### 方法
|
|
111
|
+
|
|
112
|
+
| 方法 | 说明 |
|
|
113
|
+
| --- | --- |
|
|
114
|
+
| `hittable()` | 当前是否可点击 |
|
|
115
|
+
| `scrollToVisible()` | 滚动到可见区域 |
|
|
116
|
+
| `tap()` | 单击(不可见时会先尝试滚到可见) |
|
|
117
|
+
| `doubleTap()` | 双击 |
|
|
118
|
+
| `press(duration=500)` | 长按,毫秒,默认 500 |
|
|
119
|
+
| `clickCenter()` | 点击中心 |
|
|
120
|
+
| `clickRandom()` | 范围内随机点击 |
|
|
121
|
+
| `clearInput()` | 清空输入 |
|
|
122
|
+
| `input(text)` | 追加输入(不先清空) |
|
|
123
|
+
| `setValue(text)` | 设置值(见下方) |
|
|
124
|
+
| `parent()` / `child(i)` / `allChildren()` | 父 / 子 / 全部子节点 |
|
|
125
|
+
| `siblings()` / `previousSiblings()` / `nextSiblings()` | 兄弟节点 |
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 选择器方法
|
|
130
|
+
|
|
131
|
+
### 加载与结果
|
|
132
|
+
|
|
133
|
+
| 方法 | 说明 |
|
|
134
|
+
| --- | --- |
|
|
135
|
+
| `loadNode(timeout=5000)` | 重新加载界面节点 |
|
|
136
|
+
| `clearSelector()` | 清除筛选条件 |
|
|
137
|
+
| `xml(timeout=5000)` | 获取界面 XML,失败返回 `None` |
|
|
138
|
+
| `getNodeInfo(timeout=5000)` | 所有匹配节点 |
|
|
139
|
+
| `getOneNodeInfo(timeout=5000)` | 第一个匹配节点,没有则 `None` |
|
|
140
|
+
|
|
141
|
+
`timeout` 单位毫秒。
|
|
116
142
|
|
|
117
143
|
```python
|
|
118
144
|
from kuaijs import node
|
|
119
145
|
|
|
120
146
|
selector = node.createNodeSelector()
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
print(f"找到 {len(all_nodes)} 个节点")
|
|
125
|
-
|
|
126
|
-
# 获取第一个匹配的节点
|
|
127
|
-
first_node = selector.getOneNodeInfo(3000)
|
|
128
|
-
if first_node:
|
|
129
|
-
print(f"节点标签: {first_node.label}")
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
#### 条件筛选
|
|
133
|
-
|
|
134
|
-
##### 文本相关
|
|
135
|
-
|
|
136
|
-
```python
|
|
137
|
-
# 精确匹配标签
|
|
138
|
-
def label(text: str) -> NodeSelector
|
|
139
|
-
|
|
140
|
-
# 标签模糊匹配
|
|
141
|
-
def labelMatch(pattern: str) -> NodeSelector
|
|
142
|
-
|
|
143
|
-
# 精确匹配名称
|
|
144
|
-
def title(text: str) -> NodeSelector
|
|
145
|
-
|
|
146
|
-
# 名称模糊匹配
|
|
147
|
-
def titleMatch(pattern: str) -> NodeSelector
|
|
148
|
-
|
|
149
|
-
# 精确匹配标识符
|
|
150
|
-
def identifier(text: str) -> NodeSelector
|
|
151
|
-
|
|
152
|
-
# 标识符模糊匹配
|
|
153
|
-
def identifierMatch(pattern: str) -> NodeSelector
|
|
154
|
-
|
|
155
|
-
# 精确匹配值
|
|
156
|
-
def value(text: str) -> NodeSelector
|
|
157
|
-
|
|
158
|
-
# 值模糊匹配
|
|
159
|
-
def valueMatch(pattern: str) -> NodeSelector
|
|
147
|
+
nodes = selector.label("确定").getNodeInfo(5000)
|
|
148
|
+
one = selector.getOneNodeInfo(3000)
|
|
149
|
+
xml = selector.xml()
|
|
160
150
|
```
|
|
161
151
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
```python
|
|
165
|
-
# 查找标签为"确定"的按钮
|
|
166
|
-
confirm_button = selector.label("确定").getOneNodeInfo(3000)
|
|
152
|
+
### 筛选条件
|
|
167
153
|
|
|
168
|
-
|
|
169
|
-
login_elements = selector.labelMatch(".*登录.*").getNodeInfo(3000)
|
|
154
|
+
可链式调用,多个条件同时满足。带 `Match` 的为模糊匹配。
|
|
170
155
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
# 通过标识符查找
|
|
178
|
-
el_by_id = selector.identifier("login_btn").getOneNodeInfo(2000)
|
|
179
|
-
fuzzy = selector.identifierMatch("^login_.*").getNodeInfo(3000)
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
##### 类型与属性
|
|
156
|
+
| 分类 | 方法 |
|
|
157
|
+
| --- | --- |
|
|
158
|
+
| 文本 | `label` / `labelMatch`、`title` / `titleMatch`、`identifier` / `identifierMatch`、`value` / `valueMatch`、`placeholderValue` / `placeholderValueMatch` |
|
|
159
|
+
| 类型状态 | `type` / `typeMatch`、`enabled` |
|
|
160
|
+
| 结构位置 | `index`、`depth`、`childCount`(支持 `">0"`)、`bounds`、`xpath`、`id` |
|
|
183
161
|
|
|
184
162
|
```python
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
# 类型模糊匹配
|
|
189
|
-
def typeMatch(pattern: str) -> NodeSelector
|
|
190
|
-
|
|
191
|
-
# 启用状态
|
|
192
|
-
def enabled(flag: bool) -> NodeSelector
|
|
163
|
+
selector.label("确定").type("XCUIElementTypeButton").getOneNodeInfo(3000)
|
|
164
|
+
selector.labelMatch(".*登录.*").getNodeInfo(3000)
|
|
165
|
+
selector.type("XCUIElementTypeTextField").enabled(True).getOneNodeInfo(3000)
|
|
193
166
|
```
|
|
194
167
|
|
|
195
|
-
|
|
168
|
+
常见类型:`Button`、`StaticText`、`TextField`、`SecureTextField`、`TextView`、`SearchField`、`Cell`、`Table`、`CollectionView`、`PickerWheel`、`Switch`、`Slider` 等(完整名为 `XCUIElementType...`)。
|
|
196
169
|
|
|
197
|
-
|
|
198
|
-
from kuaijs import node
|
|
199
|
-
|
|
200
|
-
selector = node.createNodeSelector()
|
|
170
|
+
---
|
|
201
171
|
|
|
202
|
-
|
|
203
|
-
all_buttons = selector.type("XCUIElementTypeButton").getNodeInfo(3000)
|
|
172
|
+
## 节点操作说明
|
|
204
173
|
|
|
205
|
-
|
|
206
|
-
text_fields = selector.typeMatch("XCUIElementTypeTextField").getNodeInfo(3000)
|
|
207
|
-
|
|
208
|
-
# 查找启用的元素
|
|
209
|
-
enabled_elements = selector.enabled(True).getNodeInfo(3000)
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
##### 位置与结构
|
|
174
|
+
### 是否可点 / 滚到可见
|
|
213
175
|
|
|
214
176
|
```python
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
# 子节点数量(支持表达式,如 ">0")
|
|
222
|
-
def childCount(expr: Union[int, str]) -> NodeSelector
|
|
223
|
-
|
|
224
|
-
# 边界范围
|
|
225
|
-
def bounds(x: int, y: int, width: int, height: int) -> NodeSelector
|
|
226
|
-
|
|
227
|
-
# XPath 路径
|
|
228
|
-
def xpath(path: str) -> NodeSelector
|
|
177
|
+
if node.hittable():
|
|
178
|
+
node.tap()
|
|
179
|
+
else:
|
|
180
|
+
node.scrollToVisible()
|
|
181
|
+
node.tap()
|
|
229
182
|
```
|
|
230
183
|
|
|
231
|
-
|
|
184
|
+
- `hittable()`:当前能否点到
|
|
185
|
+
- `scrollToVisible()`:手动滚到可见
|
|
186
|
+
- `tap` / `doubleTap` / `press`:不可见时会自动尝试滚到可见再操作
|
|
232
187
|
|
|
233
|
-
|
|
188
|
+
### 点击
|
|
234
189
|
|
|
235
190
|
```python
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
#
|
|
247
|
-
parent_elements = selector.childCount(">0").getNodeInfo(3000)
|
|
248
|
-
|
|
249
|
-
# 查找特定区域的元素
|
|
250
|
-
region_elements = selector.bounds(100, 100, 200, 50).getNodeInfo(3000)
|
|
251
|
-
|
|
252
|
-
# 使用 XPath 查找
|
|
253
|
-
xpath_elements = selector.xpath("//*[@title='快点JS']").getNodeInfo(3000)
|
|
191
|
+
btn = (
|
|
192
|
+
selector.label("确定")
|
|
193
|
+
.type("XCUIElementTypeButton")
|
|
194
|
+
.getOneNodeInfo(3000)
|
|
195
|
+
)
|
|
196
|
+
if btn:
|
|
197
|
+
btn.tap()
|
|
198
|
+
btn.doubleTap()
|
|
199
|
+
btn.press(800)
|
|
200
|
+
# btn.clickCenter()
|
|
201
|
+
# btn.clickRandom()
|
|
254
202
|
```
|
|
255
203
|
|
|
256
|
-
|
|
204
|
+
### 输入与设值
|
|
257
205
|
|
|
258
|
-
|
|
206
|
+
| 方法 | 说明 |
|
|
207
|
+
| --- | --- |
|
|
208
|
+
| `clearInput()` | 清空 |
|
|
209
|
+
| `input(text)` | 追加输入 |
|
|
210
|
+
| `setValue(text)` | 按类型设置 |
|
|
259
211
|
|
|
260
|
-
|
|
212
|
+
| 控件 | 传参 | 效果 |
|
|
213
|
+
| --- | --- | --- |
|
|
214
|
+
| `PickerWheel` | 选项文案,如 `"1小时"` | 滚到该选项 |
|
|
215
|
+
| 文本框类 | 字符串 | 追加输入,不先清空 |
|
|
261
216
|
|
|
262
217
|
```python
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
# 随机点击节点区域(坐标点击)
|
|
267
|
-
def clickRandom() -> bool
|
|
268
|
-
|
|
269
|
-
# 节点是否可接收事件(用于判断是否显示在屏幕上)
|
|
270
|
-
def hittable() -> bool
|
|
271
|
-
|
|
272
|
-
# 无障碍点击
|
|
273
|
-
def tap() -> bool
|
|
274
|
-
|
|
275
|
-
# 无障碍双击
|
|
276
|
-
def doubleTap() -> bool
|
|
277
|
-
|
|
278
|
-
# 无障碍长按,duration 单位毫秒,默认 500
|
|
279
|
-
def press(duration: int = 500) -> bool
|
|
280
|
-
|
|
281
|
-
# 将节点滚动到可见区域
|
|
282
|
-
def scrollToVisible() -> bool
|
|
218
|
+
field.clearInput()
|
|
219
|
+
field.setValue("hello")
|
|
283
220
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
# 追加输入
|
|
288
|
-
def input(text: str) -> bool
|
|
289
|
-
|
|
290
|
-
# 设置节点的值
|
|
291
|
-
def setValue(text: str) -> bool
|
|
221
|
+
wheel = selector.type("XCUIElementTypePickerWheel").getOneNodeInfo(3000)
|
|
222
|
+
if wheel:
|
|
223
|
+
wheel.setValue("1小时")
|
|
292
224
|
```
|
|
293
225
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
通过无障碍 API 直接操作节点,不依赖坐标点击。
|
|
297
|
-
|
|
298
|
-
| 方法 | 参数 | 说明 |
|
|
299
|
-
| --- | --- | --- |
|
|
300
|
-
| `tap()` | 无 | 无障碍单击 |
|
|
301
|
-
| `doubleTap()` | 无 | 无障碍双击 |
|
|
302
|
-
| `press(duration=500)` | `duration`:长按持续时间,单位毫秒,默认 500 | 无障碍长按 |
|
|
303
|
-
|
|
304
|
-
**示例:**
|
|
226
|
+
### 树导航
|
|
305
227
|
|
|
306
228
|
```python
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
# 无障碍单击
|
|
314
|
-
btn.tap()
|
|
315
|
-
|
|
316
|
-
# 无障碍双击
|
|
317
|
-
btn.doubleTap()
|
|
318
|
-
|
|
319
|
-
# 无障碍长按 800ms
|
|
320
|
-
btn.press(800)
|
|
229
|
+
field = selector.type("XCUIElementTypeTextField").getOneNodeInfo(3000)
|
|
230
|
+
if field:
|
|
231
|
+
parent = field.parent()
|
|
232
|
+
children = parent.allChildren() if parent else []
|
|
233
|
+
prev = field.previousSiblings()
|
|
234
|
+
next_ = field.nextSiblings()
|
|
321
235
|
```
|
|
322
236
|
|
|
323
|
-
|
|
237
|
+
---
|
|
324
238
|
|
|
325
|
-
|
|
239
|
+
## 示例
|
|
326
240
|
|
|
327
|
-
|
|
328
|
-
| --- | --- | --- |
|
|
329
|
-
| `XCUIElementTypePickerWheel` | `"1小时"` | 滚轮选到对应选项文案 |
|
|
330
|
-
| `XCUIElementTypeTextField` | `"hello"` | 先聚焦再输入文本 |
|
|
331
|
-
| `XCUIElementTypeSecureTextField` | `"123456"` | 同上 |
|
|
332
|
-
| `XCUIElementTypeTextView` | `"多行内容"` | 同上 |
|
|
333
|
-
| `XCUIElementTypeSearchField` | `"关键词"` | 同上 |
|
|
334
|
-
|
|
335
|
-
文本类控件不会先清空已有内容;需要清空时先调用 `clearInput()`。
|
|
336
|
-
|
|
337
|
-
**示例:**
|
|
241
|
+
### 登录
|
|
338
242
|
|
|
339
243
|
```python
|
|
340
244
|
from kuaijs import node
|
|
341
245
|
|
|
342
246
|
selector = node.createNodeSelector()
|
|
343
247
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
wheel.setValue("1小时")
|
|
248
|
+
user = selector.type("XCUIElementTypeTextField").getOneNodeInfo(5000)
|
|
249
|
+
if user:
|
|
250
|
+
user.clearInput()
|
|
251
|
+
user.setValue("demo_user")
|
|
252
|
+
|
|
253
|
+
password = (
|
|
254
|
+
selector.clearSelector()
|
|
255
|
+
.type("XCUIElementTypeSecureTextField")
|
|
256
|
+
.getOneNodeInfo(3000)
|
|
257
|
+
)
|
|
258
|
+
if password:
|
|
259
|
+
password.clearInput()
|
|
260
|
+
password.setValue("password")
|
|
261
|
+
|
|
262
|
+
login = (
|
|
263
|
+
selector.clearSelector()
|
|
264
|
+
.labelMatch(".*登录.*")
|
|
265
|
+
.type("XCUIElementTypeButton")
|
|
266
|
+
.getOneNodeInfo(3000)
|
|
267
|
+
)
|
|
268
|
+
if login:
|
|
269
|
+
login.tap()
|
|
367
270
|
```
|
|
368
271
|
|
|
369
|
-
###
|
|
272
|
+
### 列表里靠后的项
|
|
370
273
|
|
|
371
274
|
```python
|
|
372
|
-
|
|
373
|
-
def parent() -> Optional[NodeInfo]
|
|
374
|
-
|
|
375
|
-
# 获取指定索引的子节点
|
|
376
|
-
def child(index: int) -> Optional[NodeInfo]
|
|
377
|
-
|
|
378
|
-
# 获取所有子节点
|
|
379
|
-
def allChildren() -> List[NodeInfo]
|
|
380
|
-
|
|
381
|
-
# 获取兄弟节点
|
|
382
|
-
def siblings() -> List[NodeInfo]
|
|
383
|
-
|
|
384
|
-
# 获取前面的兄弟节点
|
|
385
|
-
def previousSiblings() -> List[NodeInfo]
|
|
275
|
+
from kuaijs import node
|
|
386
276
|
|
|
387
|
-
|
|
388
|
-
|
|
277
|
+
selector = node.createNodeSelector({"mode": 2})
|
|
278
|
+
item = selector.label("第 30 项").getOneNodeInfo(5000)
|
|
279
|
+
if item:
|
|
280
|
+
item.tap() # 不在可见区域时会自动滚动
|
|
389
281
|
```
|
|
390
282
|
|
|
391
|
-
|
|
283
|
+
### 查看界面结构
|
|
392
284
|
|
|
393
285
|
```python
|
|
394
286
|
from kuaijs import node
|
|
395
287
|
|
|
396
288
|
selector = node.createNodeSelector()
|
|
289
|
+
xml = selector.xml(8000)
|
|
290
|
+
if xml:
|
|
291
|
+
print(xml)
|
|
292
|
+
```
|
|
397
293
|
|
|
398
|
-
|
|
399
|
-
text_field = selector.type("XCUIElementTypeTextField").getOneNodeInfo(3000)
|
|
294
|
+
---
|
|
400
295
|
|
|
401
|
-
|
|
402
|
-
container = text_field.parent()
|
|
403
|
-
if container:
|
|
404
|
-
print(f"容器类型: {container.type}")
|
|
296
|
+
## 常见问题
|
|
405
297
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
print(f"容器包含 {len(children)} 个子元素")
|
|
298
|
+
**找不到节点**
|
|
299
|
+
加大超时;减少条件或改用 `*Match`;换 `mode`;用 `xml()` 看实际文案和类型。
|
|
409
300
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
301
|
+
**点了没反应**
|
|
302
|
+
先看 `hittable()`;确认点到的是目标控件;可对比 `clickCenter()`。
|
|
303
|
+
|
|
304
|
+
**输入叠在旧文字后面**
|
|
305
|
+
`input` / 文本类 `setValue` 是追加,先 `clearInput()`。
|
|
306
|
+
|
|
307
|
+
**滚轮设不中**
|
|
308
|
+
`setValue` 要传界面上显示的选项文案;确认类型是 `PickerWheel`;多列时选对那一列。
|