Chrome插件与油猴脚本
- 简介
- 油猴脚本编写要点
- 调试技巧
简介
开发过Chrome插件的开发者,都会被Chrome插件的content,background(service),popup,inject 等各种不同作用域的脚本搞得晕头转向,而且不同的脚本有不同的权限,比如我们要拦截页面的音频,发送到跨域服务器,并把结果填充到网页元素绑定的vue或者react实例中,则需要在content,background,inject等不同脚本中来回通讯。
所有有没有什么方法让我们在一个js文件中完成我们想做的功能呢?
有的!油猴插件。
安装了油猴插件,我们只需要调用油猴插件封装好的api,油猴插件本身帮我们解决chrome不同作用域脚本间的通讯。
完全造福让广大js开发者,不需要了解chrome插件那一套繁杂的规则就可以编写可用的脚本。
而按照油猴规范编写的js脚本就是油猴脚本。
PS:本文所述油猴插件包含几个分支:GreasyMonkey,TamperMonkey,Violentmonkey等,文章重点在于介绍油猴脚本,所有插件都能运行油猴脚本,不对插件做详细区别。
油猴脚本编写要点
油猴脚本的资源网上非常丰富,见 https://greasyfork.org/zh-CN 。
开发规范很简单,见 https://www.tampermonkey.net/documentation.php
这里主要写几个油猴脚本开发和普通js不同的几个地方:
// ==UserScript==
// @name 插件名称
// @namespace 插件命名空间
// @description 插件描述
// @author 插件作者
// @version 1.0.0
// @match https://match.address/*
// @run-at document-end
// @grant unsafeWindow
// @grant GM_xmlhttpRequest
// @grant GM_notification
// @grant GM_info
// @grant GM_getValue
// @grant GM_setValue
// @require https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js
// @require https://cdn.jsdelivr.net/npm/linq-es2015@2.5.1/dist/linq.min.js
// ==/UserScript==
- 脚本需要有头部声明,如上述内容
- 脚本中使用的油猴api需要前置声明,见上述代码 @grant
- 脚本中使用的第三方库需要前置声明,见上述代码@require
- 脚本中使用window需要声明 unsafeWindow,并且代码中需要替换window为unsafeWindow.
- 脚本中发送跨域请求需要使用GM_xmlhttpRequest
- 脚本持久化数据读写需要使用GM_setValue/GM_getValue
- 脚本中想要获取头部声明信息可以使用GM_info,比如获取脚本@version
- 如果想要脚本有交互设置项,可以在网页中添加一个紧靠边缘自动收缩的弹窗,鼠标移入弹出设置窗体,配合持久化数据读写保存/修改配置。
- 有时候为了拦截网页刚开始加载时的请求,需要设置@run-at 为document-start
- 油猴提供了一些与浏览器交互的api。比如新开标签页,弹出通知。
所以通过油猴脚本来拦截网页请求就简单高效很多。
不过需要注意在油猴脚本中 发送跨域请求需要使用GM_xmlhttpRequest,
并在前面声明
@grant GM_xmlhttpRequest
// ==UserScript==
// @name Userscript Name
// @namespace your name space
// @version 0.1
// @description desc
// @author You
// @run-at document-end
// @match https://*/*
// @grant unsafeWindow
// @grant GM_log
// ==/UserScript==(function() {'use strict';/*** 重载fetch,用于拦截网页发送的fetch请求*/let originFetch = fetch;window.unsafeWindow.fetch = async function (...args) {const response = await originFetch(...args);await response.clone().blob() // 如果是文本数据,可以使用json()等.then(data => {GM_log(data); // 获取拦截的数据}).catch(e=> GM_log(e));return response;}/*** 重载xhr的send,用于拦截网页发送的xhr请求*/let xhr = XMLHttpRequest.prototype;let originSend = xhr.send;xhr.send = async function (postData) {GM_log(postData);return originSend.apply(this, arguments);}
})();
拦截并修改数据可以参考这里转发的一篇文章:
油猴脚本重写fetch和xhr请求
调试技巧
有时候我们想要使用外部编辑器编辑js脚本,此时可以在油猴插件中添加下面的脚本内容,引用外部实际的脚本文件路径
注意match、run-at、grant等属性从引用的实际脚本内容中复制。
另外需要在浏览器中开启油猴插件的允许访问文件网址。
// ==UserScript==
// @name 测试
// @description 通过这种方式,可以使用外部编辑器修改js文件。
// @version 1.0.0
// @match https://*.yourwebsite.com/*
// @require file://E:\path\to\your\test.user.js
// ==/UserScript==