当年在百度搜索团队的时候做的一个小工具,可以把一些日常工作自动化,确实解决了一些问题。正值五一,分享点有趣的东西。希望能给大家一些启发。
故事的开始
就在不久之前,我入职了百度的搜索团队,参与 pc 搜索的一些业务。搜索业务这么多年,历史积累的技术债务蛮多的,其中影响效率的主要是开发过程的问题。比如,首页经常要切换登录态和非登录态来看效果,每次切换都要手动输入用户名密码,而且因为有的 http 的资源会涉及跨域而失败,需要单独请求下。比如,每次上线之前都要过几遍 checklist,繁琐也花时间,所以几乎没人会认真的一遍遍过 checklist,等等,一些问题。而且因为我们开发时也是直接代码推到服务器来看效果,所以经常登录跳板机和切换不同机器,需要记住一些机器名和密码,也很耗费时间。我在熟悉流程和架构之余就一直在想着怎么去解决这些痛点。有一次走查,UE 和 PM 说每次走查的登录都好麻烦哦。听到这,发现这是个共性问题,就觉得可以正式着手做了。
最初的目标
最开始的目标就是一键登录和退出登录,一键跑 checklist,还有一键登录跳板机和一键切环境,涉及到浏览器的自动化,自然就想到了 puppeteer,一个用于前端自动化测试的库。而登录跳板机和切换登录的机器不在浏览器中,需要涉及到系统的自动化(鼠标和键盘事件等),最后选择了 robotjs。这俩库都是在node环境下才能跑的,而UE和PM的电脑不会装 node,加上功能多了以后有个图形界面会更好,就想到了 electron(提供node环境和图形界面)。
先简单介绍下这三门技术:
1. Puppeteer
Puppeteer 是一个 Node 库,它提供了一些高级API来通过 DevTools 协议控制 Chromium 或 Chrome。
它能做的很多,比如:
生成页面的截图和PDF;
抓取 SPA 并生成预渲染的内容(即“SSR”);
从网站抓取内容;
自动表单提交,UI 测试,键盘输入等;
创建一个最新的自动化测试环境。 使用最新的 JavaScript 和浏览器功能,直接在最新版本的 Chrome 中运行测试;
捕获你网站的 Timeline Trace,来帮助诊断性能问题;
Most things that you can do manually in the browser can be done using Puppeteer!
它提供了这些api
Puppeteer:通过DevTools协议与浏览器通信,创建Browser实例。
Browser:浏览器实例,可以拥有多个BrowserContext。
BrowserContext:定义了一个浏览会话,可以拥有多个Page。
Page:至少有一个Frame:主框架。 可能存在由iframe或框架标签创建的其他帧。
Frame: 至少有一个执行上下文 - 默认执行上下文 - 执行框架的JavaScript。 Frame可能有与扩展相关联的其他执行上下文。
Worker: 具有单个执行上下文,便于与WebWorkers交互。
2. Robotjs
Robotjs 是 nodejs 的第一个用于桌面自动化的库。他能自动化鼠标、键盘和读取屏幕,并且提供了 Mac, Windows, Linux 的跨平台支持。
3. Electron
Electron 可以让你使用纯 JavaScript 调用丰富的原生(操作系统) APIs 来创造桌面应用。 你可以把它看作一个 Node. js 的变体,它专注于桌面应用而不是 Web 服务器端。
Electron进程分为主进程和渲染进程,Electron 运行 package.json 的 main 脚本的进程被称为主进程。 在主进程中运行的脚本通过创建web页面来展示用户界面。 一个 Electron 应用总是有且只有一个主进程, 每个 Electron 中的 web 页面运行在它的叫渲染进程的进程中。所以做 electron 应用会经常用到 ipc 来做进程通信,很多操作只能在主进程做。
之后界面的展示用任何组件方案都可以,本来想用 san(百度的前端框架),但是 san 没有 electron 的脚手架,考虑到效率,暂时选用了 electron-vue 来创建项目。
最初的用户
最初的版本的走查工具,界面是这样的:
输入 url,点击登录,就是通过 puppeteer 来启动一个浏览器,并且自动跳转到登录页面,输入用户名密码,之后点击登录,跳转到输入的 url。这里只是 pc 的,移动端的话启动的时候设置下 ua 就好了。
启动浏览器的时候通过 headless 设置为 false,puppeteer 支持启动没有界面的浏览器,主要是用于自动化测试,但我们这里需要界面。
然后通过 executablePath 指定一个本地的 chrome 的启动路径,可以在设置里面修改(一般 chrome 的路径是固定的),这样使用本地的 chrome 来跑,不用连 chrome 一起打包进去。
defaultViewport 设置为 width:0 和 height:0 是为了让内容自动适应窗口大小。
--allow-running-insecure-content 和 --disable-web-security 可以禁止同源策略,这样 https 网站加载 http 的跨域资源也不会报错。
--auto-open-devtools-for-tabs 可以打开新 tab 自动打开 dev tools(这个后续可以加到设置中去让用户自己设置)。
之后又顺手做了一个屏幕取色的功能,考虑到 ue 走查时可能会用到,实现是通过 ox-mouse 来监听系统鼠标事件,然后通过 robotjs 来获取鼠标所在位置的颜色,之后发送到 colorpicker 窗口做显示。
最初的两个用户(PM 和 UE)都给了一致的肯定,这让我很开心。
扩展更多边界
因为有了最初的一个场景的成功实践,后面也就更有热情去做了。最初的目标更多还是针对开发者,所以开发者版本独立做了一个工具。这方面可以应用的场景就多了。
最开始做的事自动登录跳板机和自动切环境的功能,真实的流程是打开终端,输入ssh链接跳板机的命令,然后输入密码并且手机认证,手机认证这部分暂时没有做自动化,也最好不要去做自动化,把之前的那些都做了自动化。最终效果是一点登录跳板机,就可以在如流手势认证登陆了。实现还是通过robotjs,先输入command + space打开spotlight,然后输入terminal.app,之后输入命令和密码。过程比较傻瓜式。
自动跑 checklist 是自动化测试的范畴,puppeteer 很拿手,只要把操作步骤写成脚本,然后在一些状态下做效果的验证就可以了。
做完这些功能后,又会想到自动创建 icafe(百度内部的项目管理平台)卡片(把 mrd(需求描述文档) 的内容拿过来自动粘贴,自动输入一些信息之后创建卡片,并且把关联 cr 的代码复制下来),自动创建提测单,自动创建上线单,自动发排期邮件,自动发周报等等。
很多平时手动的做的事情都可以自动来完成,包括浏览器里的和系统级别的。
慢慢想到这一个个的功能都是围绕代码库的,那是不是应该做一个代码库的管理,然后围绕代码库的开发周期来做工具链的集成。
开发工具基本成型
这个阶段我对开发工具的定义是做代码库的管理,(比如首页分了好多模块,可以通过分类把一些模块归到一起管理),并且围绕代码库的开发流程提供一系列提效工具。可以通过插件来扩展工具链。
大概设计的界面是这样的
每个代码库都可以在创建时输入本地路径和 icode(百度内部的代码托管平台) 路径还有相关的开发和 pm 等信息,这样可以一键用 ide 打开本地代码库,在详情里可以看到相关的人员的信息,并且点击名字可以一键打开如流中对应人员的对话框(基于 robotjs)。
然后会扫描代码库下的 package.json 中的 npm scripts,可以在界面上执行,也可以选择在系统的 terminal 或者 ide 的 terminal 中执行。
选择开发流程会看到每个阶段的tab,每个tab下有这个阶段可能用到的工具,比如开发时的一键登录跳板机和切环境,排期阶段的自动发排期邮件,自动创建icafe卡片,自测阶段的自动登录退出,上线阶段的自动创建提测单等功能,实现方式一样,就是模拟用户的操作,通过浏览器自动化和系统的自动化来代替人来完成一些工作。
因为开发流程的入口藏得比较深却很常用,又单独提到了左侧。此外一些其他的工具也很常用,可以放到工具箱里面,比如可视化删除本地 node_modules,屏幕取色,屏幕尺子等等。
工具箱中工具有两种触发方式,一键触发和定时任务触发,比如每两周都自动列一下可用的会议室,然后准备好邮件,只需要确认下信息,然后点发送就可以自动订会议室,有的工具不需要定时功能。定时功能的实现是通过 node-schedule,它的api风格是这样的:
通过 * * * * * * 来指定时间间隔
整个工具的思路是围绕代码库的开发流程的一些自动化工具,基于 puppeteer 和 robotjs,不同的场景下需要的工具不同,所以插件功能是很有必要的,如果插件足够丰富以后,我们可以在开发时选择适合自己场景的插件来安装,会自动添加一些阶段的工具。当然,这个还没有实现。
我在index.jsRobotjs错误:无效的键码指定
var settingsFile = "config.json";
var settings = JSON.parse(require("fs").readFileSync(settingsFile));
const net = require('net');
const robot = require("robotjs");
const fs = require("fs");
var client;
var customKeys = {
"scroll_up":'robot.scrollMouse(50, "up");',
"scroll_down":"robot.scrollMouse(50,'down');"
}
function startCommunication(address,port) {
client = net.connect({port: port,host:address},() => {
// 'connect' listener
console.log('connected to server!');
//client.write('world!\r\n');
});
client.on('data', (data) => {
console.log(data.toString());
var string = data.toString();
console.log(settings.keys[string.substr(1)]);
if(string.substr(0,1) == "d") {
robot.keyToggle(settings.keys[string.substr(1)],"down");
} else {
robot.keyToggle(settings.keys[string.substr(1)],"up");
}
//client.end();
});
client.on('end',() => {
console.log('disconnected from server');
});
}
startCommunication(settings.address,settings.port);
下面的代码我也有在config.json这段代码,又名什么被解析为变量的设置。
{
"port":5555,
"address":"192.168.1.118",
"keys":{
"KEY_A":"a",
"KEY_B":"b",
"KEY_X":"x",
"KEY_Y":"y",
"KEY_L":"y",
"KEY_R":"t",
"KEY_DUP":"up",
"KEY_DDOWN":"down",
"KEY_DLEFT":"left",
"KEY_DRIGHT":"right",
"KEY_START":"z",
"KEY_SELECT":"q"
}
}
什么问题是是,当我静下心来,要么robotjs.togglekeys声明我得到的错误
Error: Invalid key code specified.
这意味着,因为有错误中明确指出,这是得到一个无效的键码。我猜这是我犯的一个愚蠢的错误。我测试中的数据等于“dKEY_DRIGHT”。变量字符串等于那个,但我需要摆脱d为了它的工作。当我执行实时控制台时,我能够通过使用相同的代码获取我需要的数据,但是当它在文件中运行时somethig出错。任何东西都有帮助:)
来源
2016-07-30 master
A
回答
0
您可以尝试使用node-key-sender将按键发送到您的操作系统。
用npm install --save-dev node-key-sender安装。
和发送键使用键盘:
var ks = require('node-key-sender');
ks.sendKey('up');
所有你配置的值( 'A', 'B',...)由LIB接受。你可以直接发送它们。
查阅文档页面以获取更多信息:https://www.npmjs.com/package/node-key-sender。
来源
2017-03-13 12:52:44 computeiro
robotjstypestring解锁屏幕无效是因为RobotJSTypeString是一款用于在RobotJS环境中操作虚拟键盘的命令,通常用于模拟用户的按键输入。但是,对于解锁屏幕这种任务,RobotJSTypeString可能无法实现,因为解锁屏幕一般需要使用特定的鼠标点击来完成,而RobotJSTypeString却只能模拟用户的按键输入。
这个问题使人烦恼的是,它对我的同事在他们的计算机上有效,但是对我却不起作用,我们对调试方法一无所知。
预期行为
期望的是,当用户点击已成功注册的快捷方式时,该字符串将出现在用户打开的任何活动窗口中的屏幕上
app.on('ready', () => {
setTrayItem();
const ret = globalShortcut.register('Alt+Z', () => {
robot.typeString("Hello World");
});
if (!ret) {
console.log('registration failed');
}
});
当前行为
什么都没发生!
您的环境
RobotJS version: "robotjs": "^0.5.1"
Electron: "electron": "^4.0.0",
Chromium 69.0.3497.106,
Node 10.11.0,
V8 6.9.427.24
npm version: 6.4.1
Operating System: macOS 10.14.2
0 个答案:
没有答案
相关问题
使用robotjs获取鼠标位置无法在Electron app
Solr上的排序未按预期工作
npm' json-update'没有按预期工作
Robotjs量角器测试不适用于Jenkins
Robotjs无法使用Electron和Windows 10
combineLatest()无法按预期工作
角度,电子,打字稿和漫游器
打包电子后XMLHttpRequest无法正常工作
Robotjs已针对不同的Node.js版本进行编译
电子typeString()上的Robotjs无法按预期工作
运行一下就行了
Robotjs是nodejs的第一个用于桌面自动化的库。他能自动化鼠标、键盘和读取屏幕,并且提供了Mac, Windows, and Linux的跨平台支持
Robotjs 是github上比较常用的库, 用于nodejs/Electron 应用开发. Windows 上安装robotjs 容易遇到问题. 与Robotjs自己的文档 Documentation - RobotJS --- It is that easy 形成鲜明对比;