Как я могу извлечь URL и текст ссылки из HTML в Perl?
11 ответов
Пожалуйста, посмотрите на использование модуля WWW::Mechanize для этого. Он будет получать ваши веб-страницы для вас, а затем даст вам простой в работе со списками URL-адресов.
my $mech = WWW::Mechanize->new();
$mech->get( $some_url );
my @links = $mech->links();
for my $link ( @links ) {
printf "%s, %s\n", $link->text, $link->url;
}
Довольно просто, и если вы хотите перейти на другие URL на этой странице, это еще проще.
Мех - это в основном браузер в объекте.
Взгляните на HTML:: LinkExtractor и HTML:: LinkExtor, часть пакета HTML::Parser.
HTML:: LinkExtractor похож на HTML::LinkExtor, за исключением того, что помимо получения URL-адреса, вы также получаете текст ссылки.
Мне нравится использовать pQuery для подобных вещей...
use pQuery;
pQuery( 'http://www.perlbuzz.com' )->find( 'a' )->each(
sub {
say $_->innerHTML . q{, } . $_->getAttribute( 'href' );
}
);
Также просмотрите этот предыдущий вопрос stackru.com Эмуляция лексоподобных функций в Perl или Python для похожих ответов.
Если вы любите приключения и хотите попробовать без модулей, что-то вроде этого должно сработать (адаптируйте его под свои нужды):
#!/usr/bin/perl
if($#ARGV < 0) {
print "$0: Need URL argument.\n";
exit 1;
}
my @content = split(/\n/,`wget -qO- $ARGV[0]`);
my @links = grep(/<a.*href=.*>/,@content);
foreach my $c (@links){
$c =~ /<a.*href="([\s\S]+?)".*>/;
$link = $1;
$c =~ /<a.*href.*>([\s\S]+?)<\/a>/;
$title = $1;
print "$title, $link\n";
}
Вероятно, здесь есть несколько вещей, которые я сделал неправильно, но это работает в нескольких тестовых примерах, которые я пытался после написания (не учитывает такие вещи, как теги и т. Д.).
Другой способ сделать это - использовать XPath для запроса проанализированного HTML. Это необходимо в сложных случаях, таких как извлечение всех ссылок в div с определенным классом. Используйте HTML::TreeBuilder::XPath для этого.
my $tree=HTML::TreeBuilder::XPath->new_from_content($c);
my $nodes=$tree->findnodes(q{//map[@name='map1']/area});
while (my $node=$nodes->shift) {
my $t=$node->attr('title');
}
Шерм рекомендовал HTML:: LinkExtor, что почти то, что вы хотите. К сожалению, он не может вернуть текст внутри тега .
Энди порекомендовал WWW:: Mechanize. Это, наверное, лучшее решение.
Если вы обнаружите, что WWW:: Mechanize вам не по вкусу, попробуйте HTML:: TreeBuilder. Он построит дерево, похожее на DOM, из HTML-кода, в котором вы сможете затем искать нужные ссылки и извлекать любой ближайший контент, который хотите.
Или рассмотрите возможность расширения HTML::LinkExtor, чтобы делать то, что вы хотите, и отправки изменений автору.
Предыдущие ответы были очень хорошими, и я знаю, что опаздываю на вечеринку, но это натолкнулось на канал [perl], так что…
XML:: LibXML отлично подходит для разбора HTML и непревзойденна по скорости. Задавать recover
опция при разборе плохо сформированного HTML.
use XML::LibXML;
my $doc = XML::LibXML->load_html(IO => \*DATA);
for my $anchor ( $doc->findnodes("//a[\@href]") )
{
printf "%15s -> %s\n",
$anchor->textContent,
$anchor->getAttribute("href");
}
__DATA__
<html><head><title/></head><body>
<a href="http://www.google.com">Google</a>
<a href="http://www.apple.com">Apple</a>
</body></html>
-yields-
Google -> http://www.google.com
Apple -> http://www.apple.com
HTML::LinkExtractor лучше, чем HTML::LinkExtor
Он может дать как текст ссылки, так и URL.
Использование:
use HTML::LinkExtractor;
my $input = q{If <a href="http://apple.com/"> Apple </a>}; #HTML string
my $LX = new HTML::LinkExtractor(undef,undef,1);
$LX->parse(\$input);
for my $Link( @{ $LX->links } ) {
if( $$Link{_TEXT}=~ m/Apple/ ) {
print "\n LinkText $$Link{_TEXT} URL $$Link{href}\n";
}
}
HTML - это язык структурированной разметки, который необходимо проанализировать, чтобы извлечь его значение без ошибок. Модуль Sherm, указанный в списке, проанализирует HTML и извлечет ссылки для вас. Специальные решения на основе регулярных выражений могут быть приемлемы, если вы знаете, что ваши входные данные всегда будут формироваться одинаково (не забывайте атрибуты), но синтаксический анализатор почти всегда является правильным ответом для обработки структурированного текста.
Мы можем использовать регулярное выражение для извлечения ссылки с ее текстом ссылки. Это тоже один из способов.
local $/ = '';
my $a = <DATA>;
while( $a =~ m/<a[^>]*?href=\"([^>]*?)\"[^>]*?>\s*([\w\W]*?)\s*<\/a>/igs )
{
print "Link:$1 \t Text: $2\n";
}
__DATA__
<a href="http://www.google.com">Google</a>
<a href="http://www.apple.com">Apple</a>