如何检测页面上的已访问和未访问的链接? [英] How can I detect visited and unvisited links on a page?

查看:414
本文介绍了如何检测页面上的已访问和未访问的链接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

正确的情况是,javascript无法检测到Firefox或Chrome是否访问过链接 -



这是因为Firefox和Chrome严重地采取了安全和隐私保护措施,这是唯一适用于这个 greasemonkey 上下文的2个浏览器。从 CSS2规范


注意。样式表作者可以滥用:link和:被访问的伪类来确定用户在没有用户同意的情况下访问了哪些网站。



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


另请参阅 隐私权和已访问的选择器

您可以看到一个演示,表明安全浏览器不会让您嗅探访问的链接 jsfiddle.net/n8F9U












对于您的特定情况,由于您正在访问某个网页并将其保持打开状态,因此您可以帮助脚本跟踪链接访问。这不是傻瓜,但我相信它会做你所要求的。



首先,查看脚本在操作


  1. 安装脚本。

  2. 浏览测试页, a href =http://jsbin.com/eledog> jsbin.com/eledog 。

    每次重新加载或刷新时,测试页面都会添加一个新链接。 li>
  3. GM脚本在它运行的页面上添加了2个按钮。



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


    1. 页面上现有的所有链接都记录为已访问。


    2. 每次页面重新加载时,它会打开任何新的链接并启动一个新的重新加载计时器(默认设置:3秒),当计时器关闭时,它重新加载页面。

    3. 按停止按钮停止重新加载,访问的链接列表将保留。


    清除按钮会删除访问过的页面列表。

    警告:如果在刷新循环处于活动状态时按清除,则下次重新加载网页时, 全部 链接将在新标签页中打开。

    / li>



接下来,使用您网站上的指令码 p>

仔细阅读脚本中的注释,您必须更改 @include @排除 selectorStr 值以匹配您使用的网站。






$ b $

b

重要注意事项:




  1. 脚本必须使用永久存储来跟踪链接。 br>
    选项为:cookies, sessionStorage localStorage globalStorage GM_setValue() IndexedDB



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



    这意味着链接只能在每个站点跟踪,安全 ,或更干净的实用程序可以阻止或擦除访问链接的列表。 (就像清除浏览器的历史记录会重置访问过的链接的任何CSS样式。)


  2. 此脚本目前仅支持Firefox。



/ p>




脚本:



  / *********************************************** ******************************** 
**此脚本:
** 1)保留跟踪哪些链接已被点击。
** 2)定期刷新页面以检查新链接。
** 3)如果找到新链接,在新标签页中打开这些链接。
**
**设置:
** 1)根据目标页面的细节
**仔细选择并指定`selectorStr`。
**选择器字符串使用任何有效的jQuery语法。
** 2)将@include和/或,@exclude和/或@match指令设置为适用于目标站点的
**。
** 3)关闭任何自动更新功能。同样,不要使用任何
**重新加载每个插件。此脚本将处理重新加载/刷新。
**
**使用:
**脚本将在页面上放置2个按钮:
**中的开始/停止按钮左上角和左下角的清除按钮。
**
**按开始按钮开始脚本重新加载页面,
**打开任何新的链接。
**当按下按钮时,假定已访问任何现有链接
**。
**
**按停止按钮停止重新加载和链接打开。
**
**清除按钮清除已访问链接的列表 - 这可能
**否则永远存储。
**
**方法:
**使用localStorage跟踪状态机状态,并保留一个
**访问链接的持久列表。
**
**使用jQuery和一些GM_函数实现。
**
**现在,此脚本仅适用于Firefox。它可能不工作
** Chrome,甚至与Tampermonkey。
* /
// == UserScript ==
// @name _新链接/访问链接,跟踪和开启
// @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 ==
/ * - 需要@grant指令来处理在GM 1.0中引入的设计更改
。它恢复沙盒。
* /

// ---键控制/设置变量:
var refreshDelay = 3000; // - milliseconds。
var selectorStr ='ul.topicList a.topicTitle';

// ---添加控制按钮。
$(body).append('< div id =GM_StartStopBtnclass =GM_ControlWrap>'
+'< button>开始检查新链接。< / button> ;< / div>'

.append('< div id =GM_ClearVisitListBtnclass =GM_ControlWrap>'
+'<访问过的链接。< / button>< / div>'
);
$('div.GM_ControlWrap')。hover(
function(){$(this).stop(true,false).fadeTo(50,1);},
function ){$(this).stop(true,false).fadeTo(900,0.8);} //与CSS协调。

// ---初始化链接处理程序对象,但要等到load事件。
var stateMachine;
window.addEventListener(load,function(){
stateMachine = new GM_LinkTrack(selectorStr,
'#GM_StartStopBtn button',
'#GM_ClearVisitListBtn button',
refreshDelay
);

/ * ---显示当前访问的链接数
我们只更新一次每页加载
* /
var numLinks = stateMachine.GetVisitedLinkCount();
$(body)。append('< p>用'+ numLinks +'访问的链接打开的页面。< / p& b $ b},
false
);


/ * ---链接和状态跟踪器对象。
公共方法:
OpenAllNewLinks()
StartStopBtnHandler()
ClearVisitedLinkList()
StartRefreshTimer();
StopRefreshTimer();
SetAllCurrentLinksToVisited()
GetVisitedLinkCount()
* /
function GM_LinkTrack(selectorStr,startBtnSel,clearBtnSel,refreshDelay)
{
var visitedLinkArry = [];
var numVisitedLinks = 0;
var refreshTimer = null;
var startTxt ='开始检查新链接。
var stopTxt ='停止检查链接和重新加载。

// ---从存储获取访问的链接列表。
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){
/ * ---如果链接是新的,将它添加到列表中并返回true。
否则返回false。
* /
if(visitedLinkArry.indexOf(href)== -1){
visitedLinkArry.push(href);

var itemName ='Visited_'+ numVisitedLinks;
localStorage.setItem(itemName,href);
numVisitedLinks ++;

return true;
}
return false;
}

// ---对于每个新链接,在单独的选项卡中打开它。
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; // - 这看起来比使用`.bind(this)`更清晰。
this.StartStopBtnHandler = function(zEvent){
if(inRefreshCycle){
// ---按下Stop。停止搜索新链接。
$(startBtnSel).text(startTxt);
context.StopRefreshTimer();
localStorage.setItem('inRefreshCycle','0'); //设置为false。
}
else {
// ---开始按。开始搜寻新连结。
$(startBtnSel).text(stopTxt);
localStorage.setItem('inRefreshCycle','1'); //设置为true。

context.SetAllCurrentLinksToVisited();
context.StartRefreshTimer();
}
inRefreshCycle ^ = true; // - 切换值。
};

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);
}
}
};

// ---激活按钮。
$(startBtnSel).click(this.StartStopBtnHandler);
$(clearBtnSel).click(this.ClearVisitedLinkList);

// ---确定状态。我们现在是否正在运行刷新周期?
var inRefreshCycle = parseInt(localStorage.inRefreshCycle,10)|| 0;
if(inRefreshCycle){
$(startBtnSel).text(stopTxt); // - 将btn标签改为停止。
this.OpenAllNewLinks();
this.StartRefreshTimer();
}
}

// ---设置控制按钮的样式。
GM_addStyle(\
.GM_ControlWrap {\
opacity:0.8; / *与悬停函数协调* / \
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按钮:hover {\
color:red; \
} \
#GM_StartStopBtn {\
top:0; \
left:0; \
} \
#GM_ClearVisitListBtn {\
bottom:0; \
right:0; \
} \
);


My aim is to detect the unvisited links on a webpage and then create a greasemonkey script to click on those links. By unvisited links here I mean the links which are not opened by me. Since I can see all the browser provide capability to change the color of visited and unvisited link is it possible to detect these links in any manner. While searching I came upon this link: http://www.mozdev.org/pipermail/greasemonkey/2005-November/006821.html but someone here told me that this is no longer possible. Please help.

解决方案

Correct, it is not possible for javascript to detect if a link is visited in either Firefox or Chrome -- which are the only 2 browsers applicable in this Greasemonkey context.

That is because Firefox and Chrome take security and privacy seriously. From the CSS2 spec:

Note. It is possible for style sheet authors to abuse the :link and :visited pseudo-classes to determine which sites a user has visited without the user's consent.

UAs may therefore treat all links as unvisited links, or implement other measures to preserve the user's privacy while rendering visited and unvisited links differently. See [P3P] for more information about handling privacy.

See also, "Privacy and the :visited selector"
You can see a demo showing that secure-ish browsers will not let you sniff visited links at jsfiddle.net/n8F9U.




For your specific situation, because you are visiting a page and keeping it open, you can help a script keep track of what links were visited. It's not fool-proof, but I believe it will do what you've asked for.

First, see the script in action by doing the following:

  1. Install the script, as is.
  2. Browse to the test page, jsbin.com/eledog.
    The test page adds a new link, every time it is reloaded or refreshed.
  3. The GM script adds 2 buttons to the pages it runs on. A "start/Stop" button in the upper left and a "Clear" button in the lower right.

    When you press the "Start" button, it does the following:

    1. All existing links on the page are logged as "visited".
    2. It starts a timer (default setting: 3 seconds), when the timer goes off, it reloads the page.
    3. Each time the page reloads, it opens any new links and kicks off a new reload-timer.
    4. Press the "Stop" button to stop the reloads, the list of visited links is preserved.

    The "Clear" button, erases the list of visited pages.
    WARNING: If you press "Clear" while the refresh loop is active, then the next time the page reloads, all links will be opened in new tabs.


Next, to use the script on your site...

Carefully read the comments in the script, you will have to change the @include, @exclude, and selectorStr values to match the site you are using.

For best results, disable any "Reload Every" add-ons, or "Autoupdate" options.


Important notes:

  1. The script has to use permanent storage to to track the links.
    The options are: cookies, sessionStorage, localStorage, globalStorage, GM_setValue(), and IndexedDB.

    These all have drawbacks, and in this case (single site, potentially huge number of links, multiple sessions), localStorage is the best choice (IndexedDB might be, but it is still too unstable -- causing frequent FF crashes on my machine).

    This means that links can only be tracked on a per-site basis, and that "security", "privacy", or "cleaner" utilities can block or erase the list of visited links. (Just like, clearing the browser's history will reset any CSS styling for visited links.)

  2. The script is Firefox-only, for now. It should not work on Chrome, even with Tampermonkey installed, without a little re-engineering.



The script:

/*******************************************************************************
**  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;                                              \
    }                                                                       \
" );

这篇关于如何检测页面上的已访问和未访问的链接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆