【问题标题】:Web-crawler optimization网络爬虫优化
【发布时间】:2013-03-29 15:50:21
【问题描述】:

我正在使用向量空间模型构建一个基本的搜索引擎,这是一个用于返回 500 个 URL 并从内容中删除 SGML 标签的爬虫。但是,它非常慢(仅检索 URL 需要 30 多分钟)。如何优化代码?我已插入 wikipedia.org 作为示例起始 URL。

use warnings;

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

my $starting_url = 'http://en.wikipedia.org/wiki/Main_Page';
my @urls = $starting_url;
my %alreadyvisited;
my $browser = LWP::UserAgent->new();
$browser->timeout(5);
my $url_count = 0;

while (@urls) 
{ 
     my $url = shift @urls;
     next if $alreadyvisited{$url}; ## check if already visited

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

     if ($response->is_error())
     {
         print $response->status_line, "\n"; ## check for bad URL
     }
     my $contents = $response->content(); ## get contents from URL
     push @c, $contents;
     my @text = &RemoveSGMLtags(\@c);
     #print "@text\n";

     $alreadyvisited{$url} = 1; ## store URL in hash for future reference
     $url_count++;
     print "$url\n";

     if ($url_count == 500) ## exit if number of crawled pages exceed limit
     {
         exit 0; 
     } 


     my ($page_parser) = HTML::LinkExtor->new(undef, $url); 
     $page_parser->parse($contents)->eof; ## parse page contents
     my @links = $page_parser->links; 

     foreach my $link (@links) 
     {
             $test = $$link[2];
             $test =~ s!^https?://(?:www\.)?!!i;
             $test =~ s!/.*!!;
             $test =~ s/[\?\#\:].*//;
             if ($test eq "en.wikipedia.org")  ## check if URL belongs to unt domain
             {
                 next if ($$link[2] =~ m/^mailto/); 
                 next if ($$link[2] =~ m/s?html?|xml|asp|pl|css|jpg|gif|pdf|png|jpeg/);
                 push @urls, $$link[2];
             }
     }
     sleep 1;
}


sub RemoveSGMLtags 
{
    my ($input) = @_;
    my @INPUTFILEcontent = @$input;
    my $j;my @raw_text;
    for ($j=0; $j<$#INPUTFILEcontent; $j++)
    {
        my $INPUTFILEvalue = $INPUTFILEcontent[$j];
        use HTML::Parse;
        use HTML::FormatText;
        my $plain_text = HTML::FormatText->new->format(parse_html($INPUTFILEvalue));
        push @raw_text, ($plain_text);
    }
    return @raw_text;
}

【问题讨论】:

  • 我不确定。我是 perl 新手,仍在学习如何编写高效的代码。
  • 您正在尝试下载en.wikipedia.org整个。除了维基百科可能根本不喜欢这个之外,如果你能在 30 分钟内做到这一点,那将是一项成就。请三思而后行,并仔细检查您所做的任何网站的服务条款。大多数人不希望他们的数据被这样滥用。
  • 其实我得爬我的大学网站。对不起,我忘了提这个。我把这个网址作为一个例子。

标签: perl optimization search-engine web-crawler


【解决方案1】:

使用 WWW::Mechanize 为您处理所有 URL 解析和提取。比您正在处理的所有链接解析要容易得多。它是专门为您正在做的事情而创建的,它是 LWP::UserAgent 的子类,因此您应该能够将所有 LWP::UserAgent 更改为 WWW::Mechanize 而无需更改任何代码,除了对于所有的链接提取,所以你可以这样做:

my $mech = WWW::Mechanize->new();
$mech->get( 'someurl.com' );
my @links = $mech->links;

然后@links 是一个 WWW::Mechanize::Link 对象数组。

【讨论】:

  • 谢谢,但我不能使用 Mechanize,因为我必须在没有该软件包且我无权安装它的服务器中执行最终代码
  • @user2154731:了解如何install Perl modules under your own home directory。你会发现它的用处远不止 WWW::Mechanize。
【解决方案2】:
  • 总是 use strict

  • 从不在子例程调用中使用与符号&amp;

  • 使用URI 操作网址

你有一个sleep 1,我认为这是为了避免过多地敲击网站,这很好。但是几乎所有基于 Web 的应用程序的瓶颈都是互联网本身,如果不从站点请求更多,您将无法使您的程序更快。这意味着删除您的sleep,并可能使用例如LWP::Parallel::RobotUA 向服务器发出并行请求。这是你应该走的路吗?

【讨论】:

  • 谢谢,当我删除睡眠时,代码会快得多。将尝试使用并行请求。
  • 另一个重要的问题,你可能知道你是否已经分析过代码,是你在每一行输入时调用 HTML::FormatText->new->format(parse_html(您可以改为在整个网页上调用一次。
猜你喜欢
  • 1970-01-01
  • 2017-05-16
  • 1970-01-01
  • 2011-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-12
相关资源
最近更新 更多