Извлечение ссылок в Perl с помощью TreeBuilder

Я работаю над скриптом, чтобы извлечь кучу информации в один файл HTML. Однако у меня возникли трудности с извлечением ТОЛЬКО определенного набора ссылок с рассматриваемой страницы.

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

<div id="innercontent">
<h1>Download here</h1>
<a href="website.pdf"><img src="stuff"></a>
</div>

Теперь в идентификаторе div «внутреннее содержимое» найдено несколько ссылок, поэтому я ищу способ либо сопоставить строку, либо иным образом получить только те ссылки, которые мне нужны. Имейте в виду, что все ссылки, которые я хочу получить, будут в формате .pdf, так что, возможно, это может вам помочь. Я почти уверен, что TreeBuilder справится с этим, основываясь на проведенном мной исследовании. Вот два метода, которые я пытаюсь использовать. Я бы предпочел решить это, используя первый.

# link to pdf of transcript
for ( $mech->look_down(_tag => 'a') ) {
  next unless $_->as_trimmed_text =~ m/pdf/;
  say $_->as_HTML;
}

my @links = $mech->links();
  for my $link ( @links ) {
  print $link->url;
}

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

Любая помощь или совет будут очень признательны!


person MikeEMKI    schedule 10.09.2015    source источник


Ответы (2)


WWW::Mechanize имеет возможность извлекать ссылки на основе нескольких атрибутов, таких как текст, отображаемый для ссылки, фактическая ссылка или идентификатор.

Для вашего конкретного примера вы должны получить ссылки в формате pdf с помощью:

my @links = $mech->find_all_links(url_regex=>qr/\.pdf$/)

а затем делайте все, что вам нужно, с полученным массивом.

Вы можете ознакомиться с документацией. И этот документ покажет вам доступные варианты.

person Trenton Trama    schedule 10.09.2015
comment
Я думаю, что это очень разумный вариант, если вы уже используете мех. - person Joe McMahon; 11.09.2015
comment
Благодарю вас! Кто-то дал вам -1, хотя это было решение, которое я искал, поэтому я проголосую за это и назову его решением. - person MikeEMKI; 11.09.2015
comment
Это не проверяет, что найденный элемент a находится в пределах div с id из innercontent - person Borodin; 11.09.2015

Используя HTML::TreeBuilder, вы должны сделать два последовательных вызова tro ​​look_down. Первый, чтобы найти div элементов с атрибутом id, равным innercontent, и второй, чтобы найти внутри этих элементов, чтобы найти a элементов с атрибутом href, значение которого заканчивается на .pdf

Это выглядит так

use strict;
use warnings;

use HTML::TreeBuilder;

my $html = <<END;
<div id="innercontent">
<h1>Download here</h1>
<a href="website.pdf"><img src="stuff"></a>
</div>
END

my $tree = HTML::TreeBuilder->new_from_content($html);

for my $div ( $tree->look_down(_tag => 'div', id => 'innercontent') ) {
    my @anchors = $div->look_down(_tag => 'a', href => qr/\.pdf\z/i );
    print $_->attr('href'), "\n" for @anchors;
}

выход

website.pdf

Мне нравится Mojo::DOM для этого, так как он позволяет использовать простые методы доступа CSS и позволяет очень лаконично решать проблемы.

Вот решение, использующее этот модуль. Вывод идентичен решению выше

use strict;
use warnings;

use Mojo::DOM;

my $html = <<END;
<div id="innercontent">
<h1>Download here</h1>
<a href="website.pdf"><img src="stuff"></a>
</div>
END

my $dom = Mojo::DOM->new($html);

for my $anchor ( $dom->find('div#innercontent a[href]')->each ) {
    my $href = $anchor->attr('href');
    print "$href\n" if $href =~ /\.pdf\z/i;
}
person Borodin    schedule 11.09.2015