簡體   English   中英

如何檢測頁面上已訪問和未訪問的鏈接?

[英]How can I detect visited and unvisited links on a page?

我的目的是檢測網頁上未訪問的鏈接,然后創建一個acobsmonkey腳本來單擊那些鏈接。 這里的未訪問鏈接是指我沒有打開的鏈接。 由於我可以看到所有瀏覽器都提供了更改已訪問和未訪問鏈接的顏色的功能,因此有可能以任何方式檢測到這些鏈接。 在搜索時,我遇到了以下鏈接: http : //www.mozdev.org/pipermail/greasemonkey/2005-November/006821.html,但是這里有人告訴我這不再可能。 請幫忙。

正確,JavaScript無法檢測是在Firefox還是Chrome中訪問了鏈接-這是在此Greasemonkey上下文中僅適用的兩種瀏覽器。

這是因為Firefox和Chrome十分重視安全性和隱私性。 根據CSS2規范

注意。 樣式表作者可能會濫用:link和:visited偽類來確定用戶未經用戶同意訪問了哪些站點。

因此,UA可以將所有鏈接視為未訪問的鏈接,或實施其他措施來保護用戶的隱私,同時以不同的方式呈現已訪問和未訪問的鏈接。 有關處理隱私的更多信息,請參見[P3P]。

另請參見“隱私和:visited選擇器”
您可以在jsfiddle.net/n8F9U上看到一個演示,該演示顯示安全的瀏覽器不允許您嗅探訪問的鏈接。




對於您的特定情況 ,因為您正在訪問頁面並保持打開狀態,所以可以幫助腳本跟蹤訪問了哪些鏈接。 它不是萬無一失的,但我相信它會滿足您的要求。

首先,執行以下操作查看正在使用的腳本

  1. 按原樣安裝腳本。
  2. 瀏覽到測試頁面jsbin.com/eledog
    每次重新加載或刷新時,測試頁都會添加一個新鏈接。
  3. GM腳本在其運行的頁面上添加了2個按鈕。 左上方的“開始/停止”按鈕和右下方的“清除”按鈕。

    當您按下“開始”按鈕時,它將執行以下操作:

    1. 頁面上所有現有的鏈接都記錄為“已訪問”。
    2. 它啟動一個計時器(默認設置:3秒),當計時器關閉時,它將重新加載頁面。
    3. 每次頁面重新加載時,它都會打開所有新鏈接並啟動新的重新加載計時器。
    4. 按下“停止”按鈕停止重新加載,已訪問鏈接的列表被保留。

    “清除”按鈕清除已訪問頁面的列表。
    警告:如果在刷新循環處於活動狀態時按“清除”,則下次重新加載頁面時, 所有鏈接都將在新選項卡中打開。


接下來, 使用您網站上的腳本 ...

仔細閱讀腳本中的注釋,您將必須更改@include @exclude@include @excludeselectorStr值以匹配您正在使用的站點。

為了獲得最佳結果,請禁用所有“重新加載所有”加載項或“自動更新”選項。


重要筆記:

  1. 該腳本必須使用永久性存儲來跟蹤鏈接。
    選項包括:Cookies, sessionStoragelocalStorageglobalStorageGM_setValue()IndexedDB

    所有這些都有缺點,在這種情況下(單個站點,潛在的大量鏈接,多個會話), localStorage是最佳選擇( IndexedDB可能是,但它仍然太不穩定-導致我的計算機頻繁發生FF崩潰)。

    這意味着只能在每個站點上跟蹤鏈接,並且“安全”,“隱私”或“更干凈”的實用程序可以阻止或刪除已訪問鏈接的列表。 (就像清除瀏覽器的歷史記錄一樣,將重置訪問鏈接的所有CSS樣式。)

  2. 目前,該腳本僅適用於Firefox。 即使不進行任何重新設計,即使安裝了Tampermonkey,它也不能在Chrome上運行。



劇本:

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

您可以解析頁面上的所有鏈接並獲取其CSS color屬性。 如果鏈接的顏色與您在CSS中定義的未訪問鏈接的顏色相匹配,則此鏈接不會被訪問。

這種技術通常用於確定所有訪問的鏈接。 這是一種安全漏洞,可讓您確定用戶是否訪問了特定網站。 通常由卑鄙的商人使用。

這種技巧通常被歸類為“瀏覽器的歷史操作技巧”。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM