Как извлечь элемент HTML на основе его класса?
Я только начинаю в Perl и написал простой script, чтобы сделать некоторые веб-скребки. Я использую WWW:: Mechanize и HTML:: TreeBuilder, чтобы выполнить большую часть работы, но у меня возникли проблемы. У меня есть следующий HTML:
<table class="winsTable">
<thead>...</thead>
<tbody>
<tr>
<td class = "wins">15</td>
</tr>
</tbody>
</table>
Я знаю, что есть некоторые модули, которые получают данные из таблиц, но это особый случай; не все данные, которые я хочу, находятся в таблице. Итак, я попробовал:
my $tree = HTML::TreeBuilder->new_from_url( $url );
my @data = $tree->find('td class = "wins"');
Но @data
возвращается пустым. Я знаю, что этот метод будет работать без имени класса, потому что я успешно проанализировал данные с помощью $tree->find('strong')
. Итак, есть ли модуль, который может обрабатывать этот тип синтаксиса HTML? Я просмотрел документацию HTML:: TreeBuilder и не нашел ничего, что появилось, но я мог ошибаться.
Ответы
Ответ 1
Я использую отличный (но иногда немного медленный) модуль HTML::TreeBuilder::XPath
:
my $tree = HTML::TreeBuilder::XPath->new_from_content( $mech->content() );
my @data = $tree->findvalues('//table[ @class = "winsTable" ]//td[@class = "wins"]');
Ответ 2
Вы можете использовать метод look_down
для поиска определенного тега и атрибутов, которые вы ищете. Это находится в модуле HTML::Element
(который импортируется HTML::TreeBuilder
).
my $data = $tree->look_down(
_tag => 'td',
class => 'wins'
);
print $data->content_list, "\n" if $data; #prints '15' using the given HTML
$data = $tree->look_down(
_tag => 'td',
class => 'losses'
);
print $data->content_list, "\n" if $data; #prints nothing using the given HTML
Ответ 3
(Это своего рода дополнительный ответ dspain)
На самом деле вы пропустили место в документации HTML:: TreeBuilder, где говорится:
Объекты этого класса наследуют методы как HTML:: Parser, так и HTML:: Element. Методы, унаследованные от HTML:: Parser, используются для построения дерева HTML, а методы, унаследованные от HTML:: Element, - это то, что вы используете для тщательного изучения дерева. Помимо этой (HTML:: TreeBuilder) документации, вы также должны внимательно прочитать документацию HTML:: Element, а также снять документацию HTML:: Parser - возможно, интересны только ее методы синтаксического анализа и parse_file.
(Обратите внимание, что полужирное форматирование принадлежит мне, это не в документации)
Это означает, что вы должны читать документацию HTML:: Element, где вы найдете find
метод, в котором говорится
Это просто псевдоним find_by_tag_name
Это должно сказать вам, что оно не работает для имен классов, но в его описании также упоминается метод look_down
, который может быть немного ниже. Если вы посмотрите на пример, вы увидите, что он делает то, что вы хотите. И dspain answer показывает, как именно в вашем случае.
Справедливости ради, документация не так просто ориентироваться.
Ответ 4
Я нашел ссылку this наиболее полезной, рассказывая мне, как извлекать конкретную информацию из html-контента. Я использовал последний пример на странице:
use v5.10;
use WWW::Mechanize;
use WWW::Mechanize::TreeBuilder;
my $mech = WWW::Mechanize->new;
WWW::Mechanize::TreeBuilder->meta->apply($mech);
$mech->get( 'http://htmlparsing.com/' );
# Find all <h1> tags
my @list = $mech->find('h1');
# or this way <----- I found this way very useful to pinpoint exact classes with in some html
my @list = $mech->look_down('_tag' => 'h1',
'class' => 'main_title');
# Now just iterate and process
foreach (@list) {
say $_->as_text();
}
Казалось, что гораздо проще вставать и работать, чем любой из других модулей, на которые я смотрел. Надеюсь, это поможет!