我目前正在开展涉及抓取某些网站的项目。但是有时候我的Perl程序会因某种原因(无法弄清楚原因)在网站上“卡住”,程序会冻结几个小时。为了解决这个问题,我插入了一些代码来超时抓取网页的子程序。这个问题是,让我说我将闹钟设置为60秒,大部分时间页面都会正确超时,但偶尔程序不会超时,只能连续几个小时(因为我经常杀了程序)。
在非常糟糕的网站上,Perl程序只会吞噬我的内存,占用2.3GB内存和13GB交换空间。 CPU使用率也很高,我的电脑也会很迟钝。幸运的是,如果超时,所有资源都会很快释放。
这是我的代码还是Perl问题? 我应该纠正什么,为什么会导致这个问题?
由于
这是我的代码:
eval {
local $SIG{ALRM} = sub { die("alarm\n") };
alarm 60;
&parsePageFunction();
alarm 0;
};#eval
if($@) {
if($@ eq "alarm\n") { print("Webpage Timed Out.\n\n"); }#if
else { die($@."\n"); }#else
}#if
答案 0 :(得分:4)
根据代码的确切位置,您可能会遇到perl safe signals的问题。请参阅有关变通方法的perlipc文档(例如Perl::Unsafe::Signals)。
答案 1 :(得分:1)
您可能希望详细说明抓取过程。
我猜这是一种递归抓取,对于每个抓取的网页,您抓取其上的所有链接,并重复抓取所有这些网页上的所有链接。
如果是这种情况,您可能想要做两件事:
创建某种深度限制,在递增计数器的每次递归上,如果达到限制则停止爬行
检测循环链接,如果您有一个PAGE_A,其中包含指向PAGE_B的链接,并且PAGE_B有一个指向PAGE_A的链接,您将抓取,直到内存不足为止。
除此之外,您应该考虑使用您正在使用的模块的标准超时工具,如果LWP::UserAgent
那么LWP::UserAgent->new(timeout => 60)