V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
imn1
V2EX  ›  分享创造

改了人家一个 addon 的脚本,增加了隐藏/显示元素的功能,方便喜欢“眼不见为净”的人

  •  
  •   imn1 · 2015-01-01 20:04:06 +08:00 · 3594 次点击
    这是一个创建于 3601 天前的主题,其中的信息可能已经有所发展或是发生改变。

    不算100%创造,不知放什么节点

    https://addons.mozilla.org/en-US/firefox/addon/xpathprototyping
    https://github.com/polkovnikov-ph/xpath-prototyping
    改了上面这个script,放入油猴可用
    可以简单实现 xpath 选择并隐藏元素,css select 的支持就懒得研究了
    例如可以在本页输入 //img 试试
    兼容性不好,某些有后台ajax刷新的网页会出现跳转或关闭
    无版权、无著作权,一切权利归原作者,改了@name只是为了不冲突,谁要修改自用自便,转发请参考原作者的声明

    另外有兴趣的人可以装这个玩
    https://addons.mozilla.org/en-US/firefox/addon/element-locator-for-webdriv
    提取网页元素的xpath,支持多种语言的格式

    油猴脚本 Javascript

    // ==UserScript==
    // @name        xpath-hide-element
    // @namespace   wtf-is-namespace
    // @description HTML data mining
    // @version     0.1
    // @grant       none
    // ==/UserScript==
    
    var FIREBUG_MODE = true;
    
    function createXPathFromElement(elm) {
        for (segs = []; elm && elm.nodeType == 1; elm = elm.parentNode) {
            var name = elm.localName.toLowerCase();
            if (name == 'html') { segs.unshift(name); break; }
            var i;
            for (i = 1, sib = elm.previousSibling; sib; sib = sib.previousSibling)
                if (sib.localName == elm.localName)
                    ++i;
            if (FIREBUG_MODE) {
                if (i > 1)
                    name += '[' + i + ']';
            } else {
                if (elm.hasAttribute('id') && elm.getAttribute('id') != "") {
                    name += '[@id="' + elm.getAttribute('id') + '"]';
                } else {
                    name += '[' + i + ']';
                    if (elm.hasAttribute('class') && elm.getAttribute('class') != "")
                        name += '[@class="' + elm.getAttribute('class') + '"]';
                }
            }
            segs.unshift(name);
        }
        return segs.length ? '/' + segs.join('/') : null;
    }
    
    function lookupElementByXPath(path) {
        var evaluator = new XPathEvaluator();
        var result = evaluator.evaluate(path, document.documentElement, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
        return result.singleNodeValue;
    }
    
    function lookupElementsByXPath(x) {
        var result = document.evaluate(x, document.documentElement, null, 5, null);
        var res = [], next;
        while (next = result.iterateNext())
            res.push(next);
        return res;
    }
    
    var reverseStyle = [];
    function unStyle() {
        for (var i = 0; i < reverseStyle.length; ++i)
            reverseStyle[i][0].style.cssText = reverseStyle[i][1];
    }
    
    function drawFromPath(path) {
        var list = lookupElementsByXPath(path);
        unStyle();
        for (var i = 0; i < list.length; ++i) {
            reverseStyle.push([list[i], list[i].style.cssText]);
            if (list[i].tagName.toLowerCase() == "img") {
                list[i].style.border = '3px solid yellow';
            } else {
                list[i].style.background = '#FFFFA0';
            }
        }
    }
    
    function hideFromPath(path) {
        var list = lookupElementsByXPath(path);
        unStyle();
        for (var i = 0; i < list.length; ++i) {
            reverseStyle.push([list[i], list[i].style.cssText]);
            list[i].style.display = 'none';
        }
    }
    
    function showFromPath(path) {
        var list = lookupElementsByXPath(path);
        unStyle();
        for (var i = 0; i < list.length; ++i) {
            reverseStyle.push([list[i], list[i].style.cssText]);
            list[i].style.display = 'block';
        }
    }
    
    document.documentElement.addEventListener("click", function(event) {
        if (!event.altKey) return;
        if (event === undefined) event = window.event;
        var target = 'target' in event ? event.target : event.srcElement;
        var path = createXPathFromElement(target);
        document.getElementById("xpath").value = path;
        drawFromPath(path);
        return false;
    });
    
    var Base64 = {
        // private property
        _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
        // public method for encoding
        encode : function (input) {
            var output = "";
            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
            var i = 0;
            input = Base64._utf8_encode(input);
            while (i < input.length) {
                chr1 = input.charCodeAt(i++);
                chr2 = input.charCodeAt(i++);
                chr3 = input.charCodeAt(i++);
                enc1 = chr1 >> 2;
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;
                if (isNaN(chr2)) {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3)) {
                    enc4 = 64;
                }
                output = output +
                Base64._keyStr.charAt(enc1) + Base64._keyStr.charAt(enc2) +
                Base64._keyStr.charAt(enc3) + Base64._keyStr.charAt(enc4);
            }
            return output;
        },
    
        // public method for decoding
        decode : function (input) {
            var output = "";
            var chr1, chr2, chr3;
            var enc1, enc2, enc3, enc4;
            var i = 0;
            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
            while (i < input.length) {
                enc1 = Base64._keyStr.indexOf(input.charAt(i++));
                enc2 = Base64._keyStr.indexOf(input.charAt(i++));
                enc3 = Base64._keyStr.indexOf(input.charAt(i++));
                enc4 = Base64._keyStr.indexOf(input.charAt(i++));
                chr1 = (enc1 << 2) | (enc2 >> 4);
                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                chr3 = ((enc3 & 3) << 6) | enc4;
                output = output + String.fromCharCode(chr1);
                if (enc3 != 64) {
                    output = output + String.fromCharCode(chr2);
                }
                if (enc4 != 64) {
                    output = output + String.fromCharCode(chr3);
                }
            }
            output = Base64._utf8_decode(output);
            return output;
        },
    
        // private method for UTF-8 encoding
        _utf8_encode : function (string) {
            string = string.replace(/\r\n/g,"\n");
            var utftext = "";
            for (var n = 0; n < string.length; n++) {
                var c = string.charCodeAt(n);
                if (c < 128) {
                    utftext += String.fromCharCode(c);
                } else if((c > 127) && (c < 2048)) {
                    utftext += String.fromCharCode((c >> 6) | 192);
                    utftext += String.fromCharCode((c & 63) | 128);
                } else {
                    utftext += String.fromCharCode((c >> 12) | 224);
                    utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                    utftext += String.fromCharCode((c & 63) | 128);
                }
            }
            return utftext;
        },
    
        // private method for UTF-8 decoding
        _utf8_decode : function (utftext) {
            var string = "";
            var i = 0;
            var c = 0, c1 = 0, c2 = 0;
    
            while ( i < utftext.length ) {
    
                c = utftext.charCodeAt(i);
    
                if (c < 128) {
                    string += String.fromCharCode(c);
                    i++;
                }
                else if((c > 191) && (c < 224)) {
                    c1 = utftext.charCodeAt(i+1);
                    string += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
                    i += 2;
                }
                else {
                    c1 = utftext.charCodeAt(i+1);
                    c2 = utftext.charCodeAt(i+2);
                    string += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63));
                    i += 3;
                }
    
            }
            return string;
        }
    }
    
    window.addEventListener("load", function () {
        body = document.getElementsByTagName("body")[0];
        var space = document.createElement('div');
        space.style.height = "34px";
        space.style.clear = "both";
        body.appendChild(space);
        div = document.createElement("div");
        div.innerHTML = "\
        <div id=\"xpather\" style=\"position: fixed; left: 0px; top: 100%; margin-top: -34px; width: 100%; height: 34px; background: white; z-index: 32768;\">\
            <table style=\"border: 0px; padding: 0px; border-collapse:collapse; width: 100%; height: 34px; background-repeat: repeat-x;background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAiCAIAAAARTyRGAAAABGdBTUEAALGPC/xhBQAAAINJREFUGFcFwdkSgQAAQNH7A5492k1qKqV90aIINZliGMswvPsFv+4cOt0B9++P/Pgha9+kzYvk8CSuH0TVjbC8Euwv+NszXnHCXbc4eYO1OmCmNUZcsYhKtOWOeVCg+hsUN0d2MiQ7RTQTZkaEoIdMtYCJ6jFWXEayzVCy6IsGPUH/A1YQGPVUbzmcAAAAAElFTkSuQmCC)\">\
                <tr>\
                    <td style=\"vertical-align: middle; padding:0px; width: 21px; background-repeat: no-repeat; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAiCAIAAAA/CgXUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAbNJREFUSEul1LtOwlAcx/HjAzgJGoOIchMvUEBuhSLQUigUyq0ICFjFaNSor2Cc3XV2d3fXWWfdfRB/BgYCDPSUfJaT/L9tOW3OwuLKJjHy693dG0FE9cwIkm0MjCB8/WRIaAyKR1dK/0bRbudHMlUN+Nqp3Lly7IXNa/alVdv8SLrSB6l1gXh53bXmZKxu//xIqtwFuXNpttitbsbmCepCkqUjKHYu8cy6yuEw4eQ2FNoXlH2i0AKpdU7Zx6Um5A/PKHs214CcOqDsY2IdxMYpZR8RqiDUtOn++eV1/I1MLEf7H+YrIFSPp/vP79+39y9Z1YajE8tRH0qXgVd6M++PBh4enzCN+48vR/1+qgQZpTvz/ze16/fPH2Svbx8IJpb/30/goAipcoey93MSHMhtyudnEnlIFluU++djReCkJuX788aykMirlN/PbpSHeK5O2e+EM8CKNcp+O5SCWLZK2XuCSYjyCmXvDnAQSpdMls31Lb/eI4y4mDgw8ZzV5cX5q/cSxOljwe3nAlwBlzBZNuY//DFJHN7okMvH+mJCMCnpQuy7ESPIxk7ICKJ3wyfm/wD+N9ogH8OeTAAAAABJRU5ErkJggg==);\"></td>\
                    <td style=\"padding:0px; padding-left:3px; vertical-align: middle; background-repeat: repeat-x; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAiCAIAAAARTyRGAAAABGdBTUEAALGPC/xhBQAAADlJREFUGFdj4BVXZIjJq2dwDUlmcAlOYvCLz2UQlpRnkFUzYJDXMKIJBplvZOvBoKRtxqCgZQKyAwBCnRI+IrS80gAAAABJRU5ErkJggg==);\" >\
                        <div style=\"display: inline-block; width: 100%;\">\
                            <input id=\"xpath\" type=\"text\" style=\"margin: 0px !important; padding: 0px !important; padding-top: 1px; border: none; width: 100% !important; height: 20px !important; background: #272727 !important; color: white !important; font-family: \'Lucida Console\', Verdana, Tahoma, monospace !important;\" />\
                        </div>\
                    </td>\
                    <td style=\"padding:0px; width: 6px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAiCAIAAAACmGSyAAAABGdBTUEAALGPC/xhBQAAAUhJREFUOE910mtPgmAUwPGnD9Cr1NYU75hpAhpeEBBFQARFVMx7pq6mW+sr9NXD1XbO3Dj7vftvZzvbubm9T5Gg2Xz/BCG6dwxCtOkhCHG2X9bqrHl7dfJ+hYRj6cxz1V6e1fG+4+4wQmWZCJX1c3/x2R5tMZLIV2I0G46m7dVJGa6xS/PdPSSs5UkerDBo/k7JXmDQzPmH2J9j0Hqvx6Y5w6AZ3kEwphg0fbpv6BMMWne8q3VdDDX3raqOMGiqs+HbQwxax1m/KAMMmjJcllsWBq1lLzjJxKDJ1pwVexg0yZwxgo5BE3teqaFh0JrGpFhXMWiCPi5UOxi0huY+8QoGra46+YqMXRqV40LRFN8e5MoSRuKPXCROU3SJbRo028RIKJr0Q1nq5zgxywgYqcgm0+jSrJAp1a+QdLEWhCQLfJD/G/4++Mov51bLSPWQBGkAAAAASUVORK5CYII=);\"></td>\
                    <td style=\"padding-left: 10px; padding-right: 10px; width: 130px; vertical-align: middle;\">\
                        <a id=\"hideAll\" href=\"#\" style=\"font-size: 10pt; text-decoration: none; color: #D0D0D0;\" onmouseout=\"this.style.cssText='font-size: 10pt; text-decoration: none; color: #D0D0D0;';\" onmouseover=\"this.style.cssText='font-size: 10pt; text-decoration: none; color: #5080FF; text-shadow: 0 0 3px #5080FF;';\"> HIDE </a>\
                        <a id=\"showAll\" href=\"#\" style=\"font-size: 10pt; text-decoration: none; color: #D0D0D0;\" onmouseout=\"this.style.cssText='font-size: 10pt; text-decoration: none; color: #D0D0D0;';\" onmouseover=\"this.style.cssText='font-size: 10pt; text-decoration: none; color: #5080FF; text-shadow: 0 0 3px #5080FF;';\"> SHOW </a>\
                        <a id=\"closethis\" href=\"#\" style=\"font-size: 10pt; text-decoration: none; color: #D0D0D0;\" onmouseout=\"this.style.cssText='font-size: 10pt; text-decoration: none; color: #D0D0D0;';\" onmouseover=\"this.style.cssText='font-size: 10pt; text-decoration: none; color: #5080FF; text-shadow: 0 0 3px #5080FF;';\"> CLOSE </a>\
                    </td>\
                </tr>\
            </table>\
        </div>";
        body.appendChild(div);
        document.getElementById("xpath").addEventListener("keyup", function (event) {
            var xpath = document.getElementById("xpath").value;
            if (xpath == "") {
                unStyle();
            } else {
                drawFromPath(xpath);
            }
        });
        document.getElementById("hideAll").addEventListener("click", function (event) {
            var xpath = document.getElementById("xpath").value;
            if (xpath == "") {
                unStyle();
            } else {
                hideFromPath(xpath);
            }
        });
        document.getElementById("showAll").addEventListener("click", function (event) {
            var xpath = document.getElementById("xpath").value;
            if (xpath == "") {
                unStyle();
            } else {
                showFromPath(xpath);
            }
        });
        document.getElementById("closethis").addEventListener("click", function (event) {
            document.getElementById("xpather").style.display="none";
            return false;
        });
    });
    
    8 条回复    2015-01-02 00:50:21 +08:00
    imn1
        1
    imn1  
    OP
       2015-01-01 20:28:36 +08:00
    居然是4小时前……
    怪不得不上首页~
    @Livid
    ltm
        2
    ltm  
       2015-01-01 20:57:22 +08:00
    mozilla addon 都封了。。。
    imn1
        3
    imn1  
    OP
       2015-01-01 21:06:53 +08:00
    @ltm
    无言以对……
    wenketel
        4
    wenketel  
       2015-01-01 22:06:14 +08:00
    @ltm 只是因为EdgeCast被牵连了而已
    aaaa007cn
        5
    aaaa007cn  
       2015-01-01 22:09:41 +08:00
    这是干什么的……
    原版好像也只是查看 xpath 的
    要隐藏元素还少个用来持久化规则的组件
    或者只是为了配合 rip / yarip 来用的?
    css 选择符直接用 document.querySelector 就好了嘛
    imn1
        6
    imn1  
    OP
       2015-01-01 22:32:41 +08:00
    @aaaa007cn
    这个不是持久化的,那是adblock之类做的事
    这个值是临时清理一下网页不想看的元素,加了display=none / block 而已
    例如只想看文章,而页面图片太多,输入个//img 点 hide 就“眼不见为净”了,实际图片还是加载了的,类似还能清理其他元素,需要懂点 xpath

    我还有用一个别人写的另外的脚本,可以鼠标点哪个就隐藏/去掉哪个的,但有时太多逐个点就嫌麻烦
    例如我查某样东西,结果是含有ABCD四类,我不关心A类的,而查找条件可能没这个类别选择,就可以用 xpath 把含有A类字样的都隐藏了
    例如查太平洋的笔记本,它把停产无报价的都列出来,有时还好几页都是

    需求场合可能不是太多,但有时还是有点用的
    本来做成addon开关按钮好点
    只是改了人家的东西自用,没做成产品,也不大算维护,只是分享一下,有需要就拿去自己改吧
    有人想造成成品就从原作者那里 fork 好了
    aaaa007cn
        7
    aaaa007cn  
       2015-01-02 00:18:42 +08:00
    原来如此
    嗯……
    yarip 没有临时规则组
    rip 年代久远记不清啥样了

    话说你那个要隐藏含有 A 类字样的例子就需要规则的持久化啊……
    imn1
        8
    imn1  
    OP
       2015-01-02 00:50:21 +08:00
    @aaaa007cn
    只是方便某次使用,说不准可能下次查询就需要看 A类
    如果长久不需要就该用 privoxy 或 adblock 之类了,我在 privoxy 就设了豆瓣过滤所有招聘帖子
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   937 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 19:47 · PVG 03:47 · LAX 11:47 · JFK 14:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.