如何检测更改的网页?

时间:2012-04-18 00:14:48

标签: perl webpage crc lwp

在我的应用程序中,我使用LWP定期获取网页。无论如何要检查两个连续的提取之间是否在某些方面改变了网页(除了明确进行比较)?是否有任何签名(比如CRC)在较低的协议层生成,可以提取并与较旧的签名进行比较以查看可能的更改?

2 个答案:

答案 0 :(得分:4)

有两种可能的方法。一种是使用页面的摘要,例如

use strict;
use warnings;

use Digest::MD5 'md5_hex';
use LWP::UserAgent;

# fetch the page, etc.
my $digest = md5_hex $response->decoded_content;

if ( $digest ne $saved_digest ) { 
    # the page has changed.
}

另一种选择是使用HTTP ETag,如果,则服务器为所请求的资源提供一个。您只需存储它,然后将请求标头设置为在后续请求中包含If-None-Match字段。如果服务器ETag保持不变,您将获得304 Not Modified状态和空响应正文。否则你会得到新的页面。 (以及新的ETag。)请参阅RFC2616中的Entity Tags

当然,即使内容已经改变,服务器也可以撒谎,并发送相同的ETag。除非你看,否则无法知道。

答案 1 :(得分:3)

您应该使用If-Modified-Since request header,注意RFC中的陷阱。您随请求发送此标头。如果服务器支持它并认为内容较新,则会将其发送给您。如果它认为您拥有最新版本,则会返回304而没有邮件正文。

但是,正如其他答案所指出的那样,服务器不必告诉您实际情况,因此您有时会无法下载内容并自行检查。许多动态内容总是声称拥有新内容,因为许多开发人员从未想过在他们的网络应用程序中支持基本的HTTP内容。

对于LWP位,您可以使用额外的标头创建单个请求:

use HTTP::Request;
use LWP::UserAgent;

my $ua = LWP::UserAgent->new;
my $request = HTTP::Request->new( GET => $url );
$r->header( 'If-Modified-Since' => $time );

$ua->request( $request );

对于所有请求,您可以设置请求处理程序:

$ua->add_handler(
    request_send => sub { 
        my($request, $ua, $h) = @_; 
        # ... look up time from local store
        $r->header( 'If-Modified-Since' => $time );
        }
    );

但是,如果你想保存文件,LWP可以为你mirror完成大部分工作:

$ua->mirror( $url, $filename )