如何检测页面上的访问和未访问链接?

时间:2011-09-03 03:25:10

标签: javascript firefox hyperlink click greasemonkey

我的目标是检测网页上未访问的链接,然后创建一个greasemonkey脚本来点击这些链接。通过未访问的链接在这里我指的是我没有打开的链接。由于我可以看到所有浏览器都提供了更改已访问和未访问链接颜色的功能,因此可以以任何方式检测这些链接。 在搜索时,我发现了这个链接:http://www.mozdev.org/pipermail/greasemonkey/2005-November/006821.html但有人在这告诉我这已经不可能了。请帮忙。

2 个答案:

答案 0 :(得分:20)

正确,javascript无法检测Firefox或Chrome中是否访问过某个链接 - 这是此 Greasemonkey 上下文中仅适用的2个浏览器。

这是因为Firefox和Chrome严肃对待安全和隐私。来自the CSS2 spec

  

请注意。样式表作者可能滥用:link和:visited伪类来确定用户未经用户同意访问过哪些网站。

     因此,UA可以将所有链接视为未访问的链接,或者实现其他措施以保护用户的隐私,同时以不同方式呈现访问和未访问的链接。有关处理隐私的更多信息,请参阅[P3P]。

另见"Privacy and the :visited selector"
您可以看到一个演示,显示安全浏览器不允许您在jsfiddle.net/n8F9U嗅探访问过的链接。




针对您的具体情况,因为您正在访问某个网页并将其保持打开状态,因此您可以帮助脚本跟踪所访问的链接。这不是万无一失的,但我相信它会做你所要求的。

首先,通过执行以下操作来查看正在运行的脚本

  1. 按原样安装脚本。
  2. 浏览测试页jsbin.com/eledog 每次重新加载或刷新时,测试页都会添加一个新链接。
  3. GM脚本为其运行的页面添加了2个按钮。左上角有一个“开始/停止”按钮,右下角有一个“清除”按钮。

    当您按下“开始”按钮时,它会执行以下操作:

    1. 页面上的所有现有链接都记录为“已访问”。
    2. 启动计时器(默认设置:3秒),当计时器熄灭时,它会重新加载页面。
    3. 每次重新加载页面时,都会打开所有新链接并启动新的重新加载计时器。
    4. 按“停止”按钮停止重新加载,保留已访问链接列表。

    5. “清除”按钮会删除已访问页面列表 警告:如果在刷新循环处于活动状态时按“清除”,则下次重新加载页面时, 所有 链接将在新选项卡中打开。


      接下来,使用您网站上的脚本 ...

      仔细阅读脚本中的注释,您必须更改@include@excludeselectorStr值才能与您使用的网站相匹配。

      为获得最佳效果,禁用任何“重新加载每个”加载项或“自动更新”选项。


      重要说明:

      1. 脚本必须使用永久存储来跟踪链接 选项包括:Cookie,sessionStoragelocalStorageglobalStorageGM_setValue()IndexedDB

        这些都有缺点,在这种情况下(单个网站,可能有大量链接,多个会话),localStorage是最佳选择(IndexedDB可能是,但它仍然太不稳定 - 导致我的机器频繁发生FF崩溃。

        这意味着只能在每个站点的基础上跟踪链接,并且“安全”,“隐私”或“更干净”的实用程序可以阻止或删除访问链接列表。 (就像清除浏览器的历史记录一样,将重置访问链接的任何CSS样式。)

      2. 目前该脚本仅限Firefox。即使安装了Tampermonkey,它也不适用于Chrome,无需重新设计。



      3. 脚本:

        /*******************************************************************************
        **  This script:
        **      1)  Keeps track of which links have been clicked.
        **      2)  Refreshes the page at regular intervals to check for new links.
        **      3)  If new links are found, opens those links in a new tab.
        **
        **  To Set Up:
        **      1)  Carefully choose and specify `selectorStr` based on the particulars
        **          of the target page(s).
        **          The selector string uses any valid jQuery syntax.
        **      2)  Set the @include, and/or, @exclude, and/or @match directives as
        **          appropriate for the target site.
        **      3)  Turn any "Auto update" features off.  Likewise, do not use any
        **          "Reload Every" addons.  This script will handle reloads/refreshes.
        **
        **  To Use:
        **      The script will place 2 buttons on the page: A "Start/Stop" button in
        **      the upper left and a "Clear" button in the lower left.
        **
        **      Press the "Start" button to start the script reloading the page and
        **      opening any new links.
        **      When the button is pressed, it is assumed that any existing links have
        **      been visited.
        **
        **      Press the "Stop" button to halt the reloading and link opening.
        **
        **      The "Clear" button erases the list of visited links -- which might
        **      otherwise be stored forever.
        **
        **  Methodology:
        **      Uses localStorage to track state-machine state, and to keep a
        **      persistent list of visited links.
        **
        **      Implemented with jQuery and some GM_ functions.
        **
        **      For now, this script is Firefox-only.  It probably will not work on
        **      Chrome, even with Tampermonkey.
        */
        // ==UserScript==
        // @name        _New link / visited link, tracker and opener
        // @include     http://jsbin.com/*
        // @exclude     /\/edit\b/
        // @require     http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
        // @grant       GM_addStyle
        // ==/UserScript==
        /*- The @grant directive is needed to work around a design change
            introduced in GM 1.0.   It restores the sandbox.
        */
        
        //--- Key control/setup variables:
        var refreshDelay    = 3000;    //-- milliseconds.
        var selectorStr     = 'ul.topicList a.topicTitle';
        
        //--- Add the control buttons.
        $("body")  .append (  '<div id="GM_StartStopBtn" class="GM_ControlWrap">'
                            + '<button>Start checking for new links.</button></div>'
                    )
                   .append (  '<div id="GM_ClearVisitListBtn" class="GM_ControlWrap">'
                            + '<button>Clear the list of visited links.</button></div>'
                    );
        $('div.GM_ControlWrap').hover (
            function () { $(this).stop (true, false).fadeTo ( 50, 1); },
            function () { $(this).stop (true, false).fadeTo (900, 0.8); }// Coordinate with CSS.
        );
        
        //--- Initialize the link-handler object, but wait until the load event.
        var stateMachine;
        window.addEventListener ("load", function () {
                stateMachine    = new GM_LinkTrack (    selectorStr,
                                                        '#GM_StartStopBtn button',
                                                        '#GM_ClearVisitListBtn button',
                                                        refreshDelay
                                                    );
        
                /*--- Display the current number of visited links.
                    We only update once per page load here.
                */
                var numLinks    = stateMachine.GetVisitedLinkCount ();
                $("body").append ('<p>The page opened with ' + numLinks + ' visited links.</p>');
            },
            false
        );
        
        
        /*--- The link and state tracker object.
            Public methods:
                OpenAllNewLinks ()
                StartStopBtnHandler ()
                ClearVisitedLinkList ()
                StartRefreshTimer ();
                StopRefreshTimer ();
                SetAllCurrentLinksToVisited ()
                GetVisitedLinkCount ()
        */
        function GM_LinkTrack (selectorStr, startBtnSel, clearBtnSel, refreshDelay)
        {
            var visitedLinkArry = [];
            var numVisitedLinks = 0;
            var refreshTimer    = null;
            var startTxt        = 'Start checking for new links.';
            var stopTxt         = 'Stop checking links and reloading.';
        
            //--- Get visited link-list from storage.
            for (var J = localStorage.length - 1;  J >= 0;  --J) {
                var itemName    = localStorage.key (J);
        
                if (/^Visited_\d+$/i.test (itemName) ) {
                    visitedLinkArry.push (localStorage[itemName] );
                    numVisitedLinks++;
                }
            }
        
            function LinkIsNew (href) {
                /*--- If the link is new, adds it to the list and returns true.
                    Otherwise returns false.
                */
                if (visitedLinkArry.indexOf (href) == -1) {
                    visitedLinkArry.push (href);
        
                    var itemName    = 'Visited_' + numVisitedLinks;
                    localStorage.setItem (itemName, href);
                    numVisitedLinks++;
        
                    return true;
                }
                return false;
            }
        
            //--- For each new link, open it in a separate tab.
            this.OpenAllNewLinks        = function ()
            {
                $(selectorStr).each ( function () {
        
                    if (LinkIsNew (this.href) ) {
                        GM_openInTab (this.href);
                    }
                } );
            };
        
            this.StartRefreshTimer      = function () {
                if (typeof refreshTimer != "number") {
                    refreshTimer        = setTimeout ( function() {
                                                window.location.reload ();
                                            },
                                            refreshDelay
                                        );
                }
            };
        
            this.StopRefreshTimer       = function () {
                if (typeof refreshTimer == "number") {
                    clearTimeout (refreshTimer);
                    refreshTimer        = null;
                }
            };
        
            this.SetAllCurrentLinksToVisited = function () {
                $(selectorStr).each ( function () {
                    LinkIsNew (this.href);
                } );
            };
        
            this.GetVisitedLinkCount = function () {
                return numVisitedLinks;
            };
        
            var context = this; //-- This seems clearer than using `.bind(this)`.
            this.StartStopBtnHandler    = function (zEvent) {
                if (inRefreshCycle) {
                    //--- "Stop" pressed.  Stop searching for new links.
                    $(startBtnSel).text (startTxt);
                    context.StopRefreshTimer ();
                    localStorage.setItem ('inRefreshCycle', '0'); //Set false.
                }
                else {
                    //--- "Start" pressed.  Start searching for new links.
                    $(startBtnSel).text (stopTxt);
                    localStorage.setItem ('inRefreshCycle', '1'); //Set true.
        
                    context.SetAllCurrentLinksToVisited ();
                    context.StartRefreshTimer ();
                }
                inRefreshCycle  ^= true;    //-- Toggle value.
            };
        
            this.ClearVisitedLinkList   = function (zEvent) {
                numVisitedLinks = 0;
        
                for (var J = localStorage.length - 1;  J >= 0;  --J) {
                    var itemName    = localStorage.key (J);
        
                    if (/^Visited_\d+$/i.test (itemName) ) {
                        localStorage.removeItem (itemName);
                    }
                }
            };
        
            //--- Activate the buttons.
            $(startBtnSel).click (this.StartStopBtnHandler);
            $(clearBtnSel).click (this.ClearVisitedLinkList);
        
            //--- Determine state.  Are we running the refresh cycle now?
            var inRefreshCycle  = parseInt (localStorage.inRefreshCycle, 10)  ||  0;
            if (inRefreshCycle) {
                $(startBtnSel).text (stopTxt); //-- Change the btn lable to "Stop".
                this.OpenAllNewLinks ();
                this.StartRefreshTimer ();
            }
        }
        
        //--- Style the control buttons.
        GM_addStyle ( "                                                             \
            .GM_ControlWrap {                                                       \
                opacity:            0.8;    /*Coordinate with hover func. */        \
                background:         pink;                                           \
                position:           fixed;                                          \
                padding:            0.6ex;                                          \
                z-index:            666666;                                         \
            }                                                                       \
            .GM_ControlWrap button {                                                \
                padding:            0.2ex 0.5ex;                                    \
                border-radius:      1em;                                            \
                box-shadow:         3px 3px 3px gray;                               \
                cursor:             pointer;                                        \
            }                                                                       \
            .GM_ControlWrap button:hover {                                          \
                color:              red;                                            \
            }                                                                       \
            #GM_StartStopBtn {                                                      \
                top:                0;                                              \
                left:               0;                                              \
            }                                                                       \
            #GM_ClearVisitListBtn {                                                 \
                bottom:             0;                                              \
                right:              0;                                              \
            }                                                                       \
        " );
        

答案 1 :(得分:-2)

您可以解析页面上的所有链接并获取其CSS颜色属性。如果链接的颜色与您在CSS中定义的未访问链接的颜色匹配,则此链接未被访问。

这种技术通常用于确定所有访问过的链接。 这是一种安全漏洞,允许您确定用户是否访问了特定的网站。通常由低级营销人员使用。

这种技巧通常被归类为“浏览器的历史操纵技巧”。

有关代码的更多信息:http://www.stevenyork.com/tutorial/getting_browser_history_using_javascript