Как я могу обнаружить посещенные и не посещенные ссылки на странице? - PullRequest
18 голосов
/ 03 сентября 2011

Моя цель - обнаружить не посещенные ссылки на веб-странице, а затем создать сценарий greasemonkey, чтобы щелкнуть по этим ссылкам. Под непосещенными ссылками здесь я имею в виду ссылки, которые я не открывал. Поскольку я вижу, что все браузеры предоставляют возможность изменять цвет посещенной и не посещенной ссылки, можно ли обнаружить эти ссылки любым способом. При поиске я наткнулся на эту ссылку: http://www.mozdev.org/pipermail/greasemonkey/2005-November/006821.html, но кто-то здесь сказал мне, что это больше невозможно. Пожалуйста, помогите.

Ответы [ 2 ]

21 голосов
/ 03 сентября 2011

Правильно, для javascript невозможно определить, посещена ли ссылка в Firefox или Chrome, которые являются единственными 2 браузерами, применимыми в этом контексте Greasemonkey .

Этопотому что Firefox и Chrome серьезно относятся к безопасности и конфиденциальности.От спецификация CSS2 :

Примечание.Авторы таблиц стилей могут использовать псевдоклассы: link и: visit, чтобы определить, какие сайты посетил пользователь без согласия пользователя.

Таким образом, UA могут обрабатывать все ссылки как непосещенные ссылки или внедрять другие.меры по сохранению конфиденциальности пользователя при различном отображении посещенных и не посещенных ссылок.См. [P3P] для получения дополнительной информации о конфиденциальности.

См. Также, "Конфиденциальность и селектор посещений"
Вы можете увидеть демонстрацию, показывающую, что браузеры secure-ish не позволят вам прослушивать посещенные ссылки на jsfiddle.net / n8F9U .




Для вашей конкретной ситуации , поскольку вы посещаете страницу и держите ее открытой, вы можете помочьскрипт отслеживания того, какие ссылки были посещены.Это не защищает от ошибок, но я верю, что это сделает то, о чем вы просили.

Сначала посмотрите сценарий в действии , выполнив следующее:

  1. Установите скрипт, как есть.
  2. Перейдите на тестовую страницу, jsbin.com / eledog .
    Тестовая страница добавляет новую ссылку при каждой перезагрузке илиобновлен.
  3. Сценарий GM добавляет 2 кнопки к страницам, на которых он работает.Кнопка «Пуск / Стоп» в левом верхнем углу и кнопка «Очистить» в правом нижнем углу.

    При нажатии кнопки «Пуск» выполняется следующее:

    1. Все существующие ссылки на странице регистрируются как «посещенные».
    2. Запускает таймер (настройка по умолчанию: 3 секунды), когда таймер выключается, он перезагружает страницу.
    3. КаждаяКогда страница перезагружается, она открывает все новые ссылки и запускает новый таймер перезагрузки.
    4. Нажмите кнопку «Стоп», чтобы остановить перезагрузку, список посещенных ссылок сохраняется.

    Кнопка «Очистить» стирает список посещенных страниц.
    ВНИМАНИЕ: Если вы нажмете «Очистить», когда активен цикл обновления, то в следующий разстраница перезагрузится, все ссылки будут открыты в новых вкладках.


Далее, для использования скрипта наваш сайт ...

Внимательно прочитайте комментарии в сценарии, вам придется изменить значения @include, @exclude и selectorStr, чтобы они соответствовали сайту, который вы используете.

Для достижения наилучших результатов отключите все надстройки «Перезагрузить каждый» или «Автообновление».


Важные примечания:

  1. Скрипт должен использовать постоянное хранилище для отслеживания ссылок.
    Возможны следующие варианты: куки, sessionStorage, localStorage, globalStorage, GM_setValue() и IndexedDB.

    Все они имеют недостатки, и в этом случае (один сайт, потенциально огромное количество ссылок, несколько сеансов), localStorage являетсялучший выбор (IndexedDB может быть, но он все еще слишком нестабилен - вызывает частые сбои FF на моем компьютере).

    Это означает, что ссылки могут отслеживаться только для отдельных сайтов, и это "Утилиты безопасности, конфиденциальности и очистки могут блокировать или стирать список посещенных ссылок.(Точно так же, очистка истории браузера сбросит любой стиль CSS для посещенных ссылок.)

  2. На данный момент скрипт предназначен только для Firefox.Он не должен работать на Chrome, даже с установленным Tampermonkey, без небольшой доработки.



Сценарий:

/*******************************************************************************
**  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;                                              \
    }                                                                       \
" );
0 голосов
/ 18 января 2013

Вы можете проанализировать все ссылки на странице и получить их свойство цвета CSS.Если цвет ссылки соответствует цвету непосещенной ссылки, определенной вами в CSS, эта ссылка не посещается.

Этот метод обычно используется для определения всех посещенных ссылок.Это своего рода нарушение безопасности, позволяющее определить, посетил ли пользователь определенный веб-сайт.Обычно используется подлыми маркетологами.

Этот вид трюков обычно классифицируется как «трюки с манипуляцией с историей браузера».

Дополнительная информация с кодом: http://www.stevenyork.com/tutorial/getting_browser_history_using_javascript

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...