Сортировать строки на веб-странице, используя javascript / regex - PullRequest
0 голосов
/ 11 октября 2009

Я хотел бы написать сценарий Greasemonkey, который требует поиска строк, заканчивающихся строкой («копий»), и сортировки этих строк по числу, предшествующему этой строке.

К сожалению, на странице, которую я хочу изменить, не используются таблицы, только тег br /, поэтому я предполагаю, что для этого потребуется Regex:

http://www.publishersweekly.com/article/CA6591208.html

(Строки без соответствующей строки будут просто игнорироваться.)

Буду благодарен за любые советы, которые помогут мне начать.

Ответы [ 3 ]

2 голосов
/ 11 октября 2009

В большинстве случаев HTML и RegEx не сочетаются друг с другом, и при разборе HTML вашей первой мыслью не должно быть RegEx.

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

Вот функция, которая извлекает данные, захватывает соответствующие строки, сортирует их и помещает обратно:
($ j - jQuery)

function reorderPwList()
{
    var Container = $j('#article span.table');

    var TargetLines = /^.+?(\d+(?:,\d{3})*) copies\.<br ?\/?>$/gmi

    var Lines = Container.html().match( TargetLines );

    Lines.sort( sortPwCopies );

    Container.html( Lines.join('\n') );


    function sortPwCopies()
    {
        function getCopyNum()
        { return arguments[0].replace(TargetLines,'$1').replace(/\D/g,'') }

        return getCopyNum(arguments[0]) - getCopyNum(arguments[1]);
    }
}

1011 *
*

И объяснение регулярного выражения, используемого там:

^           # start of line
.+?         # lazy match one or more non-newline characters
(           # start capture group $1
  \d+       # match one or more digits (0-9)
  (?:       # non-capture group
    ,\d{3}  # comma, then three digits
  )*        # end group, repeat zero or more times
)           # end group $1
 copies\.   # literal text, with . escaped
<br ?\/?>   # match a br tag, with optional space or slash just in case
$           # end of line

(Для удобства чтения я выделил группы - допустимы только пробелы перед «копиями» и после «br».)
Флаги регулярных выражений gmi используются для g lobal, m ulti-line mode, case- i чувствительного сопоставления.


<Ч />

<СТАРЫЙ ОТВЕТ>

После того, как вы извлекли только текст, который хотите просмотреть (используя DOM / jQuery), вы можете передать его следующей функции, которая поместит соответствующую информацию в формат, который затем можно будет отсортировать:

function makeSortable(Text)
{
    // Mark sortable lines and put number before main content.
    Text = Text.replace
        ( /^(.*)([\d,]+) copies\.<br \/>/gm
        , "SORT ME$2    $1"
        );

    // Remove anything not marked for sorting.
    Text = Text.replace( /^(?!SORT ME).*$/gm , '' );

    // Remove blank lines.
    Text = Text.replace( /\n{2,}/g , '\n' );

    // Remove sort token.
    Text = Text.replace( /SORT ME/g , '' );

    return Text;
}


Затем вам понадобится функция сортировки, чтобы убедиться, что числа отсортированы правильно (стандартный метод JS array.sort отсортирует текст и поместит 100 000 до 20 000).


О, и вот краткое объяснение регулярных выражений, используемых здесь:

/^(.*)([\d,]+) copies\.<br \/>/gm

/.../gm    a regex with global-match and multi-line modes
^          matches start of line
(.*)       capture to $1, any char (except newline), zero or more times
([\d,]+)   capture to $2, any digit or comma, one or more times
 copies    literal text
\.<br \/>  literal text, with . and / escaped (they would be special otherwise)


/^(?!SORT ME).*$/gm

/.../gm      again, enable global and multi-line
^            match start of line
(?!SORT ME)  a negative lookahead, fails the match if text 'SORT ME' is after it
.*           any char (except newline), zero or more times
$            end of line


/\n{2,}/g

\n{2,}    a newline character, two or more times

</ СТАРЫЙ ОТВЕТ>

1 голос
/ 12 октября 2009

вы можете начать с чего-то вроде этого (просто скопируйте в консоль firebug)

    // where are the things
    var elem = document.getElementById("article").
        getElementsByTagName("span")[1].
        getElementsByTagName("span")[0];

    // extract lines into array
    var lines = []
    elem.innerHTML.replace(/.+?\d+\s+copies\.\s*<br>/g,
       function($0) { lines.push($0) });

    // sort an array

//      lines.sort(function(a, b) {
//         var ma = a.match(/(\d+),(\d+)\s+copies/);
//         var mb = b.match(/(\d+),(\d+)\s+copies/);
//
//         return parseInt(ma[1] + ma[2]) - 
//              parseInt(mb[1] + mb[2]);

            lines.sort(function(a, b) {
                 function getNum(p) {
                     return parseInt(
                          p.match(/([\d,]+)\s+copies/)[1].replace(/,/g, ""));
                 }
                 return getNum(a) - getNum(b);
    })

    // put it back
    elem.innerHTML = lines.join("");
0 голосов
/ 11 октября 2009

Мне не ясно, что ты пытаешься сделать. При размещении вопросов здесь я призываю вас опубликовать (часть) ваши фактические данные и четко указать, что именно вы пытаетесь сопоставить.

Но, я полагаю, вы знаете очень мало регулярных выражений, в таком случае зачем вообще использовать регулярные выражения? Если вы немного изучите тему, вы скоро узнаете, что регулярное выражение - это не какой-то магический инструмент, который производит то, о чем вы думаете. Regex не может сортировать каким-либо образом. Это просто соответствует тексту, вот и все.

Посмотрите на этот превосходный онлайн-ресурс: http://www.regular -expressions.info /

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

Удачи.

...