-1

我正在处理一些 html 文档,每个文档都有一个链接列表,每个链接在打开时都有另一个链接列表,但是,每个链接列表可能有来自另一个列表的链接,我有一个哈希数组,其中只有一个链接一开始my %list = ($link1 => 1);,到目前为止,我所做的是打开现有链接并循环遍历 html 文档中的所有链接(以下代码显示已解析链接的 html 内容的变量 $tree):

for my $node ( $tree->look_down('_tag' => 'a'))
{
next unless $node;

my $link = $node->attr('href');
unless(exists($list{$link}))
{
    $list{$link} = 1;
}
}       

现在我想做的是循环遍历哈希表,因为每次出现新链接时都会输入它。

我希望我已经清楚了。

编辑 :

是我从中获取链接的页面,当从列表中选择一个链接时,有时会在另一个列表中找不到链接,因此为确保我拥有来自不同列表的所有链接,我打开每个链接并循环遍历列表,当有新链接时,我将其添加到哈希数组中。

更清楚地说,我的算法如下:

  • 我有一个带有一个链接的哈希表my %list = ($link1 => 1);,值 1 表示该链接尚未打开,因此,我仍然没有检查它拥有的链接列表。
  • 一旦我得到了链接列表,我就循环遍历它并检查哈希数组是否没有我循环遍历的链接之一
  • 一旦我完成了上述列表的循环,我打开的第一个链接将更新为 2$list{$link}=2并传递到哈希表中的以下链接(请记住,每次找到新链接时都会输入哈希数组)

提前致谢

4

1 回答 1

3

您似乎想构建一个爬虫,并避免访问任何链接两次。因此,您正在将访问过的链接添加到哈希中。它是否正确?

您的问题似乎是您在实际访问它们之前将新链接添加到看到的链接,因此很难再次找到它们。在这种情况下,哈希是错误的数据结构。使用散列来注册看到的链接(为了避免重复),但对未访问的链接队列使用数组:

my @queue = ('http://www.example.com/');     # start with at least one link in the queue
my %seen = ('http://www.example.com/' => 1); # this link is "known"

# look at the next link in the queue
while (defined(my $url = shift @queue)) {
  my $tree = some_magic($url);

  # 1. extract all <a>s
  # 2. extract the href value, skipping <a>s that don't have a href
  # 3. add them to the queue if not yet seen
  for my $link ($tree->look_down(...)) {
    my $href = $link->attr('href');
    next unless length $href;
    next if $seen{$href};

    $seen{$href} = 1;
    push @queue, $href;
  }
}

内循环也可以写成

push @queue,
  grep { length($_) and not $seen{$_}++ }
  map  { $_->('href') }
  $tree->look_down(...);

还有一些遗留问题:

  • 有些 URL 看起来可能不同,但它们是等效的。例如,空间通常被编码为+or %20。规范化 URL 以避免这种情况。
  • URL 可以有一个#foo不传输到服务器的片段部分。如果您已经看到 URL,您可能应该在测试之前删除该片段。
  • 用请求敲击服务器是不礼貌的。sleep每次请求之间间隔几秒钟比较好。
  • 互联网是一个广阔的地方。您可能应该限制搜索的深度,并将其与 URL 一起记录在@queue

    my @queue = (['http://www.example.com/', 5]); # start with depth 5
    ...
    while(my $item = shift @queue) {
      my ($url, $depth) = @$item;
      ...
      $seen{$href} = 1;
      next if $depth <= 0;
      push @queue, [$href, $depth-1];
      ...
    }
    
于 2013-09-27T14:30:58.703 回答