如何在Perl中从HTML中提取URL和链接文本?

时间:2008-10-31 17:45:35

标签: html perl parsing url cpan

我之前曾问过如何在Groovy中执行此操作。但是,由于所有的CPAN库,现在我在Perl中重写我的应用程序。

如果页面包含以下链接:

<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 个答案:

答案 0 :(得分:40)

请查看使用WWW::Mechanize模块。它会为您提取您的网页,然后让您轻松使用网址列表。

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;
}

非常简单,如果您希望导航到该页面上的其他网址,则更简单。

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

答案 1 :(得分:11)

查看HTML::LinkExtractorHTML::LinkExtor HTML::Parser包的一部分。

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

答案 2 :(得分:6)

我喜欢使用pQuery来做这样的事情......

use pQuery;

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

同样请查看此之前的stackoverflow.com问题Emulation of lex like functionality in Perl or Python以获得类似的答案。

答案 3 :(得分: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";
}

这里可能有一些我做错的事情,但它在我编写的一些测试用例中起作用(它没有考虑像&lt; img&gt;标签之类的东西等)。

答案 4 :(得分: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');
  }

答案 5 :(得分:4)

Sherm推荐HTML::LinkExtor,这几乎就是您想要的。不幸的是,它无法返回&lt; a&gt;内的文字。标签

Andy建议WWW::Mechanize。这可能是最好的解决方案。

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

答案 6 :(得分:4)

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

答案 7 :(得分:4)

之前的答案非常好,我知道我迟到了,但是这个[perl]提示已经受到了影响......

XML::LibXML非常适合HTML解析,并且速度无与伦比。解析格式错误的HTML时设置recover选项。

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

答案 8 :(得分:3)

HTML::LinkExtractor比HTML :: LinkExtor

更好

它可以同时提供链接文字和网址。

用法:

 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";
        }
    }

答案 9 :(得分:2)

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

答案 10 :(得分:-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>