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