【AI】基于OpenManus实现鼠标控制

7 阅读4分钟

—基于真实存在的 OpenManus(开源 Agent 框架)+ Qwen2.5-VL(本地视觉模型)+ PyAutoGUI(鼠标控制),在 Ubuntu 22.04 上实现你要的网页登录+鼠标点击签到功能。


方案总览

组件选型作用
OSUbuntu 22.04 LTS基础环境
视觉模型Qwen2.5-VL-7B/14B (Int4 量化)识别按钮坐标、验证码、页面元素
Agent 框架OpenManus (开源)任务规划、决策逻辑
鼠标控制PyAutoGUI物理级鼠标移动/点击(跨应用)
浏览器Playwright (Chromium)网页自动化、登录态保持

核心逻辑
Agent 看到屏幕 → Qwen2.5-VL 识别"登录按钮坐标" → PyAutoGUI 移动鼠标点击 → 输入账号 → 找到"签到按钮" → 点击完成


从零开始部署步骤

1. 系统环境准备(Ubuntu 22.04)

# 更新系统
sudo apt update && sudo apt upgrade -y

# 安装基础依赖
sudo apt install -y python3-pip python3-venv git curl wget \
    libgl1-mesa-glx libglib2.0-0 libsm6 libxext6 libxrender-dev \
    scrot # 截图工具,PyAutoGUI 依赖

# 安装 Node.js 18+(OpenManus 需要)
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs

# 安装 Ollama(部署本地 Qwen2.5-VL)
curl -fsSL https://ollama.com/install.sh | sh

# 启动 Ollama 服务(后台运行)
sudo systemctl start ollama
sudo systemctl enable ollama

2. 部署 Qwen2.5-VL(本地视觉模型)

Qwen2.5-VL 是阿里开源的视觉语言模型,能识别图片中的 UI 元素并返回坐标。

# 拉取 Qwen2.5-VL 7B 量化版(约 4.5GB,需 8GB+ VRAM,无显卡用纯 CPU 极慢)
ollama pull qwen2.5:7b

# 验证部署
ollama run qwen2.5:7b "描述这张图片" # 测试对话能力

关键配置:OpenManus 需要模型支持 OpenAI-compatible API,Ollama 默认提供 http://localhost:11434/v1 端点。

3. 安装 OpenManus 并配置本地模型

# 克隆 OpenManus
git clone https://github.com/man-group/OpenManus.git
cd OpenManus

# 安装 Python 依赖
pip3 install -e .

# 创建配置文件
mkdir -p ~/.config/openmanus
cat > ~/.config/openmanus/config.toml << 'EOF'
[llm]
model = "qwen2.5:7b"
base_url = "http://localhost:11434/v1"
api_key = "ollama"  # Ollama 不需要真实 key,但字段必须存在
temperature = 0.2   # 降低随机性,确保坐标准确
max_tokens = 2048

[browser]
headless = false    # 必须 false,才能看到浏览器并被 PyAutoGUI 控制
EOF

4. 开发自定义 Tool:鼠标控制与视觉识别

OpenManus 默认没有物理鼠标控制能力,需自行扩展。

创建文件 openmanus/tools/mouse_control.py

import pyautogui
import time
import base64
from io import BytesIO
from PIL import Image
from typing import Tuple, Optional
from openmanus.tools.base import BaseTool

class MouseControlTool(BaseTool):
    name = "mouse_control"
    description = "物理鼠标控制:移动、点击、截图。支持视觉定位。"
    
    def __init__(self):
        # 禁用 PyAutoGUI 的安全边界(防止鼠标移到角落报错)
        pyautogui.FAILSAFE = False
        # 获取屏幕尺寸
        self.screen_width, self.screen_height = pyautogui.size()
    
    async def screenshot(self) -> str:
        """截图并转为 base64,供 Qwen-VL 分析"""
        screenshot = pyautogui.screenshot()
        buffered = BytesIO()
        screenshot.save(buffered, format="PNG")
        return base64.b64encode(buffered.getvalue()).decode()
    
    async def get_coordinates_from_vlm(self, description: str, base64_image: str) -> Optional[Tuple[int, int]]:
        """
        调用 Qwen2.5-VL 识别元素坐标
        返回: (x, y) 屏幕坐标
        """
        # 这里调用 Ollama API 进行视觉识别
        import openai
        client = openai.OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
        
        response = client.chat.completions.create(
            model="qwen2.5:7b",
            messages=[
                {
                    "role": "user",
                    "content": [
                        {"type": "text", "text": f"在图片中找到'{description}'的位置,返回屏幕坐标(x,y)。只返回数字格式:x,y,不要其他文字。"},
                        {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{base64_image}"}}
                    ]
                }
            ]
        )
        
        try:
            coord_str = response.choices[0].message.content.strip()
            x, y = map(int, coord_str.split(','))
            # 边界检查
            x = max(0, min(x, self.screen_width))
            y = max(0, min(y, self.screen_height))
            return (x, y)
        except:
            return None
    
    async def click(self, x: int, y: int):
        """移动鼠标并点击"""
        pyautogui.moveTo(x, y, duration=0.5)  # 0.5秒移动,避免被检测为机器人
        time.sleep(0.1)
        pyautogui.click()
        time.sleep(0.5)  # 等待页面响应
    
    async def type_text(self, text: str):
        """模拟键盘输入"""
        pyautogui.typewrite(text, interval=0.05)  # 每个字符间隔 50ms,模拟人类
    
    async def press_enter(self):
        pyautogui.press('enter')

5. 编写签到 Agent 任务流

创建 signin_agent.py

import asyncio
from mouse_control import MouseControlTool
from openmanus.tools.browser import BrowserTool

class SignInAgent:
    def __init__(self):
        self.mouse = MouseControlTool()
        self.browser = BrowserTool()
    
    async def run(self, url: str, username: str, password: str):
        # 1. 启动浏览器并导航
        await self.browser.navigate(url)
        await asyncio.sleep(3)  # 等待页面加载
        
        # 2. 截图并找到"账号输入框"
        screenshot = await self.mouse.screenshot()
        coord = await self.mouse.get_coordinates_from_vlm("账号输入框/用户名输入框", screenshot)
        
        if coord:
            await self.mouse.click(*coord)
            await self.mouse.type_text(username)
            print(f"已输入账号在坐标: {coord}")
        
        # 3. 找到密码框并输入
        screenshot = await self.mouse.screenshot()
        coord = await self.mouse.get_coordinates_from_vlm("密码输入框", screenshot)
        if coord:
            await self.mouse.click(*coord)
            await self.mouse.type_text(password)
            await self.mouse.press_enter()
            print(f"已输入密码并提交")
            await asyncio.sleep(3)  # 等待登录
        
        # 4. 寻找签到按钮(可能需滚动页面)
        for attempt in range(3):  # 尝试3次滚动查找
            screenshot = await self.mouse.screenshot()
            coord = await self.mouse.get_coordinates_from_vlm("签到按钮/Sign In Button", screenshot)
            
            if coord:
                await self.mouse.click(*coord)
                print(f"已点击签到按钮,坐标: {coord}")
                return "签到成功"
            else:
                # 向下滚动
                pyautogui.scroll(-500)
                await asyncio.sleep(1)
        
        return "未找到签到按钮"

# 运行
if __name__ == "__main__":
    agent = SignInAgent()
    result = asyncio.run(agent.run(
        url="https://your-signin-website.com",
        username="your_username",
        password="your_password"
    ))
    print(result)

6. 运行与调试

# 安装 Playwright 浏览器(Chromium)
playwright install chromium

# 运行 Agent(需在图形界面下,SSH 不行,必须本地或 VNC)
python3 signin_agent.py

常见问题

  • 坐标不准:Qwen2.5-VL 7B 可能识别精度不足,建议换 14B 或调整提示词(要求返回中心点坐标)。
  • 被反爬:网站检测 Selenium/Playwright,需加 stealth 插件或换用undetected-chromedriver。
  • 无头模式:若用 headless=True,PyAutoGUI 无法截图浏览器窗口,必须用 headed 模式。