天马行空工作室

 找回密码
 加入天马
搜索
查看: 3268|回复: 0

GreaseMonkey脚本开发小记

[复制链接]
发表于 2013-2-3 23:05:44 | 显示全部楼层 |阅读模式
GM脚本以.user.js为扩展名。只有一个脚本文件,结构构成非常简单。总共就两部分:metadata部分和javascript部分。
        metadata以javascript的注释形式出现在脚本最开头部分。主要作用是记录脚本的一些必要信息,GreaseMonkey会阅读这一部分的信息,来识别脚本应该在何时应用以及一些其他的操作方法。
        javascript部分则就是简单的javascript代码,具体的语法我不会在这里详述。一是篇幅所限,二是水平有限。
        如果你还不会javascript,可以参考该网站的教程,写的相当不错:
                http://w3school.com.cn/
        这网站可以说帮了我很大的忙。从我初步的体验来看,作为一个只有一点Python底子,C/C++烂的可以忽略不计的人来说,javascript还是比较容易入门的一种语言。(当然,这也可能是因为javascript与python比较相似造成的)
metadata结构说明
        metadata要放在GM脚本的开头,起于:
        // ==UserScript==
        止于:
        // ==/UserScript==
        中间每行均已//开头(毕竟为了不影响js脚本的使用,他们都是注释~~)。变量前都有@,变量和值之间用空格或制表符隔开(几个都行,有就可以),形如:
        // @name    myGreaseMonkeyScript
        下面我们来看下metadata中的各种变量含义:
        @name
        脚本名,有且只能有一个。随便明明什么都可以,这是你的自由。
        @namespace
        命名空间,不多于一个,可以没有。这个也是随便什么都可以,甚至可以没有。它的作用是区分相同名称的不同脚本。一般来说,如果你有自己的主页,就填上相应的URL,如果没有该项,默认就是下载该脚本的地址。
        @description
        脚本描述,不多于一个,可以没有。顾名思义,这个就是脚本的描述,写什么随便,写不写也随便。不过建议还是简单的写上两句,让用户大概知道这个脚本是个啥。
        @include 和 @exclude
        包括和不包括的站点,数量任意:如果没有exclude,则只匹配include中指名的网站;如果没有include,则只排除exclude中的网站;都没有,则相当于匹配所有。需指名URL,支持*通配符。但别指望GM会多智能:http://www.exsample.comhttp://exsample.com是不会被自动识别为相同的网站的……
        @version
        脚本版本,不多于一个,可以没有。含义就不用解释了,只要注意一点,如果没有版本,就没法自动更新。
        @updateURL 和 @downloadURL
        升级地址和下载地址,分别不多于一个,可以没有。用于脚本的自动更新(需要GreaseMonkey是v0.9.18或以上版本)。如果不填写,默认是脚本的下载地址。如果是基于userscripts.org发布,则一般downloadURL填写脚本下载链接,而updateURL填写meta下载链接(将你的脚本名由xxx.user.js改为xxx.meta.js即可,前面的URL内容不用变)。

        综上所述,我的这个脚本的metadata部分是这么写的:
// ==UserScript==
// @name        测试脚本
// @namespace   http://www.xsecure.cn/
// @description 这是一个测试脚本
// @include     http://*.exsample.com/*
// @exclude     http://www.exsample.com/*
// @updateURL        https://userscripts.org/scripts/source[img]file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/)W_[PKS_35XA~%25$SQ0_SRK9.gif[/img]xxxx.meta.js
// @downloadURL        https://userscripts.org/scripts/source[img]file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/)W_[PKS_35XA~%25$SQ0_SRK9.gif[/img]xxxx.user.js
// @version     0.1.4
// ==/UserScript==
javascript要点小记
        我说了,无论是限于篇幅还是本人水平,我都不可能去介绍javascript这门语言。所以我是在假设大家已经了解javascript的基本语法的前提下,分享一些我在写脚本过程中遇到的问题及解决方法:
1.获取元素:
        一般使用函数getElementById()或getElementsByTagName().在元素有固定id的前提下,肯定是优先使用前一个,这样可以精准的定位到某一个特定id的元素;而在元素没有id的情况下,可以用第二个函数获取,其参数为元素名称。但由getElementsByTagName()获取到的并非一个元素,而是一个含有多个元素的数组。这时候需要通过循环或索引的方式获取到其中的某个或某些元素节点进行具体操作。
2.获取类名:
        如这段代码我就困惑了很久:
                <h3 class="res-title">…</h3>
        我获取到了<h3>元素的节点后,却怎么也取不到h3.class的值,这让我困惑了很久。后来我突然意识到——class可能是个特殊的属性,于是我专门去查了下如何获取“类名”,终于知道了,应该用:
                h3.className
        如此一来,我就可以顺利的获取域名了。
3.获取/删除属性:
        很多时候我需要获取某个元素的属性来进行判断或赋值。那么获取属性就应该用getAttribute()函数。我知道可能有些人会说用诸如a.href这种方式也可以获取元素中属性的值——但显然不全是这样。
        我这里遇到了一个实际的例子:
        so.360.cn这个域名下的搜索,为了反屏蔽干脆直接将所有指向百度的链接指向了自己的快照。而具体实现方法则是在指向百度链接的<a>元素中加入一个名为"data-cache"的属性,就因为这个data和cache中间的横线,就没法直接获取了。当你运行类似如下的代码的时候就会被抛出一个异常:
var a=document.getElementsByTagName("a");
for(var i in a) {
    alert(a.data-cache);
}
//Exception: cache is not defined
        而为了避免这种情况,还是应该用a.getAttribute("data-cache")来获取这一属性的值。
        同样是在这一例子中,我其实是需要删除该属性的(因为我自己会完成反屏蔽的功能,不再需要他跳转到快照中)。删除属性的函数其实已经不难猜到了—--removeAttribute()即可。
4.添加监听函数以及屏蔽原有功能:
        在开发过程中,我需要劫持用户点击页面<a>元素链接的动作,并将其替换为我自己设定的行为,那么这里我就需要解决两个问题:其一是如何获取用户点击这一动作;其二是如何屏蔽<a>元素原本打开链接的功能。
        获取用户点击动作我用事件监听器来实现,即:addEventListener()函数,该函数有三个参数,分别是:type、listener和useCapture.一般最后一个设为false即可;第一个type是一个字符串,表明你要监听的动作,比如鼠标点击就是"click"(不是"onClick",其他事件也类似,去掉on,首字母小写);而listener参数则是一个自定义的函数,这个函数会接收一个event参数——记住这个event参数,下面要用。
        这样,通过addEventListener()函数就可以监听鼠标点击链接的动作,并且自定义你要执行的函数了。
        而屏蔽原有功能——比如这里我想让<a>元素原有的操作不执行(如果不屏蔽,用户就会在一次点击时触发两个新页面的打开——一个是我的脚本发起的,另一个是<a>元素自身发起的)。方法其实也很简单(最开始我是傻傻的将<a>元素的href属性定义为"javascript:void(0)"了……):在addEventListener()函数的自定义函数里进行操作即可。还记得上面的那个事件参数event么?就是他的一个方法:event.preventDefault()——就这一句,即可屏蔽掉被监听器监听的元素原有的功能。
5.获取触发事件的元素节点:
        解决完上面的事情,我又遇到了一个很实际的问题:我是以循环的方式向所有指向百度的链接添加监听器的,所以监听器的函数必然是相同的,但我需要在点击不同链接的时候跳转到不同的地址,这怎么办?我图样图森破的试过直接在添加监听器的时候引用当时的变量值,但失败了——因为监听器虽然是在循环中就加载的,但并没有执行。等你触发监听器的时候,变量的值早就因为循环而变了……
        依然是那句话——还记得那个event元素么?event.target属性,便可轻松的获取触发监听器的元素节点了!至此,你想获取什么信息就获取什么信息

您需要登录后才可以回帖 登录 | 加入天马

本版积分规则

Archiver|手机版|小黑屋|天马行空工作室 ( 京ICP备12003429号  

GMT+8, 2020-4-5 02:25 , Processed in 0.027570 second(s), 18 queries .

Powered by Discuz! v8

© 2010-2014 GreaseMonkey脚本开发小记 - 编程讨论 天马行空工作室

快速回复 返回顶部 返回列表