项目简介

Precision Locator 是一款基于 Playwright 和大语言模型的智能页面元素定位 MCP 服务,旨在解决自动化测试和 RPA 场景中元素定位不稳定的痛点。通过独创的四级降级策略(本地 OCR → 文本定位 → 截图 LLM → 坐标定位),实现从自然语言指令到精准元素操作的自动转换。

核心特性:

  • 四级降级策略:Level 0 零 Token → Level 1 低 Token → Level 2 中 Token → Level 3 终极兜底

  • 坐标→稳定定位器转换:像素坐标反查 DOM 属性,消除分辨率依赖

  • 本地视觉定位:PaddleOCR + OpenCV 模板匹配,零 Token 消耗

  • 翻译检测:自动拦截 LLM 将中文元素文本翻译为英文的行为

  • 图标定位:表头筛选图标、操作按钮等非文字元素的精准定位

  • 多模型支持:OpenAI / 智谱 / MiniMax / 通义千问 / DeepSeek / Moonshot

  • MCP 协议:通过 Model Context Protocol 与 AI 客户端无缝集成

  • 模块化架构:11 个独立模块,每个类单独文件,开源项目级代码质量

开源地址: https://github.com/zxpFreesky/ai_locator_agent


核心架构

用户指令 → SmartExecutor → 四级降级策略 → Playwright 操作
                             │
    ┌────────────────────────┼────────────────────────┐
    │                        │                        │
    ▼                        ▼                        ▼
 Level 0                  Level 1                  Level 2/3
 (零Token)               (低Token)               (中/高Token)
┌──────────┐    ┌──────────────────┐    ┌──────────────────┐
│PaddleOCR │    │ DOMExtractor     │    │ScreenshotLocator │
│OpenCV    │    │ LocatorAgent     │    │ 多模态LLM分析    │
│模板匹配  │    │ VisualLocator    │    │ 定位器/坐标      │
└────┬─────┘    │ SafeBuilder      │    └────────┬─────────┘
     │          │ FallbackRule     │             │
     │          │ DirectQuery      │             │
     │          └──────────────────┘             │
     │                    │                      │
     └────────┬───────────┘                      │
              ▼                                  ▼
    ┌──────────────────────────────────────────────────┐
    │          坐标 → 稳定定位器转换                     │
    │   document.elementFromPoint(x,y)                 │
    │   → data-testid > placeholder > role+name        │
    │     > text > class                               │
    └──────────────────────────────────────────────────┘

项目结构

precision_locator/
├── __init__.py              # 包入口,统一导出
├── utils.py                 # 工具函数(日志、清洗、中文检测)
├── dom_extractor.py         # DOM 紧凑采集器
├── llm_config.py            # 多模型 LLM 配置(6家供应商)
├── locator_agent.py         # AI 定位器生成(Level 1c)
├── visual_locator.py        # DOM 上下文视觉定位(Level 1b)
├── screenshot_locator.py    # 截图视觉定位(Level 2/3)
├── safe_locator.py          # Playwright 定位器安全构建
├── local_vision.py          # 本地 OCR + 模板匹配(Level 0)
├── executor.py              # 智能执行器(核心调度引擎)
└── server.py                # MCP Server 入口(9个工具)

四级降级策略详解

Level 0 — 本地视觉定位(零 Token 消耗)

使用 PaddleOCR 进行文字识别 + OpenCV 模板匹配,在本地完成元素定位,不消耗任何 LLM Token

工作流程:

  1. 截取当前页面截图

  2. PaddleOCR 识别所有文字区域

  3. 通过 bigram/trigram 分词从用户指令中提取搜索词

  4. 在 OCR 结果中搜索匹配文本,返回中心坐标

排序优先级: 最长搜索词匹配 > 最短文本长度 > 最高置信度

DOM 补充机制: 当 OCR 无法识别(如白色文字在透明背景上)时,自动降级到 DOM 属性查询,直接查询 placeholder/role/text 等属性生成定位器。

# bigram/trigram 分词示例
# 指令:"点击我的客户标签页"
chinese_chars = ['我', '的', '客', '户', '标', '签', '页']
# 4-gram: 我的客户, 的客户标, 客户标签, 户标签页
# 3-gram: 我的客, 的客户, 客户标, 户标签, 标签页
# 2-gram: 我的, 的客, 客户, 户标, 标签, 签页

Level 1 — 文本定位(低 Token 消耗)

五个子策略按顺序尝试:

子策略

优先级

说明

_match_by_testid

1a

从指令提取关键词,匹配 DOM 的 data-testid 属性

visual_locator

1b

复杂场景(表头/图标/弹窗)用 LLM + DOM 上下文

locator_agent

1c

LLM 根据 DOM 结构生成定位器,后校验文本存在性

_fallback_rule

1d

硬编码规则匹配常见 UI 模式

_direct_text_query

1e

Playwright 原生 API 在页面中搜索

Level 2 — 截图 + 多模态 LLM(中 Token 消耗)

将页面截图发送给多模态 LLM(GPT-4o / GLM-4V / Qwen-VL),直接生成 Playwright 定位器表达式。

Level 3 — LLM 坐标定位(高 Token 消耗,终极兜底)

多模态 LLM 分析截图返回目标元素的像素坐标 {x, y},然后通过坐标→稳定定位器转换机制生成不依赖分辨率的定位器。


核心模块详解

1. DOMExtractor - DOM 紧凑采集器

通过注入 JavaScript 脚本到页面,提取所有可交互元素的属性。

关键功能:

  • 强制采集关键交互元素(Radio、Tab、Menu),即使不可见也保留

  • 支持提示词相关性排序(hint 参数),提高后续 AI 定位精度

  • 兼容 Element Plus 等 UI 框架(el-tabs__itemel-radio-button

  • 自动推导隐式 role(button"button"a"link"

  • isTab 检测使用 \b 词边界避免误匹配(\bel-tabs__item\b 不匹配 el-table

提取的元素信息:

字段

说明

示例

tag

标签名

input, button, th

text

显示文本

我的客户

placeholder

占位符文本

请输入客户编号

role

ARIA 角色

button, tab, radio

dataTestId

测试 ID

customer-tab

relevance

相关度评分

80

isTab / isRadio / isMenu

特殊元素标记

true

2. LocatorAgent - AI 定位器生成器

将 DOM 结构(截断至 30 个元素、5000 字符)和用户指令发送给 LLM,生成定位器。

后校验机制:

  • get_by_text 的文本参数必须存在于 DOM 的有效文本集合中

  • get_by_role(name=...) 的 name 参数必须存在于 DOM 中

  • get_by_placeholder 的值必须存在于 DOM 中

  • get_by_label 的值必须存在于 DOM 中

  • 翻译检测:指令包含中文 + 生成文本不含中文 + 不在 DOM 中 → 判定为翻译行为,拦截

3. SafeLocator - 安全构建器

解析 LLM 生成的定位器表达式字符串,安全构建 Playwright Locator 对象。

支持的方法:

  • locator(selector) / get_by_role() / get_by_placeholder() / get_by_text() / get_by_title() / get_by_label()

  • .filter(has_text="...") / .first / .last

4. LocalVisionLocator - 本地视觉定位器(单例模式)

两种定位策略:

策略

方法

原理

文字识别

locate_by_text()

PaddleOCR → bigram/trigram 匹配

模板匹配

locate_by_template()

OpenCV matchTemplate + 预存图标

当 PaddleOCR/OpenCV 未安装时自动降级(available=False),不影响其他 Level 运行。

5. ScreenshotLocator - 截图视觉定位器

两种分析模式:

模式

方法

返回

定位器模式

analyze()

Playwright 定位器表达式

坐标模式

analyze_coordinates()

{x, y, description}

429 / 余额不足时自动标记模型不可用,避免连续重试浪费请求。

6. SmartExecutor - 智能执行器(核心调度引擎)

整合所有定位模块,通过 _try_locate_and_act 统一调度四级降级策略。

特殊处理机制:

  • Strict Mode 自动修正:检测 strict mode violation 错误,自动提取推荐定位器重试

  • Force Click:元素被遮挡时自动使用 force=True 点击

  • 图标定位检测:指令含"图标"/"icon"时,通过 _find_icon_near_element 向上遍历 5 层父元素搜索 img/svg


坐标→稳定定位器转换

这是 v5.0 的关键创新,将分辨率依赖的像素坐标转换为稳定的 Playwright 定位器:

像素坐标 (x, y)
    ↓ document.elementFromPoint(x, y)
DOM ElementHandle
    ↓ 提取属性
属性优先级: data-testid > placeholder > role+name > text > class
    ↓ 生成定位器
page.get_by_role("button", name="登录")

对于图标定位,额外调用 _find_icon_near_element,向上遍历父元素找到 th/td/header,搜索其内部的 img/svg 元素:

# 坐标(500, 120) → th 内文字"检讨报告" → 图标定位器
page.locator("th").filter(has_text="检讨报告").locator("img, svg").first

MCP Server 接口

通过 MCP(Model Context Protocol)协议提供 9 个工具:

工具名

描述

参数

navigate

导航到指定 URL

url: string

smart_click

智能点击页面元素

instruction: string

smart_fill

智能填充输入框

instruction: string, value: string

smart_select

智能选择下拉选项

instruction: string, value: string

smart_hover

智能悬停页面元素

instruction: string

smart_check

智能勾选复选框

instruction: string

get_page_structure

获取页面精简 DOM 结构

hint: string (可选)

screenshot

截取当前页面截图

filename: string (可选)

close_browser

关闭浏览器释放资源


实际应用场景

场景 1:CRM 系统自动化测试(11 步完整流程)

import precision_locator.server as pl

await pl.ensure_browser()

# Step 1-2: 导航并登录
await pl._page.goto("https://crm.example.com")
await pl._executor.smart_fill("输入账号", "admin")
await pl._executor.smart_fill("输入密码", "password")
await pl._executor.smart_click("点击登录按钮")

# Step 3-4: 导航到客户管理
await pl._executor.smart_click("点击我的客户标签页")  # Level 0 OCR 命中

# Step 5-7: 筛选客户
await pl._executor.smart_click("点击客户编号表头右侧的筛选图标")  # 图标定位
await pl._executor.smart_fill("输入客户编号筛选框", "C001")
await pl._executor.smart_click("点击确定按钮")

场景 2:复杂表单填写

await executor.smart_click("点击新建按钮")
await executor.smart_fill("输入客户名称", "ABC公司")
await executor.smart_fill("输入联系人", "张三")
await executor.smart_select("选择客户类型", "企业客户")
await executor.smart_check("勾选VIP客户")
await executor.smart_click("点击保存按钮")

配置与部署

环境变量配置

# LLM 配置
LLM_PROVIDER=openai              # openai / zhipu / minimax / qwen / deepseek / moonshot
LLM_MODEL=                       # 留空使用供应商默认模型
LLM_TEMPERATURE=0.0              # 推荐 0.0(确定性输出)

# API Keys(至少配置一个匹配 LLM_PROVIDER 的 Key)
OPENAI_API_KEY=sk-xxx
# ZHIPU_API_KEY=xxx
# DASHSCOPE_API_KEY=xxx
# DEEPSEEK_API_KEY=xxx

# 视觉模型(可选,默认跟随 LLM_PROVIDER)
# VISION_LLM_PROVIDER=openai
# VISION_MODEL=gpt-4o

# 浏览器配置
HEADLESS=false                   # 无头模式
# VIEWPORT=1920x1080             # 视口大小
# LOCALE=zh-CN                   # 浏览器语言

安装与启动

# 安装依赖
pip install -r requirements.txt
playwright install chromium

# 配置环境变量
cp .env.example .env
# 编辑 .env,填入 API Key

# 启动 MCP Server
python -m precision_locator.server

PaddleOCR 依赖较大(~1.5GB),如不需要 Level 0 本地视觉定位,可跳过 paddleocr/paddlepaddle/opencv-python/numpy

支持的 LLM 供应商

供应商

LLM_PROVIDER

默认模型

视觉模型

OpenAI

openai

gpt-4o

gpt-4o

智谱 AI

zhipu

glm-4-plus

glm-4v-plus

MiniMax

minimax

MiniMax-M2.7-Highspeed

-

通义千问

qwen

qwen-plus

qwen-vl-plus

DeepSeek

deepseek

deepseek-chat

-

Moonshot

moonshot

moonshot-v1-8k

-


踩坑记录与技术亮点

1. PaddleOCR 版本陷阱

PaddleOCR 3.x 有破坏性 API 变更:predict() 替代了 ocr()show_log 参数被移除。必须在 requirements.txt 中锁定 <3.0.0

2. 白色文字 OCR 无法识别

密码输入框的 placeholder 渲染为白色文字(rgb(255,255,255))在透明背景上,PaddleOCR 物理上无法看到。解决方案:添加 DOM 补充定位 _dom_supplement_locate(),直接查询 DOM 的 placeholder 属性。同时截图前执行 document.activeElement?.blur() 避免光标干扰。

3. Element Plus 组件的 span 覆盖问题

el-radio-button 内的 span 覆盖了外层元素,导致 intercepts pointer events 错误。解决方案:使用 locator(".el-radio-button").filter(has_text="...") 代替 get_by_label()

4. isTab 误匹配 el-table

最初的 isTab 检测用 'tab' in class_name,会匹配到 el-table。修复:使用 \bel-tabs__item\b 正则词边界。

5. Strict Mode 自动修正

Playwright 的 strict mode violation 错误信息中包含推荐定位器(aka get_by_role(...)),自动提取并重试:

if 'strict mode violation' in error_msg:
    aka_matches = re.findall(r'aka (get_by_\w+\([^)]+\)|locator\([^)]+\))', error_msg)
    # 使用推荐定位器重试

6. LLM 翻译检测

LLM 常常将中文元素文本翻译为英文(如"登录" → "Login")。通过三重条件检测:

  • 指令包含中文

  • 生成文本不含中文

  • 生成文本不在 DOM 有效文本集合中

7. 关键词 Bigram/Trigram 分词

中文不像英文有空格分词,整句"点击我的客户标签页"无法精确匹配。通过 bigram/trigram 滑动窗口提取子词,配合停用词过滤,大幅提升匹配率。


总结

Precision Locator  通过创新性的四级降级策略,在保证高定位成功率的同时最大程度节省 Token 消耗。Level 0 的本地 OCR 直接解决了约 40-50% 的定位需求(零 Token),剩余场景通过 Level 1-3 逐步升级处理。

适用场景:

  • Web 自动化测试(尤其是 Element Plus 等 UI 框架)

  • 机器人流程自动化(RPA)

  • AI 智能助手网页操作

  • 自动化数据采集

未来规划:

  • 增加 iframe 跨域定位支持

  • 优化移动端视口适配

  • 增加元素等待智能策略(动态等待 + 条件等待)

  • 支持 Firefox / WebKit 浏览器引擎

  • 增加 Electron 桌面应用支持

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐