【问题标题】:Extracting links inside <div>'s with HTML::TokeParser & URI使用 HTML::TokeParser & URI 提取 <div> 中的链接
【发布时间】:2012-04-06 21:20:29
【问题描述】:

我是 Perl 的老新手,我正在尝试使用 HTML::TokeParser 和 URI 在 perl 中创建一个子例程。

我需要提取包含在名为“zone-extract”的 div 中的所有有效链接

这是我的代码:

#More perl above here... use strict and other subs
use HTML::TokeParser;
use URI;
sub extract_links_from_response {
my $response = $_[0];

my $base = URI->new( $response->base )->canonical;
# "canonical" returns it in the one "official" tidy form

my $stream = HTML::TokeParser->new( $response->content_ref );
my $page_url = URI->new( $response->request->uri );

print "Extracting links from: $page_url\n";

my($tag, $link_url);

while ( my $div = $stream->get_tag('div') ) {

   my $id = $div->get_attr('id');
   next unless defined($id) and $id eq 'zone-extract';

      while( $tag = $stream->get_tag('a') ) {
      next unless defined($link_url = $tag->[1]{'href'});
      next if $link_url =~ m/\s/; # If it's got whitespace, it's a bad URL.
      next unless length $link_url; # sanity check!

      $link_url = URI->new_abs($link_url, $base)->canonical;
      next unless $link_url->scheme eq 'http'; # sanity

      $link_url->fragment(undef); # chop off any "#foo" part

      print $link_url unless $link_url->eq($page_url); # Don't note links to itself!
  }
}
  return;
}

如您所见,我有 2 个循环,首先使用 get_tag 'div',然后查找 id = 'zone-extract'。第二个循环查看这个 div 内部并检索所有链接(或者这是我的意图)......

内部循环有效,它提取所有链接正确独立工作,但我认为第一个循环内部存在一些问题,正在寻找我想要的 div 'zone-extract'.. . 我用这篇文章作为参考:How can I find the contents of a div using Perl's HTML modules, if I know a tag inside of it?

但我现在只有这个错误:

Can't call method "get_attr" on unblessed reference

一些想法?帮助! 我的 HTML(注意 URL_TO_EXTRACT_1 和 2):

<more html above here>
<div class="span-48 last">
<div class="span-37">
    <div id="zone-extract" class="...">
        <h2 class="genres"><img alt="extracting" class="png"></h2>  
                    <li><a title="Extr 2" href="**URL_TO_EXTRACT_1**">2</a></li>
                    <li><a title="Con 1" class="sel" href="**URL_TO_EXTRACT_2**">1</a></li>
            <li class="first">Pàg</li>
    </div>
</div>      
</div>
<more stuff from here>

【问题讨论】:

  • 首先,始终始终 use strictuse warnings。每一个。单身的。时间。因此,启用strictwarnings,在您尝试使用get_attr 之前,添加以下内容:use Data::Dumper;print Dumper($div) . "\n"; 看看会发生什么。
  • 嗨,杰克,感谢您的回复。我使用严格和警告,这段代码只是一个子程序。我会试试数据转储器谢谢

标签: perl


【解决方案1】:

我发现 TokeParser 是一个非常粗糙的工具,需要太多的代码,它的缺点是只支持程序风格的编程。

由于声明式编程而需要更少代码的更好的替代方案是Web::Query

use Web::Query 'wq';
my $results = wq($response)->find('div#zone-extract a')->map(sub {
    my (undef, $elem_a) = @_;
    my $link_url = $elem_a->attr('href');
    return unless $link_url && $link_url !~ m/\s/ && …
    # Further checks like in the question go here.

    return [$link_url => $elem_a->text];
});

代码未经测试,因为问题中没有示例 HTML。

【讨论】:

  • 您好,谢谢 daxim。我已经下载并安装了网络查询,它看起来非常强大,但我无法让它工作......我现在正在努力。我还在我的问题中包含了一个 html 示例以获取更多详细信息
猜你喜欢
  • 2015-06-14
  • 1970-01-01
  • 1970-01-01
  • 2013-07-19
  • 2012-04-04
  • 2013-09-18
  • 2012-07-07
  • 2023-03-16
相关资源
最近更新 更多