首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >网络爬虫优化

网络爬虫优化
EN

Stack Overflow用户
提问于 2013-04-07 23:44:35
回答 2查看 424关注 0票数 2

我正在建立一个使用矢量空间模型的基本搜索引擎,这是返回500个URL的爬虫,并从内容中删除SGML标签。然而,它非常慢(仅检索URL就需要30分钟以上)。如何优化代码?我已经插入了wikipedia.org作为开始网址的示例。

代码语言:javascript
运行
复制
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;
}
EN

回答 2

Stack Overflow用户

发布于 2013-04-08 00:37:56

Always use strict

  • Never use
  • & on子例程调用时始终使用与号
  • Use URI to

URL

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

票数 5
EN

Stack Overflow用户

发布于 2013-04-08 00:54:51

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

代码语言:javascript
运行
复制
my $mech = WWW::Mechanize->new();
$mech->get( 'someurl.com' );
my @links = $mech->links;

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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15864277

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档