# 最佳实践和实战案例

纯视觉网页自动化的成功技巧和真实案例分析。

---

## 实战案例：成功的点击策略

### 案例1：H5活动页面按钮点击

**场景**：需要点击活动页面上的按钮，但按钮使用背景图实现，不是标准的 `<img>` 标签。

**成功方法**：

#### 1. 完整页面分析
```python
# 获取所有元素信息
get_all_elements = """
var buttons = document.querySelectorAll('.ui-button, .button1');
var results = [];
for (var i = 0; i < buttons.length; i++) {
    var btn = buttons[i];
    var rect = btn.getBoundingClientRect();
    var bg = window.getComputedStyle(btn).backgroundImage;
    results.push({
        index: i,
        x: Math.round(rect.left + rect.width / 2),
        y: Math.round(rect.top + rect.height / 2),
        width: Math.round(rect.width),
        height: Math.round(rect.height),
        backgroundImage: bg
    });
}
return results;
"""
elements = browser.driver.execute_script(get_all_elements)
```

#### 2. 通过尺寸筛选目标按钮
```python
# 找到尺寸为 202x75 的按钮（原始尺寸 310x115 缩放后）
target_buttons = [e for e in elements
                  if abs(e['width'] - 202) < 10 and abs(e['height'] - 75) < 10]
```

#### 3. 使用 JavaScript 直接点击
```python
js_click = """
var buttons = document.querySelectorAll('.ui-button');
for (var i = 0; i < buttons.length; i++) {
    var btn = buttons[i];
    var rect = btn.getBoundingClientRect();

    // 检查尺寸匹配
    if (rect.width >= 190 && rect.width <= 220 &&
        rect.height >= 65 && rect.height <= 85) {
        // 滚动到可见位置
        btn.scrollIntoView({behavior: 'auto', block: 'center'});
        // 直接点击
        btn.click();
        return {success: true, x: Math.round(rect.left + rect.width / 2),
                y: Math.round(rect.top + rect.height / 2)};
    }
}
return {success: false};
"""
result = browser.driver.execute_script(js_click)
```

**成功坐标**：
- 左侧按钮：`(528, 650)`
- 右侧按钮：`(752, 650)`

**关键要点**：
- ✅ 使用 `scrollIntoView()` 确保元素在视口内
- ✅ 通过 `backgroundImage` 识别背景图按钮
- ✅ 使用尺寸范围而非精确值（考虑缩放）
- ✅ JavaScript 点击比坐标点击更可靠（处理了滚动和层级）

---

### 案例2：多次点击测试

**场景**：需要多次点击按钮触发不同状态。

**成功方法**：
```python
# 多次点击循环
for round_num in range(1, 4):
    # 点击左侧按钮
    result_left = browser.driver.execute_script(js_click_left)
    time.sleep(2)

    # 验证状态
    screenshot = browser.screenshot_base64()

    # 点击右侧按钮
    result_right = browser.driver.execute_script(js_click_right)
    time.sleep(2)

    # 验证状态
    print(f'第 {round_num} 轮完成，URL: {browser.get_url()}')
```

**最佳实践**：
- 每次点击后等待 2-3 秒
- 截图验证状态变化
- 记录 URL 变化
- 使用循环处理重复操作

---

### 案例3：元素定位策略

**当元素难以定位时，使用多层筛选**：

```python
# 1. 按类名筛选
elements = document.querySelectorAll('.ui-button, [class*="button"]')

# 2. 按尺寸筛选
filtered = [e for e in elements if 190 <= e.width <= 220]

# 3. 按位置筛选
target = [e for e in filtered if 600 <= e.y <= 700]

# 4. 按索引选择
first_button = target[0]  # 左侧
second_button = target[1] # 右侧
```

---

## 调试技巧

### 1. 保存详细日志
```python
# 生成元素分析报告
with open('page_elements.json', 'w') as f:
    json.dump(all_elements, f, indent=2)
```

### 2. 截图对比
```python
# 操作前后截图对比
before = browser.screenshot_base64()
browser.driver.execute_script(
    "const el=document.elementFromPoint(arguments[0], arguments[1]); if(el){el.click();}",
    x, y
)
after = browser.screenshot_base64()
# 保存两张截图以对比差异
```

### 3. 坐标标注
```python
# 在截图上标注点击位置
annotated = browser.annotated_screenshot(x, y, "点击位置")
```

---

## 成功技巧汇总

1. **首先使用网格截图**以理解坐标空间
2. **每次操作后验证**使用新截图
3. **点击中心，不要点边缘**针对按钮和输入框
4. **滚动显示**屏幕外元素后再点击
5. **清晰报告**完成或阻塞时
6. **保持操作简单** - 每轮一个明确的操作
7. **使用 JavaScript 点击** - 比坐标点击更可靠
8. **多层筛选** - 类名 → 尺寸 → 位置 → 索引
9. **等待和验证** - 每次操作后等待 2-3 秒并截图验证
10. **保存日志** - 记录元素信息、坐标、URL 变化

---

## 常见问题和解决方案

### 问题1：点击无响应

**原因**：
- 元素被遮挡
- 坐标不准确
- 未使用 JavaScript 点击

**解决方案**：
```python
# 使用 JavaScript 点击并滚动到元素
js_click = """
const el = document.elementFromPoint(arguments[0], arguments[1]);
if(el) {
    el.scrollIntoView({behavior: 'auto', block: 'center'});
    el.click();
}
"""
browser.driver.execute_script(js_click, x, y)
```

### 问题2：元素位置不对

**原因**：
- 页面未完全加载
- H5 页面未刷新
- 坐标系统不对（移动端 vs 桌面端）

**解决方案**：
```python
# H5 页面必须先刷新
browser.refresh()
time.sleep(2)

# 验证视口尺寸
width, height = browser.get_viewport_size()
print(f"当前视口: {width}x{height}")
```

### 问题3：找不到元素

**原因**：
- 元素在屏幕外
- 元素尚未加载
- 元素被隐藏

**解决方案**：
```python
# 滚动到元素位置
browser.scroll_to_bottom()
time.sleep(1)

# 检查元素是否存在
check_element = """
const el = document.elementFromPoint(arguments[0], arguments[1]);
return el ? {tag: el.tagName, class: el.className} : null;
"""
element_info = browser.driver.execute_script(check_element, x, y)
print(f"元素信息: {element_info}")
```

---

[← 返回主文档](../SKILL.md)
