21

我之前问过如何在 Groovy 中做到这一点。但是,由于所有 CPAN 库,现在我正在用 Perl 重写我的应用程序。

如果页面包含这些链接:

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

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

输出将是:

谷歌,http://www.google.com
苹果,http://www.apple.com

在 Perl 中执行此操作的最佳方法是什么?

4

11 回答 11

41

请查看为此使用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,它甚至更简单。

Mech 基本上是一个对象中的浏览器。

于 2008-10-31T19:40:37.067 回答
11

查看HTML::LinkExtractorHTML::LinkExtor,它们是HTML::Parser包的一部分。

HTML::LinkExtractor 类似于 HTML::LinkExtor,除了获取 URL 之外,您还获取链接文本。

于 2008-10-31T17:59:17.223 回答
6

我喜欢将pQuery用于这样的事情......

use pQuery;

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

还可以查看之前的 stackoverflow.com 问题Emulation of lex like features in Perl or Python以获得类似的答案。

于 2008-10-31T18:49:26.780 回答
6

如果您喜欢冒险并且想尝试不使用模块,那么这样的事情应该可以工作(根据您的需要进行调整):

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

我可能在这里做错了几件事,但它在我编写后尝试的少数测试用例中有效(它不考虑 <img> 标签等)。

于 2012-06-04T20:39:14.977 回答
5

另一种方法是使用 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');
  }
于 2008-11-05T17:49:25.790 回答
4

Sherm推荐了HTML::LinkExtor,这几乎就是你想要的。不幸的是,它不能返回 <a> 标记内的文本。

安迪推荐WWW::Mechanize。这可能是最好的解决方案。

如果您发现 WWW::Mechanize 不符合您的喜好,请尝试HTML::TreeBuilder。它将从 HTML 中构建一个类似 DOM 的树,然后您可以搜索您想要的链接并提取您想要的任何附近的内容。

于 2008-10-31T19:47:11.687 回答
4

或者考虑增强 HTML::LinkExtor 以执行您想要的操作,并将更改提交给作者。

于 2008-11-02T02:43:11.503 回答
4

以前的答案非常好,我知道我迟到了,但这在 [perl] 提要中遇到了问题,所以......</p>

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>

–产量–</p>

     Google -> http://www.google.com
      Apple -> http://www.apple.com
于 2011-03-22T23:10:38.720 回答
3

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";
        }
    }
于 2013-09-13T12:19:04.157 回答
2

HTML 是一种结构化标记语言,必须对其进行解析才能准确无误地提取其含义。列出的模块 Sherm 将解析 HTML 并为您提取链接。如果您知道您的输入将始终以相同的方式形成(不要忘记属性),那么基于特殊正则表达式的解决方案可能是可以接受的,但解析器几乎总是处理结构化文本的正确答案。

于 2008-10-31T18:49:00.430 回答
-1

我们可以使用正则表达式来提取链接及其链接文本。这也是一种方式。

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>
于 2013-01-29T09:36:48.043 回答