Как я могу надежно проанализировать профиль игрока QuakeLive, используя Perl? - PullRequest
3 голосов
/ 05 октября 2010

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

Я использовал для этого регулярные выражения, и они работают для всего, кроме любимой арены, оружия и типа игры. Мне просто нужно получить имена этих трех элементов в $ 1 для дальнейшей обработки.

Я пытался переформулировать изображение в избранном, но безуспешно. Если это хоть что-то используется, я уже использую WWW :: Mechanize в скрипте.

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

Вы можете найти пример профиля ЗДЕСЬ .

Обратите внимание, что для предыдущей части страницы она работала с использованием кода, подобного следующему:

$content =~ /<b>Wins:<\/b> (.*?)<br \/>/;
$wins = $1;
print "Wins: $wins\n";

Ответы [ 2 ]

7 голосов
/ 05 октября 2010

Непосредственной проблемой является то, что у вас есть:

<p class="prf_faves">
<img src="http://cdn.quakelive.com/web/2010092807/images/profile/none_v2010092807.0.gif" 
     width="17" height="17" alt="" class="fl fivepxhr" />
                <b>Arena:</b> Campgrounds
                <div class="cl"></div>
            </p>

То есть, после значения для избранного, такого как Arena , нет значения <br />. Теперь правильный способ сделать это - использовать правильный HTML-парсер. Хрупкое решение состоит в том, чтобы адаптировать ваш шаблон (не проверено):

my ($favarena) = $content =~ m{<b>Arena:</b> ([^<]+)};

Это должно положить все до < следующего <div> в $favarena. Теперь, если все арены являются отдельными словами без пробелов,

my ($favarena) = $content =~ m{<b>Arena:</b> (\S+)};

избавит вас от необходимости урезать пробелы впоследствии.

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

<p class="prf_faves">
<img src="http://cdn.quakelive.com/web/2010092807/images/profile/none_v2010092807.0.gif" 
     width="17" height="17" alt="" class="fl fivepxhr" />
<!-- <b>Arena: </b> here -->
                <b>Arena:</b> Campgrounds
                <div class="cl"></div>
            </p>

Ваш скрипт будет в затруднении, если решение с использованием парсера HTML не будет.

Пример использования HTML :: TokeParser :: Simple :

#!/usr/bin/perl

use strict; use warnings;

use HTML::TokeParser::Simple;

my $p = HTML::TokeParser::Simple->new( 'martianbuddy.html' );

while ( my $tag = $p->get_tag('p') ) {
    next unless $tag->is_start_tag;
    next unless defined (my $class = $tag->get_attr('class'));
    next unless grep { /^prf_faves\z/ } split ' ', $class;

    my $fav = $p->get_tag('b');
    my $type = $p->get_text('/b');
    my $value = $p->get_text('/p');
    $value =~ s/\s+\z//;

    print "$type = $value\n";
}

Выход:

Arena:  Campgrounds
Game Type:  Clan Arena
Weapon:  Rocket Launcher

И вот пример использования HTML :: TreeBuilder :

#!/usr/bin/perl

use strict; use warnings;

use HTML::TreeBuilder;
use YAML;

my $tree = HTML::TreeBuilder->new;
$tree->parse_file('martianbuddy.html');

my @p = $tree->look_down(_tag => 'p', sub {
        return unless defined (my $class = $_[0]->attr('class'));
        return unless grep { /^prf_faves\z/ } split ' ', $class;
        return 1;
    }
);

for my $p ( @p ) {
    my $text = $p->as_text;
    $text =~ s/^\s+//;
    my ($type, $value) = split ': ', $text;
    print "$type: $value\n";
}

Выход:

Arena: Campgrounds 
Game Type: Clan Arena 
Weapon: Rocket Launcher

Учитывая, что документ является фрагментом HTML, а не полным документом, вы будете более успешны с модулями, основанными на HTML :: Parser , а не с модулями, которые рассчитаны на работу с правильно сформированными документами XML.

5 голосов
/ 05 октября 2010

Использование регулярных выражений для этой конкретной задачи далеко не идеально. Есть слишком много вещей, которые могут измениться, и вы не пользуетесь встроенной структурой HTML-страниц. Рассматривали ли вы использовать что-то вроде HTML::TreeBuilder вместо этого? Это позволит вам сказать «найдите мне значение 3-й ячейки таблицы в таблице с именем оружия» и т. Д.

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