我之前曾问过如何在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中执行此操作的最佳方法是什么?
答案 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::LinkExtractor和HTML::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>