Tampermonkey油猴脚本编写快速入门
目录
油猴脚本概述
- Tampermonkey 是一款免费的浏览器扩展和最为流行的用户脚本管理器,相当于一个管理插件的插件,它适用于 Chrome, Microsoft Edge, Safari, Opera Next, 和 Firefox。
- 虽然有些受支持的浏览器拥有原生的用户脚本支持,但 Tampermonkey 将在您的用户脚本管理方面提供更多的便利,它提供了诸如便捷脚本安装、自动更新检查、标签中的脚本运行状况速览、内置的编辑器等众多功能, 同时Tampermonkey还有可能正常运行原本并不兼容的脚本。
- 官网及下载安装地址:Home | Tampermonkey,安装非常简单,与安装普通的插件无异。
- Tampermonkey 内置有编辑器,可以非常方便地管理、编辑用户脚本;支持自动更新检查功能。
- 官网文档:https://www.tampermonkey.net/documentation.php。
脚本注释/注解
1、如下所示为新建脚本时的默认内容,顶部的注释/注解表明了脚本的各个属性。
2、元数据块必须位于顶部 ==UserScript== 之间。
3、下面是 Greasy Fork 要读取的脚本元键值,参考:https://greasyfork.org/zh-CN/help/meta-keys
这是 Greasy Fork 将读取的 用户脚本属性值 的一个列表。不在此列表的属性也可以写在脚本中,那些不在此列表的属性值也会包含在用户安装的脚本中,但是并不会对 Greasy Fork 上的脚本页面做任何变动。
- §
@name
- 脚本的名称。该项将显示在页面的标题以及链接内容,必填项。
- §
@name:XX-YY
- 脚本在特定语言区域的标题。XX 指 ISO 639-1 国家代码 以及 YY 指可选的 ISO 3166 地区代码。该选项用于提供多语言的
@name
脚本名称。 - §
@description
- 脚本功能的描述,显示在脚本标题下面,必填项。
- §
@description:XX-YY
- 用某门语言写成的脚本描述。XX 指 ISO 639-1 国家代码 以及 YY 指可选的 ISO 3166 地区代码。该选项用于提供多语言的
@description
脚本介绍。 - §
@namespace
@namespace
与@name
这两个属性被作为脚本的唯一标识符,用户脚本管理器根据它们来判断一个脚本是否已安装。Greasy Fork 也需要这些属性,若用户在更新脚本时改变了两者中的任意一项,将发出警告。- §
@version
- 脚本的版本标记将使用 Mozilla 版本格式,并显示于脚本的简介页面。Greasy Fork 要求填写该属性,且当用户更新脚本时没有更新版本号或降低了版本号时将发出警告。
- §
@include
,@exclude
,@match
- 描述脚本会在哪些网站上运行。该列表会被解析和展示到脚本的简介页面,并用于脚本的分类。每个脚本须有至少一个
@match
或@include
。了解格式细则。 - §
@require
- 引入外部脚本到用户脚本。查看关于引入外部脚本到代码的规则。如果你使用 SRI(Sub-Resource Integrity) 来记录外部脚本哈希(更多信息请参阅 TamerMonkey 文档 与 MDN 文档),当 SRI 与文件的实际哈希不一致时将会在 Greasy Fork 进行警告。
- §
@resource
- 引入外部资源(如 JavaScript、CSS、图像等)到脚本。查看关于引入外部脚本到代码的规则。如果你使用 SRI(Sub-Resource Integrity) 来记录外部脚本哈希(更多信息请参阅 TamerMonkey 文档 与 MDN 文档),当 SRI 与文件的实际哈希不一致时将会在 Greasy Fork 进行警告。
- §
@updateURL
,@installURL
,@downloadURL
- 告知用户脚本管理器应该在哪个地址获取脚本更新。Greasy Fork 将自动修改该属性使其永远通过 Greasy Fork 进行更新。
- §
@license
- By posting your script to Greasy Fork, you give others permission to install and use it. The license describes whether and how people are allowed to modify and distribute your script. License is displayed on a script's info page.
@license
can be:- The name of a license (for example,
@license GPL3
). Using a "Full name" or "Identifier" from the SPDX License List is recommended. - The conditions under which you allow use (for example
@license You can modify as long as you credit me
, though using a pre-existing license is recommended. - A copyright statement (for example
@license Copyright MyName
) if you don't want to release under a license. - Omitted entirely, which is the same as having a copyright statement, but less clear to users.
- The name of a license (for example,
- §
@supportURL
- 该脚本的技术支持链接(如:错误反馈系统、论坛、电子邮箱地址等),该链接将显示在脚本的反馈页面。
- §
@contributionURL
- 用于捐赠脚本作者的链接,该链接将显示在脚本的反馈页面。网址可以为 http、https 或比特币协议的网址。如果您需要链接到贝宝捐赠页面,请使用例如 https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=your.email.here@example.com&item_name=Greasy+Fork+donation 这样的格式,替换为您自己的邮箱地址即可。
- §
@contributionAmount
- 建议捐赠金额,请配合
@contributionURL
使用。 - §
@compatible
- 标记此脚本与某个浏览器兼容,兼容性信息将显示在脚本的简介页面上。您也可以添加额外的兼容说明,如
@compatible firefox 火狐上必须关闭广告过滤器
这样的格式。目前能被网站识别的浏览器名称有:firefox
,chrome
,opera
,safari
,edge
。 - §
@incompatible
- 标记此脚本与某个浏览器不兼容,兼容性信息将显示在脚本的简介页面上。您也可以添加额外的兼容说明,如
@incompatible firefox 自火狐 23 开始不兼容
这样的写法。目前能被网站识别的浏览器名称有:firefox
,chrome
,opera
,safari
,edge
。 - §
@antifeature
- 披露会为脚本作者而非用户带来额外收益的功能。你可以通过在脚本的元数据中添加
@antifeature type description
值的方法披露。其中type(类型)是必须填写的内容,而 description(描述)则可以留空。点击此处了解 Greasy Fork 读取的 type(类型)的相关信息。 - §
@antifeature:XX-YY
- 你可以使用多种语言声明
@antifeature
属性,其中 XX 为 ISO 639-1 中定义的两个字符的代码,而 YY 则是一个可选的 ISO 3166 中定义的国家代码。在@antifeature
中制定的每一个类型都可以自定义其本地化的说明。
// ==UserScript== // @name New Userscript // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author You // @match https://mp.csdn.net/mp_blog/creation/editor/new?spm=1001.2101.3001.5352 // @icon https://www.google.com/s2/favicons?sz=64&domain=csdn.net // @grant none // ==/UserScript== (function() { 'use strict'; // Your code here... })();
注释/注解说明
属性名 |
作用 |
@name |
油猴脚本名称,会展示到浏览器中。必填项。 |
@namespace |
脚本命名空间,用于唯一确定脚本。油猴管理面包中点击主页按钮即可跳转到此地址。 |
@homepage | 主页地址。油猴管理面包中点击主页按钮即可跳转到此地址。可以作为脚本更新网址。 |
@version |
脚本版本,用于脚本的更新。必填项。 |
@icon | 用于指定脚本图标,可以设置为图片 URL 地址或 base64 的字符串 |
@description |
脚本描述。必填项。 |
@author |
作者名字 |
@license |
脚本所使用的许可协议名称或地址,该协议需包含用户是否允许二次分发 或修改 脚本的权利。 其它人都可以随意使用时,指定为 MIT 即可。 |
@match |
使用通配符匹配需要运行网址,例如 * 、 http://* 、 http://www.baidu.com/*等。 |
@exclude | 排除匹配到的网站。 |
@include | 保护匹配到的网站。 |
@run-at | 指定脚本的运行时机,如 页面加载完成时执行:@run-at document-end |
@grant |
指定脚本运行所需权限,拥有相应的权限才能调用油猴扩展提供的与浏览器进行交互的API。如果为 none,则不使用沙箱环境,脚本会直接运行在网页的环境中,这时无法使用大部分油猴扩展的 Api,而只能使用油猴默认添加的几个最常用 Api。 |
@require |
指定脚本依赖的其他js库,比如 JQuery。 |
@connect |
用于跨域访问时指定的目标网站域名。 当用户使用 gm_xmlhttprequest 请求远程数据的时候,需要使用connect指定允许访问的域名,支持域名、子域名、ip地址以及 * 通配符 |
@updateURL @installURL |
脚本更新网址,当油猴扩展检查更新的时候,会尝试从这个网址下载脚本,然后比对版本号确认是否更新,不写时,@homepage也可以代替。 |
@supportURL | 用户可获得该脚本技术支持的链接地址 (如:错误反馈系统、论坛、电子 邮件),该链接将显示在脚本的反馈页面。 |
@contributionURL | 用于捐赠脚本作者的链接,该链接将显示在脚本的反馈页面。 |
@contributionAmount | 建议捐赠金额,请配合 @contributionURL 使用。 |
脚本权限 grant
1、@grant 常用的权限,注意其中的前缀 GM 必须大写。
权限名 |
功能 |
@grant unsafewindow |
允许脚本可以完整访问原始页面,包括原始页面的脚本和变量。 |
@grant GM_getValue //GM_getValue(name,defaultvalue) |
从油猴扩展的存储中访问指定key的数据。可以设置默认值,在没成功获取到数据的时候当做初始值。如果保存的是日期等类型的话,取出来的数据会变成文本,需要自己转换一下。 |
@grant GM_setValue |
将数据保存到油猴扩展的存储中:GM_setValue(name,value)。 即使关了浏览器,重新打开仍然能获取到值。 同一个值在匹配的全部网页中都能获取到,所以必须在属性名中加以区分。 |
@grant GM_deleteValue |
将数据从油猴扩展的存储中删除:GM_deleteValue(name) |
@grant GM_listValues | 从油猴扩展的存储中访问全部数据。 |
@grant GM_addValueChangeListener |
添加对 gm_setvalue 的值进行监听,当值发生变化时,调用方法事件。 // 添加一个监听器 |
@grant GM_removeValueChangeListener | 移除对 GM_setvalue 的值进行监听:GM_removeValueChangeListener(listener_id) |
@grant GM_xmlhttprequest |
异步请求数据。 GM_xmlhttpRequest({ |
@grant GM_setclipboard // GM_setclipboard(data, info) |
将数据复制到剪贴板中,第一个参数是要复制的数据,第二个参数是mime类型,用于指定复制的数据类型。 |
@grant GM_log |
用于在控制台中打印日志,便于调试: GM_log("Hello World") 也可以使用原生的 console.log(xxx); 打印日志。 |
@grant GM_addStyle |
向网页中指定元素(可以通过标签名,class样式,ID等选择)添加样式:GM_addStyle(css) 示例三:GM_addStyle("div .logo {background-image: url('http://xxxxxx.jpg') !important}"); a、为含有 .logo 样式的 div 元素设置背景图片(中间的空格表示层级)。 示例四:向页面添加自定义样式属性,然后使用 JQuery 的 hasClass、addClass、removeClass、toggleClass 方法操作目标元素的样式。 示例五:将含有指定属性的div元素设置为不可见。 |
@grant GM_notification |
设置网页通知/提示。 GM_notification(details, ondone) GM_notification(text, title, image, onclick) |
@grant window.close |
|
@grant window.focus |
|
// @grant GM_registerMenuCommand
注册菜单命令,浏览器油猴插件展示脚本名称时,会携带此菜单,方便用户做一些设置,而不用手动修改脚本。 |
function switchLanguage(){ |
@grant GM_openInTab // GM_openInTab(url, options) |
打开一个新的标签页面,类似 windown.open(url)。 url:指定打开的新 URL 地址; options:指定页面展示方式及焦点停留页面。 // active:true,新标签页获取页面焦点 |
添加新脚本
- 安装好油猴插件之后,在浏览器右上角找到并点击油猴插件,选择添加新脚本。
- 然后在打开的编辑器窗口中可以编辑自己的脚本文件,还可以将脚本内容复制到合适的编辑器中编辑,完成之后再复制回来。
- 将自己的脚本编写到 // your code here .. 那里,可以编写函数,然后在最后调用这几个函数,这样的模块化编写方法写出来的脚本比较容易维护。
调试脚本/debugger
- 在脚本需要调试的地方插入 debugger; 语句成为断点,然后F12开发者工具调试。
- 使用最原始的打印日志,可以利用 console.log(xxx) 和 gm_log(xxx) 来将关键信息打印出来。
- 使用 alert(xxx) 函数,弹出对象的框提示。
事例:
// ==UserScript== // @name helloTest // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author You // @match https://*/* // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant none // ==/UserScript== alert("begin"); (function() { 'use strict'; debugger; console.log('HelloWorld') })(); alert("end");
自定义网页倒计时
网页浏览离开黑屏保护
- 网页一定时间内没有浏览时,自动黑屏保护,即使是刷新或者关闭浏览器重开也会持续保持黑屏。必须输入正确的密码后才能继续正常浏览。
- 网页浏览离开黑屏保护。
微博视频下载助手
1、浏览微博视频时,自动在视频上边展示【下载】按钮,点击按钮即可下载对应的视频,方便快捷。
2、greasyfork.org/zh-CN/scripts/458716-微博视频下载助手。
华为云工作项列表突出展示工作项
https://greasyfork.org/zh-CN/scripts/459871-华为云工作项列表突出展示工作项。
Greasy Fork 发布脚本
- 脚本功能没有问题以后,可以分享出来一起使用的,比如可以分享到 gitee、github 等等。
- 油猴官方支持好几个网站,其中使用最频繁的是 GreasyFork (油叉) ,操作也很简单,纯中文,按着提示操作即可。
- 右上角点击'登录'(可以使用github账号登陆)。新账号登陆后,需要过30分钟左右后才能正式发布脚本。
- 登陆之后,点击用户名称进入控制台,选择'发布你编写的脚本',最后添加内容即可,发布时需要指定 @license 许可证。
- @namespace 不写时会默认自动生成,这样油猴管理面版中点击主页按钮即可跳转到此地址。
- @updateurl 不指定时也可以使用@homepage设置脚本更新地址。
出处:https://blog.csdn.net/wangmx1993328/article/details/128649406
=======================================================================================
油猴脚本编写教程
油猴脚本(Tampermonkey)是一个非常流行的浏览器扩展,它可以运行由广大社区编写的扩展脚本,来实现各式各样的功能,常见的去广告、修改样式文件、甚至是下载视频。今天我们就来看看如何编写自己的油猴脚本。当然为了运行油猴脚本,你应该在浏览器中安装油猴插件。
安装油猴插件
安装油猴插件非常简单,直接在浏览器的扩展商店中安装即可。国产浏览器的话一般可以通过下载扩展文件手动拖动的方式来安装。下图是微软新版Edge浏览器的扩展商店,直接搜索Tampermonkey即可。
新建脚本
首先在浏览器右上角找到并点击油猴插件,选择添加新脚本。
然后就会打开如图所示的编辑器窗口,我们就可以在其中编辑自己的脚本文件了。如果你喜欢的话,还可以将脚本内容复制到合适的编辑器中编辑,完成之后再复制回来。
如果你点击开发者菜单的话,可以选择ES6模板,然后就可以在脚本中使用新版JavaScript的特性了,它会有Babel转译回ES5。不过这个模板貌似有点问题,用了它就没办法使用代码纠错功能了。所以这里我还是选择了默认的ES5模板。
脚本编写方法
功能注释
首先来看看脚本的内容,上面是一大排注释,这些注释可以非常有用的,它表明了脚本的各个属性。下面来简单介绍一下。
属性名 | 作用 | |
---|---|---|
name | 油猴脚本的名字 | |
namespace | 命名空间,类似于Java的包名,用来区分相同名称的脚本,一般写成作者名字或者网址就可以了 | |
version | 脚本版本,油猴脚本的更新会读取这个版本号 | |
description | 描述,用来告诉用户这个脚本是干什么用的 | |
author | 作者名字 | |
match | 只有匹配的网址才会执行对应的脚本,例如* 、http://* 、http://www.baidu.com/* 等,参见谷歌开发者文档
|
|
grant | 指定脚本运行所需权限,如果脚本拥有相应的权限,就可以调用油猴扩展提供的API与浏览器进行交互。如果设置为none 的话,则不使用沙箱环境,脚本会直接运行在网页的环境中,这时候无法使用大部分油猴扩展的API。如果不指定的话,油猴会默认添加几个最常用的API |
|
require | 如果脚本依赖其他js库的话,可以使用require指令,在运行脚本之前先加载其他库,常见用法是加载jquery | |
connect | 当用户使用GM_xmlhttpRequest请求远程数据的时候,需要使用connect指定允许访问的域名,支持域名、子域名、IP地址以及* 通配符 |
|
updateURL | 脚本更新网址,当油猴扩展检查更新的时候,会尝试从这个网址下载脚本,然后比对版本号确认是否更新 |
脚本权限
下面简单介绍一下grant指令那里可以填写的一些权限,详情请查看油猴脚本文档。这里就简单介绍几个常用的,可以调用的函数全部以GM_作为开头。
权限名 | 功能 |
---|---|
unsafeWindow | 允许脚本可以完整访问原始页面,包括原始页面的脚本和变量。 |
GM_getValue(name,defaultValue) | 从油猴扩展的存储中访问数据。可以设置默认值,在没成功获取到数据的时候当做初始值。如果保存的是日期等类型的话,取出来的数据会变成文本,需要自己转换一下。 |
GM_setValue(name,value) | 将数据保存到存储中 |
GM_xmlhttpRequest(details) | 异步访问网页数据的API,这个方法比较复杂,有大量参数和回调,详情请参考官方文档。 |
GM_setClipboard(data, info) | 将数据复制到剪贴板中,第一个参数是要复制的数据,第二个参数是MIME类型,用于指定复制的数据类型。 |
GM_log(message) | 将日志打印到控制台中,可以使用F12开发者工具查看。 |
GM_addStyle(css) | 像网页中添加自己的样式表。 |
GM_notification(details, ondone), GM_notification(text, title, image, onclick) | 设置网页通知,请参考文档获取用法。 |
GM_openInTab(url, loadInBackground) | 在浏览器中打开网页,可以设置是否在后台打开等几个选项 |
还有一些API没有介绍,请大家直接查看官方文档吧。
编写脚本
编写脚本就很简单了,编写到// Your code here ..
那里即可。可以编写函数,然后在最后调用这几个函数,这样的模块化编写方法写出来的脚本比较容易维护。
等vagrant更新时候提醒我的脚本
前段时间了解了vagrant这个东西,感觉很有意思,准备研究一下,但是照着官网教程运行的时候,第一步就发生了错误。我上网一搜,原来我更新的virtualbox比较新,vagrant恰好不支持。但是如今几个月过去了,vagrant还是没有更新,所以我要写一个脚本,等到vagrant更新的时候,给我网页上弹出一个对话框。
首先访问vagrant官网,然后就可以看到中间下载按钮上大大的版本号2.2.6了。因为版本肯定是不会倒退的,所以只要判断一下版本号不是2.2.6,就可以弹出提示了。通过F12开发者工具可以看到,这三个按钮其实都是链接,只不过显示成了按钮的样子,而且他们恰好都位于header
标签之中。如果如果可以的话,直接用选择器就可以非常轻松的获取到版本号。
为了能在更新的时候及时获取到提示,我需要脚本在所有网站上生效,来检测版本。但是这样做会导致另外一个问题,那就是每次打开一个网页都会运行一次检查vagrant的脚本,而这是完全不必要的。所以需要一个额外的判断,这就需要利用油猴提供的API来保存当前日期,只有每天第一次的时候才会执行检查代码。本来我想的很复杂,需要一个日期变量,然后还要额外一个变量保存是否是今天第一次更新。后来我发现我想的太多了,做法其实很简单。每天先获取一次日期,然后和事先保存的日期比较,如果不一样的话才执行脚本,并将日期设置为今天的日期;如果日期一样的话无事发生。
最后一个问题就是如何来判断版本号,有两种方法:第一种就是上面提到的,直接解析HTML代码并找到版本号;第二种是更直接的办法, 因为vagrant也是Github上开源的项目,所以可以直接调用Github的API来获取最新发布的版本号。可惜的是,第二种办法我试了一下居然不成功,不知为何,没办法获取到发布信息,但是换成其他项目就可以。所以最后没办法只好采用第一种办法。有兴趣的同学可以自己试一下第二种方法。
好了,所有相关的坑我都已经解释完毕了,相信大家应该很容易就可以看懂下面的代码,我就不介绍了。虽然看着简单,但是我其实还是踩了不少的坑,就这点代码花了我好几天的时间。而且确实这个代码写的也并不是很好,因为ajax取回来的代码是完整一个html页面,貌似用原版DOM API没办法解析,最后只好用jQuery的parseHTML
方法解析的。而且我还因为原生方法和jQuery之间的方法名搞混了,浪费了很多时间。
// ==UserScript==
// @name remind_me_vagrant_update
// @namespace https://github.com/techstay/myscripts
// @version 0.1
// @description remind me if vagrant support virtualbox
// @author techstay
// @match *
// @require https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js
// @connect vagrantup.com
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_setClipboard
// @grant GM_log
// @grant GM_xmlhttpRequest
// @grant unsafeWindow
// @grant window.close
// @grant window.focus
// ==/UserScript==
(function () {
'use strict';
const CHECKED_DATE = 'checkedDate';
function checkDateEquals(a, b) {
return a.getFullYear() === b.getFullYear() &&
a.getMonth() === b.getMonth() &&
a.getDate() === b.getDate();
}
function checkVagrantVersion() {
GM_setValue(CHECKED_DATE, new Date());
GM_xmlhttpRequest({
"method": "GET",
"url": "https://www.vagrantup.com/",
"headers": {
"user-agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
},
"onload": function (result) {
var list = jQuery.parseHTML(result.response);
jQuery.each(list, function (i, el) {
if (el.nodeName == 'HEADER') {
var header = jQuery.parseXML(el.innerHTML);
var version = header.getElementsByTagName('a')[1].textContent.replace('Download ', '');
if (version != '2.2.6') {
alert('Vagrant update!');
}
return false;
}
});
}
});
}
var today = new Date();
var lastCheckedDay = new Date(GM_getValue(CHECKED_DATE, new Date('2006-1-1')));
if (!checkDateEquals(lastCheckedDay, today)) {
checkVagrantVersion();
}
})();
调试脚本
编写脚本很难一次成功,大部分时间都花在了调试上面。调试油猴脚本的话有几种调试方法。
第一种方法就是最原始的打印日志,可以利用console.log
和GM_log
来将关键信息打印出来,上面的脚本就是我靠打印日志一点点发现各种参数错误的。说实话这种办法有点笨。
第二种就是利用浏览器的调试功能,在脚本需要调试的地方插入debugger;
语句,然后在打开F12开发者工具的情况下刷新页面,就会发现网页已经暂停在相应位置上。这样就可以利用F12开发者工具进行单步调试、监视变量等操作了。
将文章同步复制到Csdn和思否编辑器的脚本
我的文章一般都是简书首发,然后复制粘贴到Csdn中,但是后来我发现每次手动操作太蠢了,为什么不用脚本来自动化呢?所以我又写了个脚本帮忙完成自动化工作。本来以为这个脚本应该比较简单,不过还是踩了很多坑才凑合把功能写出来。
首先是数据的保存,利用油猴提供的GM_setValue
倒是可以很简单的将文章标题和内容保存起来。不过问题来了,如何在不同页面之间共享呢?有几种方案:第一种最简单粗暴,直接复制两份,对应页面首先判断是否存在数据,存在的话才执行复制操作,然后清空数据。这种方案最简单,而且如果自己直接新建文章的话也不会出问题。第二种就是数据只保存一份,通过几个变量来确定什么时候复制完成,清空数据,但是这样比较复杂,要理清逻辑顺序很麻烦。所以最后我就采用了第一种办法。
然后又遇到一个问题,那就是如果编辑器自带了保存和恢复功能,很可能会把我复制过去的文章给覆盖了,所以需要等页面加载完之后,延迟一段时间才进行复制操作。然后我又谷歌了一番,差不多解决了这个问题。
然后遇到了一个非常棘手的问题,就是SF的编辑器设计比较复杂,没办法通过直接填充value
或者text
属性的方式来写入文章,我想了很久也没有想出来怎么解决。没办法只好改用剪贴板的方式来糊弄了,也就是将文章内容复制到剪贴板里头,然后手动粘贴到编辑器中。
最后一个问题就是简书上这个复制按钮应该如何实现,其实简书编辑器的工具栏倒是空了一些部分,我本来想把按钮直接加到那个上面。但是我发现貌似一旦添加东西,那个工具栏会自动重载取消更改,所以水平所限没做到,只好利用jQueryUI加了一个很丑的浮动按钮,而且因为拖动的时候会触发单击,没办法把按钮改成了双击触发。
最后的脚本就是下面这样的。相比第一个脚本多了几个打开新页面、删除变量、访问剪贴板的API。
// ==UserScript==
// @name copy_jianshu_to_csdn_and_segmentfault
// @namespace https://github.com/techstay/myscripts
// @version 0.1
// @description 将简书文章复制到csdn和思否编辑器中
// @author techstay
// @match https://editor.csdn.net/md/
// @match https://segmentfault.com/write
// @match https://www.jianshu.com/writer*
// @require https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js
// @require https://cdn.bootcss.com/jqueryui/1.12.1/jquery-ui.min.js
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant unsafeWindow
// @grant GM_setClipboard
// @grant window.close
// @grant window.focus
// @grant GM_openInTab
// ==/UserScript==
(function () {
'use strict';
const SF_URL = 'https://segmentfault.com/write'
const CSDN_URL = 'https://editor.csdn.net/md/'
const SF_TITLE = 'sf_title'
const SF_CONTENT = 'sf_content'
const CSDN_TITLE = 'csdn_title'
const CSDN_CONTENT = 'csdn_content'
function saveArticle() {
GM_setValue(CSDN_TITLE, $('._24i7u').val())
GM_setValue(CSDN_CONTENT, $('#arthur-editor').val())
GM_setValue(SF_TITLE, $('._24i7u').val())
GM_setValue(SF_CONTENT, $('#arthur-editor').val())
}
function copyToCsdn() {
var title = GM_getValue(CSDN_TITLE, '')
var content = GM_getValue(CSDN_CONTENT, '')
if (title != '' && content != '') {
$('.article-bar__title').delay(2000).queue(function () {
$('.article-bar__title').val(title)
$('.editor__inner').text(content)
GM_deleteValue(CSDN_TITLE)
GM_deleteValue(CSDN_CONTENT)
$(this).dequeue()
})
}
}
function copyToSegmentFault() {
$(document).ready(function () {
var title = GM_getValue(SF_TITLE, '')
var content = GM_getValue(SF_CONTENT, '')
if (title != '' && content != '') {
$('#title').delay(2000).queue(function () {
$('#title').val(title)
GM_setClipboard(content, 'text')
GM_deleteValue(SF_TITLE)
GM_deleteValue(SF_CONTENT)
$(this).dequeue()
})
}
})
}
function addCopyButton() {
$('body').append('<div id="copyToCS">双击复制到CSDN和思否</div>')
$('#copyToCS').css('width', '200px')
$('#copyToCS').css('position', 'absolute')
$('#copyToCS').css('top', '70px')
$('#copyToCS').css('left', '350px')
$('#copyToCS').css('background-color', '#28a745')
$('#copyToCS').css('color', 'white')
$('#copyToCS').css('font-size', 'large')
$('#copyToCS').css('z-index', 100)
$('#copyToCS').css('border-radius', '25px')
$('#copyToCS').css('text-align', 'center')
$('#copyToCS').dblclick(function () {
saveArticle()
GM_openInTab(SF_URL, true)
GM_openInTab(CSDN_URL, true)
})
$('#copyToCS').draggable()
}
$(document).ready(function () {
if (window.location.href.startsWith('https://www.jianshu.com')) {
addCopyButton()
} else if (window.location.href.startsWith(SF_URL)) {
copyToSegmentFault()
} else if (window.location.href.startsWith(CSDN_URL)) {
copyToCsdn()
}
})
})()
其他注意事项
脚本编写流程
踩了几天坑,最后总结一下编写油猴脚本的一点步骤。首先要思考脚本的实现方式,需要用到什么API和权限,然后填写好脚本的注释信息。
然后将功能封装成函数的形式,最后在脚本末尾调用实现的函数。写的差不多的时候复制到浏览器中尝试运行。
遇到困难的时候,可能需要直接在F12开发者工具里进行调试。有些网页不用jQuery,为了方便,我们需要自己将jQuery导入到页面中,可以将下面的代码复制到浏览器控制台中。
var jq = document.createElement('script');
jq.src = "https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js";
document.getElementsByTagName('head')[0].appendChild(jq);
发布脚本
更新URL
脚本做完了,自然是要共享出来让大家一起使用的。当然既然要发布,自然要支持更新方便日后维护。方法也很简单,直接在上面的注释部分添加updateURL
即可,然后设置脚本访问地址。例如我要将脚本发布到Github上,就添加下面的注释。
// @updateURL https://raw.githubusercontent.com/techstay/myscripts/master/tampermonkey/remind_me_vagrant_update.js
上传脚本
油猴脚本支持好几个网站,其中目前最主流的是GreasyFork,登录这个网站注册一个账号,然后进入用户页面选择提交脚本,然后填写脚本代码和各项信息。
这样脚本就提交上去了,其他人也可以搜索到并安装脚本了!
出处:https://segmentfault.com/a/1190000021654926
=======================================================================================
油猴中文网
另外,也可以去油猴中文网去看看或学习,或许有想不到的收获呢?
网址:https://bbs.tampermonkey.net.cn/
油猴脚本的资源网上非常丰富,见:https://greasyfork.org/zh-CN
开发规范很简单,见 https://www.tampermonkey.net/documentation.php
常用脚本功能
添加<style>元素
//原生写法 var css = document.createElement('style'); css.setAttribute('type', 'text/css'); css.setAttribute('id', 'arrowCss'); css.append('#articleContentId{ color: red; }'); document.getElementsByTagName('head')[0].appendChild(css); //JQuery写法 var styleRule = $('<style></style>').appendTo('head'); styleRule.attr('type', 'text/css'); styleRule.attr('id', 'arrowCss'); styleRule.append('#articleContentId{ color: red; }');
=======================================================================================
如何排除在iframe中执行脚本?
document.body.insertBefore(myDiv, document.body.firstChild);但现在该网站为google-ads添加了一个iframe,结果我的div也出现在iframe中,这不是我想要的。 如何停止影响iframe的脚本?
答案1:
答案2:
if (window.top != window.self) //don't run on frames or iframes return;
出处:https://www.orcode.com/question/341802_k77225.html
=======================================================================================
每页加载只运行一次Greasemonkey脚本?
如果您使用
@include *
创建Greasemonkey脚本并转到类似youtube的网站,则每次刷新时它都会运行脚本20次以上。这是在Firefox上,不确定Chrome。 有办法防止这种情况吗?
答案1:
首先,您可能不希望脚本在iFrame中运行。 您可以使用
@noframes
指令来阻止它,该指令现在可以在2014年10月的Greasemonkey和Tampermonkey中使用。 对于旧版本或不支持
@noframes
的脚本引擎,您可以在元数据块之后使用此代码:
if (window.top != window.self) //don't run on frames or iframes { //Optional: GM_log ('In frame'); return; }
其次,您可以在页面加载时等待并触发GM代码一次。用
main()
包裹所有内容并在
load
事件中调用它,如下所示:
window.addEventListener ("load", LocalMain, false); function LocalMain () { // Your code goes here. }
第三,您可以通过向元数据块添加
// @exclude
指令来排除网站或页面。 总的来说,如果可能的话,最好避免普遍包含的GM脚本。 其他方法可能设置标志或使用URL参数重新加载页面。这些变得棘手,所以将它们作为最后的手段来保存
答案2:
例如,您可以将给定位置存储在持久变量中。 在页面加载时,您必须检查当前位置是否已存储在此变量中。 如果没有,你设置变量并运行你的函数,如果是什么都不做。 如何存储持久变量:GM_setValue
出处:https://www.orcode.com/question/1028919_k1a1fa.html
=======================================================================================
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==
出处:https://blog.csdn.net/Backspace110/article/details/128807263
=======================================================================================
油猴脚本的内置api简单分类
油猴脚本中的@grant标签后会跟 GM_**类似的api
@grant is used to whitelist GM_* and GM.* functions, the unsafeWindow object and some powerful window functions.
@grant 功能描述的这个whitelist白名单,我就理解成解禁或者启用的意思
这个标签是用来启用GM_*和GM.*函数,不安全的窗口对象和强有力的window 函数
官方文档地址:
https://www.tampermonkey.net/documentation.php?ext=dhdg&version=4.19.0
GM_*API 按功能主要分类
WEB请求类:
GM_xmlhttpRequest(details)
GM_webRequest(rules, listener)
cookie操作:
GM_cookie.list(details[, callback])
GM_cookie.set(details[, callback])
GM_cookie.delete(details, callback)
tab选项卡操作:
GM_getTab(callback)
GM_saveTab(tab)
GM_getTabs(callback)
键值对操作:
GM_setValue(key, value)
GM_getValue(key, defaultValue)
GM_deleteValue(key)
GM_listValues()
GM_addValueChangeListener(key, (key, old_value, new_value, remote) => void)
GM_removeValueChangeListener(listenerId)
修改dom:
GM_addElement(tag_name, attributes), GM_addElement(parent_node, tag_name, attributes)
添加样式:
GM_addStyle(css)
下载:
GM_download(details), GM_download(url, name)
获取@resource 引入的资源文件的文本内容(比如js)
GM_getResourceText(name)
获取@resource 引入的资源文件的源地址
GM_getResourceURL(name)
控制台打印
GM_log(message)
屏幕通知
GM_notification(details, ondone),
GM_notification(text, title, image, onclick)
打开新选项卡
GM_openInTab(url, options),
GM_openInTab(url, loadInBackground)
菜单注册
GM_registerMenuCommand(name, callback, accessKey)
菜单注销
GM_unregisterMenuCommand(menuCmdId)
设置剪切板
GM_setClipboard(data, info)
windows窗体操作:
窗口地址改变 window.onurlchange
窗口关闭 window.close()
窗口聚焦 window.focus()
执行页面上的Window: unsafeWindow
计算对比引入文件的hash值,防止恶意代码执行:Subresource Integrity
使用方法
脚本注释区里添加 @grant API方法名 表示启用
代码区方法里直接调用
如下:
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_setClipboard
// @grant unsafeWindow
// @grant window.close
// @grant window.focus
// @grant window.onurlchange
出处:https://baijiahao.baidu.com/s?id=1768049830713830932
关注我】。(●'◡'●)
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/17509937.html
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!
posted on 2023-06-27 21:05 jack_Meng 阅读(4961) 评论(0) 编辑 收藏 举报