前言
这边主要介绍一款个人自行开发的chrome插件 web-robot,
这边讲解的是他的V1.0版本,
包括它的开始设计,使用教程,实现思路和细节。
源码的github地址是在https://github.com/webgjc/web_robot
软件设计
关于这个软件的初始设计定位,这边将他定位为网页自动化链路管理执行;
类似模拟自动化测试,但不会有结果校验。
创建事务和流程的用户主要针对的用户是稍微了解一点点html的用户,当然小白可以用他人分享的事务流程享受自动运行的快感。
软件主要要包括的有以下一些:
- 网页元素的可视化筛选;
- 筛选的元素加上动作与延时变成一个事件;
- 多个事件形成一个事务流程;
- 主界面可以管理多个事务,进行事务的运行、轮播、分享等;
软件风格大致按使用的前端ui框架的极简风格走;
软件使用教程
下载与导入
源码下载导入
源码github地址:https://github.com/webgjc/web_robot
首先到github上将源码clone到本地 / 下载解压也可以
git clone https://github.com/webgjc/web_robot.git
然后打开chrome点开右上角三个点的地方,
选择更多工具 ==》扩展程序;
因为是源码,开启右上角的开发者模式
然后点击左上角的加载已解压的扩展程序,
选择刚刚clone下来的目录
下面表示已经加载进来了
且右上角出现这个小图标
重要:右键这个小图标,
可读取和更改的网站数据,
选择 在所有网站上;
至此已经完成下载和导入啦!😋
从chrome商店下载导入
暂时没有上线chrome应用商店
版本更新
首先更新本地代码
git pull
然后重复上面的 加载已解压的扩展程序 的操作。
软件使用
新建事务
首先新建一个事务
这边建一个test为例子
筛选器
点击 test 进入 过程添加页
点击添加过程,进入筛选器页面
这边支持按 html标签 / class / id 筛选
下面都进行举例
html标签筛选
选择一个html标签,a(链接), body, div等
下方会展示一个列表,表示页面中该元素有几个。
鼠标移到列表每个上面,
页面对应元素将会渲染一个蒙版到以便正确定位选择。
这是选择body的时候
这是选择div的时候
class / id 筛选
首先在选择标签列表的下列菜单中
选择 第一个 class/id选择器
然后会出现一个输入框输入对应的class或id
class选择器需要以.开头,如:.xxx
id选择器需要以#开头,如:#xxx
选好后按回车,如果有对应的选择器,将会展示一个列表,
后续操作同html标签,鼠标移到列表上会渲染蒙版
单个事件
用筛选器选中好一个元素后
将会进入事件编辑页面
(如想改变元素,可以按最上面的元素返回)
这边的选择操作可以选的有:
- click – 点击
- value – 设值
- refresh – 刷新
- pagejump – 当页url跳转
然后输入 执行前等待时间 / 和上一步执行中间间隔时间
可以测试运行当前事件,也可以把事件添加到事务流程中。
流程事件管理
添加后会返回流程页,
如下加了一条,等待一秒后,(click)点击第一个<a>标签
如下表示,
等待一秒后,(click)点击第一个<a>标签的链接,
再等待一秒后,往第一个input输入框里赋值 你好
可以选择继续添加,
可以选择返回主页,
可以测试运行单个事件,
可以删除单个事件;
事务管理
继续到主页
事务支持新增,删除,运行,轮播,导出,导入
运行事务
运行主要是按定好的流程运行每个事件,
运行会放在浏览器后台中,中间关闭这个页面并不会切断运行。
轮播事务
轮播表示的是循环运行,运行完一次后立即进行下一次。
中间的间隔是第一个事件的等待时间。
由于在浏览器后台轮播可能会导致大量吃资源,因此轮播限制了只能前台运行,也就是关闭了这个管理页后就会断掉轮播。
导入导出事务
点击导出,事务的信息会自动保存到剪切板,复制给他人即可;
点击导入,将他人复制的事务信息导入即可;
常见问题说明
筛选器失效
有时候页面与浏览器插件的连接会失效或过期,
这个时候可以刷新页面,然后重新打开这个插件页面。
软件开发过程
其他准备知识
关于chrome插件的开发,请看官网教程或其他教程
软件开发设计
这个浏览器插件包括以下几部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 配置文件 manifest.json
样式文件夹 /css
html文件,主要放了popup.html,也就是这个插件管理页 /html
存放图片 /images
存放js 主要实现的包括popup.js(管理页的后端) 和background.js(浏览器的后端) /js
|
部分代码说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
| function get_my_robot(callback) { chrome.storage.local.get(["my_robot"], function(res) { if (callback) callback(res.my_robot) }) }
function set_my_robot(new_robot, callback) { chrome.storage.local.set({ "my_robot": new_robot }, function() { if (callback) callback() }) }
function connect(callback) { chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) { var port = chrome.tabs.connect(tabs[0].id, { name: "robot" }); callback(port) }) }
function exectab(callback) { chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) { callback(tabs[0].id) }) }
function jscode(process) { let exec_code = "(function(){ \n"; if(process["tag"].startsWith(".")) { exec_code += 'var robot_node = document.getElementsByClassName("' + process["tag"].substring(1) + '")[' + process["n"] + '];' }else if(process["tag"].startsWith("#")) { exec_code += 'var robot_node = document.getElementById("' + process["tag"].substring(1) + '");' }else{ exec_code += 'var robot_node = document.getElementsByTagName("' + process["tag"] + '")[' + process["n"] + '];' } if (process["opera"] == "click") { exec_code += "robot_node.click();" } else if (process["opera"] == "value") {
exec_code += "let lastValue = robot_node.value;" exec_code += "robot_node.value=\"" + process["value"] + "\";"; exec_code += "let event = new Event('input', { bubbles: true });"; exec_code += "event.simulated = true;"; exec_code += "let tracker = robot_node._valueTracker;"; exec_code += "if (tracker) { tracker.setValue(lastValue); }\n"; exec_code += "robot_node.dispatchEvent(event);"; } else if (process["opera"] == "refresh") { exec_code += "window.location.reload();"; } else if (process["opera"] == "pagejump") { exec_code += "window.location.href=\"" + process["value"] + "\";"; } exec_code += "\n})();"; console.log(exec_code) return exec_code; }
function refresh_cases() { get_my_robot(my_robot => { if (my_robot == undefined) { set_my_robot({}) } else { var cases = ""; for (let i in my_robot) { let one_case = {} one_case["case_name"] = i; one_case["content"] = my_robot[i]; let tr = '<tr id=' + i + '> \ <td> \ <a href="#" class="case_name">' + i + '</a> \ </td> \ <td> \ <a href="#" class="run_case">运行</a> \ <a href="#" class="del_case">删除</a> \ <a href="#" class="lun_case">轮播</a> \ <a href="#" class="export_case" data-clipboard-text=' + JSON.stringify(one_case) + '>导出</a> \ </td> \ </tr>'; cases = cases + tr; } $("#cases").html(cases); } }) new ClipboardJS('.export_case'); }
function refresh_process(case_name) { get_my_robot(my_robot => { var data = my_robot[case_name]; var process_li = ""; for (let i = 0; i < data.length; i++) { let lili = '<li class="collection-item" id="process-' + i + '"> \ <div class="row "> \ <div class="col s6 ">标签:' + data[i]["tag"] + '</div> \ <div class="col s6 ">#:' + data[i]["n"] + '</div> \ </div> \ <div class="row "> \ <div class="col s6 ">操作:' + data[i]["opera"] + '</div> \ <div class="col s6 ">等待:' + data[i]["wait"] + '秒</div> \ </div> \ <div class="row "> \ <div class="col s12 ">赋值:' + data[i]["value"] + '</div> \ </div> \ <div class="row "> \ <a href="# "> \ <div class="col s6" id="process_test_run" >test</div> \ </a> \ <a href="# "> \ <div class="col s6 " id="process_del">删除</div> \ </a> \ </div> \ </li> '; process_li = process_li + lili; } $("#process_list").html(process_li); }) }
$(document).ready(function() {
var tag_types = ["class/id选择器", "a", "body", "button", "div", "i", "img", "input", "li", "p", "span", "td", "textarea", "tr", "ul", "h1", "h2", "h3", "h4", "h5"]; var operas = ["click", "value", "refresh", "pagejump"]; var case_name = ""; var init_select = 1;
refresh_cases();
$('.modal').modal();
exectab(tab_id => {
$("#cases").on("click", ".run_case", function() { var case_name = $(this).parent().parent().attr("id"); var save_run = $(this).parent().html(); var that = $(this).parent(); that.html("运行中"); get_my_robot(my_robot => { var bg = chrome.extension.getBackgroundPage(); bg.execute(my_robot[case_name], tab_id); var process_wait = 0; for (let i = 0; i < my_robot[case_name].length; i++) { process_wait = process_wait + my_robot[case_name][i]["wait"] * 1000; } setTimeout(function() { that.html(save_run); }, process_wait) }) })
$("#cases").on("click", ".lun_case", function() { var case_name = $(this).parent().parent().attr("id"); var save_run = $(this).parent().html(); var that = $(this).parent(); that.html("运行中"); get_my_robot(my_robot => { var process_wait = 0; for (let n = 0; n < 100; n++) { for (let i = 0; i < my_robot[case_name].length; i++) { process_wait = process_wait + my_robot[case_name][i]["wait"] * 1000; setTimeout(function() { chrome.tabs.executeScript(tab_id, { code: jscode(my_robot[case_name][i]) }); }, process_wait); } } setTimeout(function() { that.html(save_run); }, process_wait); }) })
$("#cases").on("click", ".export_case", function() { $(this).html("导出成功"); var that = $(this); setTimeout(function() { that.html("导出"); }, 1000); })
}) })
|
感谢