起因
有一天老爸找我,他们公司每年都要在线看视频学习,要花费很多时间,问我有没有办法可以自动学习。
在这之前,我还给我老婆写了个浏览器插件,解决了她的在线学习问题,她学习的是一个叫好医生的学习网站,我通过研究网站的接口和代码,帮她开发出了一键学习全部课程和自动考试的插件,原本需要十来天的学习时间,分分钟就解决了。
有兴趣的可以看一下,好医生自动学习+考试插件源码。
正因为这次的经历,我直接接下了这个需求,毕竟可以在家人面前利用自己的能力去帮他们解决问题,是一件非常骄傲的事。
事情并没有那么简单
我回家一看,他们的学习平台是个桌面端的软件(毕竟是银行的平台,做的比那个好医生严谨的多),内嵌的浏览器,无法打开控制台,更没办法装插件,甚至视频学习调了什么接口,有什么漏洞都无法发现,我感觉有点无能为力。
但是牛逼吹出去了,也得想办法做。
技术选型
既然没办法找系统漏洞去快速学习,那只能按部就班的去听课了,我第一想到的方式是用按键精灵写个脚本,去自动点击就可以了。但是我爸又想给他的同事用,再教他们用按键精灵还是有点上手成本的,所以我打算自己开发一个小工具去实现。
由于我是个前端开发者,做桌面端首先想到的是 Electron,因为我有一些开发经验,所以并不难,但打包后的体积太大,本来一个小工具,做这么大,这不是显得我技术太烂嘛。
所以我选择了 tauri 去开发。
需求分析
首先我想到的方式就是:
- 用鼠标框选一个区域,然后记录这个区域的颜色信息,记录区域坐标。
- 不断循环识别这个区域,匹配颜色。
- 如果匹配到颜色,则点击这个区域。
例如,本节课程学习后,会弹出提示框,进入下一节学习,那么可以识别这个按钮,如果屏幕出现这个按钮,则点击,从而实现自动学习的目的。
我还给它起了个很形象的名字,叫做打地鼠。

由于要点击的不一定只有一个下一节,可能还有其他章节的可能要学习,所以还实现了多任务执行,这样可以识别多个位置。
有兴趣可以看一下源码。
零基础入门 rust
Tauri 已经提供了很多可以在前端调用的接口去实现很多桌面端的功能,但也不能完全能满足我本次开发的需求,所以还是要学习一点 rust 的语法。
这里简单说一下我学到的一些简单语法,方便大家快速入门。由于功能简单,我们并不需要了解 rust 那些高深的内容,了解基础语法即可,不然想学会 rust 我觉得真心很难。我们完全可以先入门,再深入。
适合人群
有一定其他编程语言(C/Java/Go/Python/JavaScript/Typescript/Dart等)基础。你至少得会写点代码是吧。
环境安装
推荐使用 rustup 安装 rust,rustup 是官方提供的的安装工具。
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
安装后,检查版本,这类似安装 node 后查看版本去验证是否成功安装。
rustc --version
>>> rustc 1.73.0 (cc66ad468 2023-10-03)
cargo 是 rust 官方的包管理工具,类似 npm,这里也校验一下是否成功安装。
cargo --version
如果提示不存在指令,重新打开终端再尝试。
编辑器
官方推荐 Clion,是开发 rust 首选开发工具。
不过作为前端,我们依然希望可以使用 vscode 去开发,当然,这也是没有问题的。
vscode 需要搭配 rust-analyzer 一起使用。
除了上面提到的两个命令,还有 rustup 命令也可以直接使用了:
rustup component add rust-analyzer
执行后就都配置好了,可以进行语法的学习了。
变量与常量的声明
定义变量和常量的声明 javascript 和 rust 是一样的,都是通过 let 和 const,但是在定义变量时还是有一些区别的:
- 默认情况下,变量是不可变的。(这点对于前端同学来说是不是很奇怪?)
- 如果你想定义一个可变的变量,需要在变量名前面加上
mut。
let x = 1;
x = 2; ❌
let mut x = 1;
x = 2; ✅
如果你不想用 mut,你也可以使用相同的名称声明新的变量:
let x = 1;
let x = x + 1;
Rust 里常量的命名规范是使用全大写字母,每个单词之间使用下划线分开,虽然 JS 没有强制的规范,但是我们也是这么做的。
数据类型
对于只了解 javascript 的同学,这个是非常重要的一环,因为 rust 需要在定义变量时做出类型的定义。即使是有过 typescript 开发经验的同学,这里也有着非常大的区别。这里只说一些与 js 区别较大的地方。
数字
首先 ts 对于数字的类型都是统一的 number,但是 rust 区别就比较大了,分为有符号整型,无符号整型,浮点型。
有 i8、i16、i32、i64、i128、u8、u16、u32、u64、isize、usize、f32、f64。
虽然上面看起来有这么多种类型去定义一个数字类型,实际上它们只是去定义了这个值所占用的空间,新手其实不用太过于纠结这里。如果你不知道应该选择哪种类型,直接使用默认的i32即可,速度也很快。有符号就是分正负(+,-),无符号只有正数。浮点型在现代计算机里上 f64 和 f32 运行速度差不多,f64 更加精确,所以不用太纠结。
数组
数组定义也有很大区别,你需要一开始就定义好数组的长度:
let a: [i32; 5] = [0; 5];
这表示定义一个包含 5 个元素的数组,所有元素都初始化为 0。一旦定义,数组的大小就不能改变了。
这是不是让前端同学很难理解,那么如何定义一个可变的数组呢?这好像更符合前端的思维。
在 Rust 中,Vec 是一个动态数组,也就是说,它可以在运行时增加或减少元素。
let v: Vec<i32> = Vec::new();
v.push(

本文讲述了作者如何满足父亲公司在线学习软件的自动化需求,从使用Electron到转向Rust和Tauri,介绍了Rust的基础语法和在项目中的应用,展示了如何通过TauriAPI进行鼠标操作和屏幕颜色抓取,以及如何构建跨平台的Windows安装包。
最低0.47元/天 解锁文章
2668

被折叠的 条评论
为什么被折叠?



