Как я могу извлечь URL и текст ссылки из HTML в Perl? - PullRequest
20 голосов
/ 31 октября 2008

Ранее я спрашивал, как это сделать в Groovy. Однако теперь я переписываю свое приложение на Perl из-за всех библиотек CPAN.

Если на странице содержались следующие ссылки:

<a href="http://www.google.com">Google</a>

<a href="http://www.apple.com">Apple</a>

Вывод будет:

Google, http://www.google.com
Apple, http://www.apple.com

Каков наилучший способ сделать это в Perl?

Ответы [ 11 ]

40 голосов
/ 31 октября 2008

Пожалуйста, обратите внимание на использование модуля 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-адресам на этой странице, это еще проще.

Мех - это в основном браузер в объекте.

11 голосов
/ 31 октября 2008

Взгляните на HTML :: LinkExtractor и HTML :: LinkExtor , часть пакета HTML :: Parser .

HTML :: LinkExtractor аналогичен HTML :: LinkExtor, за исключением того, что помимо получения URL-адреса вы также получаете текст ссылки.

6 голосов
/ 05 июня 2012

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

#!/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";
}

Вероятно, здесь есть несколько вещей, которые я сделал неправильно, но это работает в нескольких тестовых примерах, которые я пробовал после написания (не учитываются такие вещи, как теги imageи т. Д.).

6 голосов
/ 31 октября 2008

Мне нравится использовать pQuery для подобных вещей ...

use pQuery;

pQuery( 'http://www.perlbuzz.com' )->find( 'a' )->each(
    sub {
        say $_->innerHTML . q{, } . $_->getAttribute( 'href' );
    }
);

Также проверьте этот предыдущий вопрос stackoverflow.com Эмуляция лексоподобных функций в Perl или Python для похожих ответов.

5 голосов
/ 05 ноября 2008

Другой способ сделать это - использовать 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');
  }
4 голосов
/ 23 марта 2011

Предыдущие ответы были очень хорошими, и я знаю, что опаздываю на вечеринку, но это натолкнулось на канал [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
4 голосов
/ 02 ноября 2008

Или рассмотрите возможность расширения HTML :: LinkExtor для выполнения своих задач и отправки изменений автору.

4 голосов
/ 31 октября 2008

Sherm рекомендуется HTML :: LinkExtor , что почти то, что вы хотите. К сожалению, он не может вернуть текст внутри тега .

Энди рекомендуется WWW :: Механизация . Это, наверное, лучшее решение.

Если вы считаете, что WWW :: Mechanize вам не нравится, попробуйте HTML :: TreeBuilder . Он создаст DOM-подобное дерево из HTML, в котором вы сможете затем искать нужные ссылки и извлекать любой ближайший контент, который хотите.

3 голосов
/ 13 сентября 2013

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";
        }
    }
2 голосов
/ 31 октября 2008

HTML - это язык структурированной разметки, который необходимо проанализировать, чтобы извлечь его значение без ошибок. Модуль Sherm, указанный в списке, проанализирует HTML и извлечет ссылки для вас. Специальные решения на основе регулярных выражений могут быть приемлемы, если вы знаете, что ваши входные данные всегда будут формироваться одинаково (не забывайте атрибуты), но парсер почти всегда является правильным ответом для обработки структурированного текста.

...