记userscripts.org
所幸还有好心人建立了一个镜像站点http://userscripts-mirror.org/。只是仅仅能静态訪问。搜索讨论修改等功能都关闭。假设要找某个脚本,仅仅能利用相似Google的站点搜索功能。
印象中我获知userscripts.org大约是在09年前后。Firefox五花八门的插件阵营里的明星GreaseMonkey让Firefox倡导的自己定义互联网的理念不止步于浏览器。进入原本是站点开发人员决定的网页领域。依照自己的想法修正、增强和美化一直以来仅仅能被动接受的网页,这个新鲜的主意令非常多网民中的开发人员跃跃欲试。也让很多其它普通的Firefox用户踊跃安装使用数量高速增长、针对大量站点、功能繁多的脚本。个性化和自主性需求的满足似乎一时让上网变得更加有趣。
用户脚本的集散地userscripts.org站点也应需而生。
当年这个专门用途的站点在我眼里是个有趣又精致的地方,在这能发现他人的巧思,仅凭一个脚本就使熟悉的站点更加友好方便。而当我也開始在上面公布脚本后,常常去看看每日脚本下载次数就变得我想有点像股民关注股市,毕竟这是第一次自己写的程序被互联网那一端成千上万不认识的人下载使用。
Chrome、Opera随后也有了各自的XXXMonkey插件,内容脚本不再是Firefox的专利。渐渐地随着对脚本修改的降低,我对它的兴趣也淡漠了。站点的改版、浏览器和插件的升级都可能使脚本失效或不再实用,还有一方面设计和开发精良的站点,用户操作友好,内容脚本的用武之地也减小(除了那些突破站点开发人员本意的限制的功能)。不知不觉我几个月也未必会上一次userscripts.org。
这时userscripts.org离去了,我惊愕之馀若有所失。有人评论,userscripts.org关闭之前由于未对广告和恶意脚本加以限制。已显颓像。后继者greasyfork.org维护管理更好。我上去看后却认为它的页面美观和操作性不如前者。当互联网日益成为普通人生活中密切的一部分。抽象的数字空间也会被附以感情。
万物有生有灭。在新站点不断涌现被人接受和熟悉之际,一些以前的老伙伴也已消失。有人将这样的现象比作数字黑洞,一旦站点关闭,上面的全部数据。包含成千上万使用者的活动记录,就被永远吞噬。
所以已经有人開始“备份”整个互联网,web.archive.org如今已记录了4350亿个历史页次。userscripts.org的静态页面也能够通过它訪问。
相较于针对特定站点的脚本,一些通用功能的脚本是我认为最实用的。
我的最爱就包含在userscripts.org下载的用左右键翻页的脚本。
将它附在末尾以志念。
// ==UserScript== // @name HotKey Next Page // @namespace scottxp@126.com // @author scottxp // @version 1.0 // @description 按左右键翻页,能够自己针对站点定制xpath规则 // @include http://* // @include https://* // Modified by Starrow. // 1. Add the detection of contenteditable div used as textarea in HTML 5. // 2. Remove the reference to unsafeWindow, which is unnecessary and doesn't work since Firefox 30. // ==/UserScript== const nextStrs = [ '下一页', '下页', '下一节', '下一章', '下一篇', '后一章', '后一篇', '»', 'next', 'next page', 'old', 'older', 'earlier', '下頁', '下一頁', '后一页', '后一頁', '下一則', '翻下页', '翻下頁', '后页', '后頁', '下翻', '下一个', '下一张', '下一幅', 'Next >' ]; const lastStrs = [ '上一页', '上页', '上一节', '上一章', '上一篇', '前一章', '前一篇', '«', 'previous', 'prev', 'previous page', 'new', 'newer', 'later', '上頁', '上一頁', '上一則', '前一页', '前一頁', '翻上页', '翻上頁', '前页', '前頁', '上翻', '上一个', '上一张', '上一幅', '< Prev' ]; const GeneralXpaths = [ ["//a[(text()='","')]"], ["//input[@type='button' and @value='","']"] ]; //编辑以下的数组来自己定义规则 const SpecialXpaths = [ { //匹配的url urls : [ "http://www.google.com" ], //上一页节点的xpath last : "//a[@id='pnprev']", //下一页节点的xpath next : "//a[@id='pnnext']" } ]; const LEFT = 37; const RIGHT = 39; function checkKey(e){ if (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey ) return ; if(checkTextArea(e.target)) return ; var node; if(e.keyCode == LEFT && (node = getNode(LEFT))){ click(node); } if(e.keyCode == RIGHT && (node = getNode(RIGHT))){ click(node); } } function checkTextArea(node){ var name = node.localName.toLowerCase(); if (name == 'textarea' || name == 'input' || name == 'select') return true; if(name == 'div' && node.id.toLowerCase().indexOf('textarea')!=-1) return true; //Add new textarea which are div with contenteditable being true. //contenteditable is new in HTML 5 and supported in all major browsers. //In case contenteditable is supported but cannot be read via DOM, use attributes["contenteditable"].value. if (node.contenteditable===true || (node.attributes["contenteditable"] && node.attributes["contenteditable"].value==="true")) { return true; } return false; } function click(node){ if(node.onclick) node.onclick(); if(node.click) node.click(); if(node.href) location.href = node.href; } function xpath(query) { return document.evaluate(query, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); } function getNode(keyCode){ var node = getNodeByGeneralXpath(keyCode) if (!node) node = getNodeBySpecialXpath(keyCode); return node; } function getNodeByGeneralXpath(keyCode){ var strs; if(keyCode == LEFT) strs = lastStrs; else if(keyCode == RIGHT) strs = nextStrs; else return null; var x = GeneralXpaths; for (var i in x){ for (var j in strs){ var query = x[i][0]+strs[j]+x[i][1]; var nodes = xpath(query); if(nodes.snapshotLength > 0) return nodes.snapshotItem(0); } } return null; } function getNodeBySpecialXpath(keyCode){ var s = SpecialXpaths; for (var i in s){ if(checkXpathUrl(s[i].urls)){ if (keyCode == LEFT){ return xpath(s[i].last).snapshotItem(0); } else if(keyCode == RIGHT){ return xpath(s[i].next).snapshotItem(0); } } } return null; } function checkXpathUrl(urls){ for(var i in urls) if(location.href.indexOf(urls[i]) == 0) return true; return false; } if (top.location != self.location) return; document.addEventListener('keydown', checkKey, false);
版权声明:本文博主原创文章。博客,未经同意不得转载。