在本文中,我将完成一系列出版物,在这些出版物中,我想谈谈我为浏览器编写Web扩展的经验。 我已经有创建Web扩展的经验,该Web扩展由大约100,000个Chrome用户安装,它们可以自动工作,但是在本系列文章中,我决定通过将Web扩展与服务器端紧密集成来研究Web扩展的开发过程。




第1部分 ,
第2 部分 ,
第3部分计划任务
Web扩展允许您配置自定义脚本,以在页面加载完成后自动执行其代码。 例如,当您有一个相同类型的页面列表用于从脚本执行中爬网和接收数据时,这很方便。 或者,如果您需要删除Internet上任何页面上的烦人的广告,则可以使用代码来跟踪您在网络资源上的操作,将页面背景更改为深色等。
在这种情况下,通常有必要在每日计划模式下从页面接收数据。 例如,如果站点具有货币汇率,并且URL直接请求将保护散列参数。 作为此类副本,您可以考虑
欧洲中央银行的
网站 。 在这种情况下,要获取当前汇率,您必须知道哈希URL才能获取XML格式的正确数据。
使用Web扩展程序,您可以设置通过脚本接收数据以请求汇率所需的频率。 Web扩展程序接受以Crown格式的字符串作为输入,因此,要获取每日模式的汇率,必须指定* * / 1 * * *。
从技术角度来看,服务器部分通过向Chromium浏览器页面添加用户脚本来启动Puppeteer。 在这种情况下,我们会面临Chromium进程随时间而有意关闭的问题,因为进程数的增加将不利地影响服务器端的整体性能。 如果您打算以周期性模式运行用户脚本来解决上述问题,则必须从用户脚本向Puppeteer发送请求以完成Chromium进程。
在对任务计划程序实现过程进行了长时间的测试之后,决定跟踪脚本控制台的输出。 因此,要停止Chromium进程,用户脚本必须在代码的必需部分中具有命令以停止该进程:
console.log('script is ended');
使用此命令,用户脚本可以关闭由Puppeteer生成的Chromium服务器进程。 这是通过跟踪Puppeteer“控制台”事件来实现的:
如果用户脚本没有这样的命令,则要在任务计划程序模式下完成执行过程,必须强制计时器终止。 这是使用setTimeout以简单的方式实现的:
const timeLimitCron = 30; const timeout = setTimeout(async () => { if(browser) { await browser.close(); } clearTimeout(timeout); }, timeLimitCron * 1000 );
由于任务计划程序在服务器端运行,并且用户经常需要使用特定的IP地址,因此添加了使用代理服务器的选项。

用户还可以从Puppeteer控制台下载最新的消息日志。 例如,检查代理服务器的正确操作很方便。
键盘快捷键
在测试和现场测试期间,事实证明,对于某些类型的脚本,拥有热键以在Web资源上执行它们非常有用。 此类脚本的一个示例是Redability.js。 该脚本创建一个“干净的视图”以读取站点的内容。 也就是说,js库使用内容分析页面的结构,并允许您以很高的概率获取页面的标题,作者和内容。 之后,用户脚本可以覆盖Web资源的html,并允许用户以“纯格式”阅读,而无需不必要的标记,广告等。
最初,只有通过单击“执行”按钮才能从弹出的Web扩展中运行用户脚本。 与接口交互的逻辑通常是出于安全考虑。 但是在上面的示例中,它不允许您轻松地将Web资源的内容转换为“纯格式”。
如上所述,Web扩展允许您通过content.js使用DOM,但是由于window对象不是打开选项卡的窗口对象,因此不能用于例如存储参数。 此条件限制了Web扩展程序作为跟踪按键的对象的操作。
在要解决的问题中,有必要将“热键”从Web扩展界面传输到服务器端进行存储。 接下来,每次加载Web资源页面时,单击正确的组合后,将获得“热键”列表并加载用户脚本。
Hotkeys.js用作使用热键的库。
从服务器端收到热键列表后,将执行以下代码:
var hotKeysMap = {keys: [], id: []}; for(var i in data.response.data) { hotKeysMap.keys.push(data.response.data[i]['hotkeys']); hotKeysMap.id.push(data.response.data[i]["_id"]); } if(hotKeysMap.keys) { getScript("hotkeys.js", function() { var script = document.createElement("script"); script.setAttribute("class", "gCore-hotKeys"); script.setAttribute("data-endpoint", event.data.endPoint); script.setAttribute("data-token", event.data.token); script.setAttribute("data-userid", event.data.userId); script.innerHTML = "GChotKeys = JSON.parse(\"" + JSON.stringify(hotKeysMap).replace(/"/g, "\\\"") + "\");\n" + "hotkeys(GChotKeys.keys.join(','), function(event, handler) {" + " event.preventDefault();" + " localStorage.setItem('runHotKeysScript', GChotKeys.id[GChotKeys.keys.indexOf(handler.key)]);" + "});"; document.body.appendChild(script); }); }
getScript函数为script标记生成html代码,并将其写入Web资源页面。 因此,我们在每个页面上都具有跟踪按键的功能。 我们还需要传递一个与脚本ID匹配的热键数组来执行。 这是通过为script标签添加html代码来实现的,脚本标签的内容会初始化一个全局变量以JSON格式存储匹配数组。
上面已经提到,Web资源的打开页面与Web扩展的内容扩展extension.js脚本之间存在通信问题,该脚本用于操作DOM。 在这种情况下,您可以采用一种简单的技术来检查localStorage中的值,这是上述两个交互点的通用对象。
在content.js中,您只需每秒检查一次localStorage值,并执行与单击弹出式Web扩展中的“执行”按钮时相同的DOM操作。
setInterval(function() { if(localStorage.getItem('runHotKeysScript')) {
因此,实现了“热键”技术,使您可以使用内部库的功能快速启动用户脚本来解决实际问题。
结论
在该项目的实施过程中,解决了基于meteor.js和跨浏览器Web扩展在服务器部分之间编写集成的实际任务。 关键的绊脚石是SCP和客户端部分三个组件之间的交互过程-在浏览器中打开的页面,content.js和background.js脚本。
我希望我的经验将使编写更专业的跨浏览器Web扩展变得更容易。
将来,计划对Web扩展进行本地化并编写对社区有用的脚本。 如果读者有想法或希望帮助编写此类用户脚本,请用私人消息编写。