惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

M
MIT News - Artificial intelligence
博客园 - Franky
H
Help Net Security
A
About on SuperTechFans
Know Your Adversary
Know Your Adversary
罗磊的独立博客
Help Net Security
Help Net Security
腾讯CDC
博客园 - 三生石上(FineUI控件)
月光博客
月光博客
Project Zero
Project Zero
有赞技术团队
有赞技术团队
Blog — PlanetScale
Blog — PlanetScale
T
Threat Research - Cisco Blogs
The Hacker News
The Hacker News
Engineering at Meta
Engineering at Meta
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Simon Willison's Weblog
Simon Willison's Weblog
T
Threatpost
Google DeepMind News
Google DeepMind News
V
V2EX
B
Blog
人人都是产品经理
人人都是产品经理
J
Java Code Geeks
N
Netflix TechBlog - Medium
P
Privacy International News Feed
Recorded Future
Recorded Future
D
Darknet – Hacking Tools, Hacker News & Cyber Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Stack Overflow Blog
Stack Overflow Blog
Cisco Talos Blog
Cisco Talos Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Securelist
NISL@THU
NISL@THU
The GitHub Blog
The GitHub Blog
T
Troy Hunt's Blog
S
Security @ Cisco Blogs
Vercel News
Vercel News
L
LINUX DO - 热门话题
博客园_首页
The Register - Security
The Register - Security
GbyAI
GbyAI
TaoSecurity Blog
TaoSecurity Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
V2EX - 技术
V2EX - 技术
L
LangChain Blog
T
Tor Project blog
P
Privacy & Cybersecurity Law Blog
Security Latest
Security Latest
K
Kaspersky official blog

博客园 - 我才是银古

第16章:常见问题、排错与最佳实践 第15章:扩展生态、MCAD 与外部集成 第12章:实战案例:机械结构与 3D 打印零件 第14章:构建、测试、调试与贡献流程 第13章:OpenSCAD 源码架构与核心执行流程 第11章:预览、渲染、网格精度与性能优化 第09章:列表推导、递归与算法建模 第08章:参数化零件库与复用设计 第10章:导入导出、命令行与自动化 第06章:CSG 布尔建模方法 第07章:二维图形、拉伸、旋转与投影 第05章:基础几何、坐标系与变换 第04章:参数、变量、函数、模块与作用域 OpenSCAD 教程目录 第03章:OpenSCAD 语言基础 第02章:安装、环境配置与开发工作流 第01章:OpenSCAD 项目全景与学习路线 第02章:源码获取、编译与开发环境配置 第01章:OCCT项目全景与学习路线 第18章:二次开发实战与综合案例 第18章:综合实战案例 第17章:数据交换与协同 第16章:源码架构与二次开发 第15章:插件与自定义工作台开发 第14章:Python脚本宏与自动化 第13章:FEM仿真分析 第12章:CAM数控加工 第11章:SurfaceMesh与逆向工程 第10章:Draft二维绘图与BIM建筑 第09章:工程图TechDraw 第07章:参数化表达式与Spreadsheet 第08章:装配设计Assembly 第06章:Part工作台与几何内核 第05章:PartDesign实体特征建模 第04章:草图Sketcher约束建模 第02章:安装版本与工作环境配置 第03章:界面工作台与基础操作 第01章:项目全景与学习路线 第十二章:插件开发、研究功能与最佳实践 第十章:定时任务与自动化(Cron) 第七章:技能、记忆与自学习闭环 第八章:MCP 集成与上下文文件 第六章:工具系统与终端后端 第五章:模型供应商与配置体系 Hermes Agent 教程目录 第十一章:语音、视觉、浏览器与子代理协作 第四章:CLI/TUI 与会话管理 第十二章:学习路线、实战方案与最佳实践 第十一章:源码结构、开发调试与插件开发 第十章:自动化、远程访问、日志与排障 第九章:Control UI、节点、Canvas 与语音能力 第七章:工具、技能、插件与能力扩展 第八章:安全模型、访问控制与沙箱实践 第六章:Agent 工作区、会话与多智能体路由 第五章:多通道消息接入与聊天平台配置 第四章:配置体系、模型接入与认证管理 第三章:Gateway 架构、协议与运行机制 第二章:安装、环境准备与快速上手 第一章:OpenClaw 项目概览与核心定位 oh-my-openagent 教程目录 09-命令模型回退与配置参考 10-实战案例最佳实践与故障排除 05-工作模式-Ultrawork-Prometheus-Atlas 08-Hooks与MCP系统 06-Category与Skill系统 07-核心工具链 04-智能体全景详解 03-安装与环境配置 02-整体架构与多模型编排机制 01-项目简介与核心理念 01-项目概览与学习路线 02-安装部署与工具适配 03-Skill机制与using-superpowers 05-TDD系统化调试与完成前验证 04-需求澄清方案设计与计划编写 07-并行智能体子智能体与Git-Worktree 第六章:代码审查、反馈处理与分支收尾 08-中国特色Skills与本土团队落地 09-MCP构建工作流执行与自定义Skill 第23章:FreeCAD-Python-API Clipper2 C# 源码解读教程 第19章:PolyTree 多边形树结构 第20章:实际应用与最佳实践 第18章:Minkowski 和与差 第17章:RectClip 矩形裁剪优化 第16章:ClipperOffset 偏移类详解 第15章:填充规则详解 第14章:布尔运算执行流程 第13章:ClipperD 浮点裁剪类 第11章:OutRec 与 OutPt 输出结构 第9章:Active 活动边结构 第10章:Vertex 顶点与 LocalMinima 局部极小值 第12章:Clipper64 裁剪类详解 第7章:高精度运算与128位整数 第8章:ClipperBase 基类详解 第5章:枚举类型与常量定义 第6章:InternalClipper 内部工具类 第2章:核心数据结构 - Point64、PointD 第3章:路径与多边形表示 - Path64、PathD、Paths64、PathsD 第4章:矩形边界 - Rect64、RectD
第14章 - 综合实战项目
我才是银古 · 2026-06-24 · via 博客园 - 我才是银古

第14章 - 综合实战项目

前面十三章我们分模块讲解了 RobotGo 的各项能力。本章把这些能力融会贯通,通过几个由简到繁的完整实战项目,演示如何在真实场景中组织自动化代码。每个项目都给出完整可读的结构与关键实现,帮助你建立“工程化使用 RobotGo”的思路。

14.1 项目一:自动化表单填写

场景:在某个桌面应用或网页表单中,按固定流程填写多个字段并提交。这是 RPA 最经典的应用。

核心思路:定位输入框(用 Tab 切换或图像查找)→ 输入文本(长文本走剪贴板)→ 提交。

package main

import (
    "runtime"

    "github.com/go-vgo/robotgo"
)

func cmdKey() string {
    if runtime.GOOS == "darwin" {
        return "cmd"
    }
    return "ctrl"
}

// 通过剪贴板可靠地输入一个字段,然后用 Tab 跳到下一个
func fillField(value string) {
    robotgo.WriteAll(value)
    robotgo.MilliSleep(60)
    robotgo.KeyTap("v", cmdKey())
    robotgo.MilliSleep(60)
    robotgo.KeyTap("tab")
}

func main() {
    robotgo.MouseSleep = 150
    robotgo.KeySleep = 80

    // 给用户时间切换到目标表单并点中第一个输入框
    robotgo.Sleep(3)

    fillField("张三")
    fillField("13800000000")
    fillField("北京市海淀区中关村大街 1 号")
    fillField("这是一段较长的备注信息,用剪贴板粘贴可以避免逐字输入的低效与丢字问题。")

    // 提交(假设提交按钮可用回车触发)
    robotgo.KeyTap("enter")
}

要点:用剪贴板粘贴而非逐字 Type,配合 Tab 在字段间跳转,避免硬编码每个输入框坐标,使脚本更稳健。

14.2 项目二:图像驱动的自动点击器

场景:等待某个按钮/图标出现在屏幕上,一旦出现就自动点击它。适合“等加载完成再操作”的流程,或简单的挂机点击。

核心思路:循环截图 → 位图查找模板 → 找到则点击 → 直到超时或用户停止。

package main

import (
    "fmt"

    "github.com/go-vgo/robotgo"
    "github.com/vcaesar/bitmap"
)

// 在屏幕中查找模板图并点击,返回是否点击成功
func clickByImage(template string) bool {
    bit := bitmap.Open(template)
    defer robotgo.FreeBitmap(bit)

    fx, fy := bitmap.Find(bit)
    if fx < 0 || fy < 0 {
        return false
    }
    robotgo.Move(fx, fy)
    robotgo.MilliSleep(100)
    robotgo.Click()
    return true
}

func main() {
    template := "button.png" // 预先截好的按钮模板
    fmt.Println("开始监视按钮,最多等待 30 秒...")

    elapsed := 0
    for elapsed < 30000 {
        if clickByImage(template) {
            fmt.Println("已点击目标按钮")
            return
        }
        robotgo.MilliSleep(500)
        elapsed += 500
    }
    fmt.Println("超时,未发现目标按钮")
}

要点:用图像查找代替固定坐标,使脚本不受窗口位置变化影响;用轮询 + 超时机制保证健壮,避免无限等待。

14.3 项目三:全局热键启动器

场景:常驻后台的小工具,按下不同全局热键执行不同自动化动作(粘贴模板文本、打开网址、截图等)。综合运用 gohook 与 robotgo。

package main

import (
    "fmt"
    "runtime"

    "github.com/go-vgo/robotgo"
    hook "github.com/robotn/gohook"
)

func cmdKey() string {
    if runtime.GOOS == "darwin" {
        return "cmd"
    }
    return "ctrl"
}

func pasteText(text string) {
    robotgo.WriteAll(text)
    robotgo.MilliSleep(50)
    robotgo.KeyTap("v", cmdKey())
}

func main() {
    fmt.Println("热键启动器已就绪:")
    fmt.Println("  ctrl+shift+1 → 粘贴签名")
    fmt.Println("  ctrl+shift+2 → 截全屏到 shot.png")
    fmt.Println("  ctrl+shift+q → 退出")

    // 热键 1:粘贴签名
    hook.Register(hook.KeyDown, []string{"1", "ctrl", "shift"}, func(e hook.Event) {
        pasteText("此致\n敬礼\n张三")
    })

    // 热键 2:截图
    hook.Register(hook.KeyDown, []string{"2", "ctrl", "shift"}, func(e hook.Event) {
        robotgo.SaveCapture("shot.png")
        fmt.Println("已保存截图 shot.png")
    })

    // 热键 Q:退出
    hook.Register(hook.KeyDown, []string{"q", "ctrl", "shift"}, func(e hook.Event) {
        fmt.Println("退出")
        hook.End()
    })

    s := hook.Start()
    <-hook.Process(s)
}

要点:用 Register 注册多个热键;务必提供一个退出热键调用 hook.End();回调内的动作要轻量。

14.4 项目四:定向操作指定应用

场景:找到某个特定应用(如浏览器),激活它,在地址栏输入网址并访问。综合运用进程窗口管理与键盘输入。

package main

import (
    "fmt"
    "runtime"

    "github.com/go-vgo/robotgo"
)

func cmdKey() string {
    if runtime.GOOS == "darwin" {
        return "cmd"
    }
    return "ctrl"
}

func openURLInApp(appName, url string) error {
    pids, err := robotgo.FindIds(appName)
    if err != nil || len(pids) == 0 {
        return fmt.Errorf("未找到应用 %s", appName)
    }

    // 激活窗口并等待其切到前台
    robotgo.ActivePid(pids[0])
    robotgo.MilliSleep(400)
    fmt.Println("当前窗口:", robotgo.GetTitle())

    // 定位地址栏(多数浏览器为 Ctrl/Cmd + L),输入并回车
    robotgo.KeyTap("l", cmdKey())
    robotgo.MilliSleep(100)
    robotgo.WriteAll(url)
    robotgo.MilliSleep(50)
    robotgo.KeyTap("v", cmdKey())
    robotgo.KeyTap("enter")
    return nil
}

func main() {
    if err := openURLInApp("chrome", "https://github.com/go-vgo/robotgo"); err != nil {
        fmt.Println("出错:", err)
    }
}

要点:先 FindIdsActivePid 激活,激活后留足延时;用 GetTitle 确认窗口;用剪贴板粘贴 URL 比逐字输入更可靠。

14.5 项目五:操作录制与回放(进阶)

场景:记录用户一段时间内的键鼠操作,然后自动回放。综合运用 gohook 的低层事件流与 robotgo 的控制能力。

核心思路

  1. 录制:用 hook.Start() 消费事件通道,记录每个事件的类型、坐标/按键以及相对时间戳。
  2. 回放:遍历记录,按相对时间间隔 MilliSleep,用 robotgo 重放对应的鼠标移动/点击或按键。
package main

import (
    "fmt"
    "time"

    "github.com/go-vgo/robotgo"
    hook "github.com/robotn/gohook"
)

type record struct {
    delay time.Duration
    kind  uint8
    x, y  int16
}

func recordEvents(seconds int) []record {
    var records []record
    last := time.Now()

    evChan := hook.Start()
    go func() {
        time.Sleep(time.Duration(seconds) * time.Second)
        hook.End()
    }()

    for ev := range evChan {
        now := time.Now()
        if ev.Kind == hook.MouseMove || ev.Kind == hook.MouseDown {
            records = append(records, record{
                delay: now.Sub(last),
                kind:  ev.Kind,
                x:     ev.X,
                y:     ev.Y,
            })
            last = now
        }
    }
    return records
}

func replay(records []record) {
    for _, r := range records {
        time.Sleep(r.delay)
        robotgo.Move(int(r.x), int(r.y))
        if r.kind == hook.MouseDown {
            robotgo.Click()
        }
    }
}

func main() {
    fmt.Println("开始录制鼠标操作,持续 5 秒...")
    recs := recordEvents(5)
    fmt.Printf("录制完成,共 %d 个事件。3 秒后回放...\n", len(recs))
    robotgo.Sleep(3)
    replay(recs)
    fmt.Println("回放结束")
}

要点:录制时同时保存相对时间间隔,回放才自然;注意字段名以你所用 gohook 版本为准;回放鼠标移动时用 Move,需要更自然可换 MoveSmooth。这是一个简化示例,完整的录制回放还应处理键盘事件、鼠标松开、滚轮等。

14.6 工程化建议

把上面这些项目落地为可维护的工具时,建议:

  1. 封装动作库:把“点击图像”“粘贴文本”“激活应用”等常用动作封装成可复用函数,业务脚本只调用这些高层函数。
  2. 配置化:把坐标、模板图路径、热键、文本内容等放到配置文件,避免硬编码、便于修改。
  3. 统一节奏:在程序入口集中设置 MouseSleep / KeySleep,并提供“调试模式”(更大延时、打印日志)。
  4. 健壮性:所有“查找”操作都要处理“找不到”的情况;所有等待都要有超时;保证热键工具能优雅退出。
  5. 跨平台:用 runtime.GOOS 抽象修饰键等差异,必要时用构建约束分离平台代码。

14.7 小结

本章通过五个完整实战项目——自动化表单填写、图像驱动点击器、全局热键启动器、定向操作指定应用、操作录制与回放——把全书的鼠标、键盘、剪贴板、屏幕、图像查找、进程窗口、事件监听等能力综合运用起来,并给出了工程化的组织建议。下一章作为收尾,我们将系统总结最佳实践、性能优化与常见问题排查。