【问题标题】:Web crawler using perl使用 perl 的网络爬虫
【发布时间】:2015-03-14 09:39:27
【问题描述】:

我想开发一个网络爬虫,它从种子 URL 开始,然后爬取它发现的 100 个与种子 URL 属于同一域的 html 页面,并记录遍历的 URL 以避免重复。我编写了以下内容,但 $url_count 值似乎没有增加,并且检索到的 URL 甚至包含来自其他域的链接。我该如何解决这个问题?在这里,我插入了 stackoverflow.com 作为我的起始 URL。

use strict;
use warnings;

use LWP::Simple;
use LWP::UserAgent;
use HTTP::Request;
use HTTP::Response;


##open file to store links
open my $file1,">>", ("extracted_links.txt");
select($file1); 

##starting URL
my @urls = 'http://stackoverflow.com/';

my $browser = LWP::UserAgent->new('IE 6');
$browser->timeout(10);
my %visited;
my $url_count = 0;


while (@urls) 
{
     my $url = shift @urls;
     if (exists $visited{$url}) ##check if URL already exists
     {
         next;
     }
     else
     {
         $url_count++;
     }         

     my $request = HTTP::Request->new(GET => $url);
     my $response = $browser->request($request);

     if ($response->is_error()) 
     {
         printf "%s\n", $response->status_line;
     }
     else
     {
         my $contents = $response->content();
         $visited{$url} = 1;
         @lines = split(/\n/,$contents);
         foreach $line(@lines)
         {
             $line =~ m@(((http\:\/\/)|(www\.))([a-z]|[A-Z]|[0-9]|[/.]|[~]|[-_]|[()])*[^'">])@g;
             print "$1\n";  
             push @urls, $$line[2];
         }

         sleep 60;

         if ($visited{$url} == 100)
         {
            last;
         }
    }
}

close $file1;

【问题讨论】:

  • 查看此链接以获取链接的根域名并将其与您的初始 URL 的根域进行比较:stackoverflow.com/questions/15627892/…
  • 既然您要提取 URL 和链接,请开始使用 WWW::Mechanize,它会为您处理大部分繁琐的工作。
  • 我不能使用它,因为我应该在没有该软件包的服务器上运行代码,并且我没有安装它们的权限。

标签: perl web-crawler


【解决方案1】:

有几点,你的网址解析很脆弱,你肯定不会得到相对链接。此外,您不会测试 100 个链接,而是测试当前 url 的 100 个匹配项,这几乎肯定不是您的意思。最后,我对 LWP 不太熟悉,所以我将展示一个使用 Mojolicious 工具套件的示例。

这似乎行得通,也许它会给你一些想法。

#!/usr/bin/env perl

use strict;
use warnings;

use Mojo::UserAgent;
use Mojo::URL;

##open file to store links
open my $log, '>', 'extracted_links.txt' or die $!;

##starting URL
my $base = Mojo::URL->new('http://stackoverflow.com/');
my @urls = $base;

my $ua = Mojo::UserAgent->new;
my %visited;
my $url_count = 0;

while (@urls) {
  my $url = shift @urls;
  next if exists $visited{$url};

  print "$url\n";
  print $log "$url\n";

  $visited{$url} = 1;
  $url_count++;         

  # find all <a> tags and act on each
  $ua->get($url)->res->dom('a')->each(sub{
    my $url = Mojo::URL->new($_->{href});
    if ( $url->is_abs ) {
      return unless $url->host eq $base->host;
    }
    push @urls, $url;
  });

  last if $url_count == 100;

  sleep 1;
}

【讨论】:

  • 感谢您的回复。但由于缺少 Mojolicious 工具包,我无法试用您的代码。
  • 它很容易安装。单线是这样的:curl get.mojolicio.us | sh
  • 嗨乔尔,感谢您的代码 sn-p。但我认为它需要调整以解决相关链接,否则页面将无法正常工作。为了解决这个问题,我创建了一个名为 $baseURL 的变量来保存起始 URL(在您的示例中为“stackoverflow.com'”),然后我将您的代码更改如下:if ( $url-&gt;is_abs ) { return unless $url-&gt;host eq $base-&gt;host; } else { $url = Mojo::URL-&gt;new($baseURL)-&gt;path($_); } push @urls, $url;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多