4

我希望我的脚本只下载文本/html 内容,而不是下载可能需要更多时间的二进制文件或图像。我知道max_size参数,但我想在Content-Type标题上添加一个检查。这是可行的吗?

4

3 回答 3

6

正如其他人指出的那样,您可以在HEAD请求之前执行GET请求。您应该这样做是为了对服务器有礼貌,因为您实际上很容易中止连接,但对于 Web 服务器来说,中止发送一堆数据并在其末端做一堆工作并不一定容易.

根据您想要的复杂程度,有一些不同的方法可以做到这一点。

  1. 您可以在您的请求中发送一个Accept标头,其中仅列出text/html. 406 Not Acceptable如果您说您不接受文件的任何内容,那么一个实施良好的 HTTP 服务器将返回一个状态。当然,无论如何,他们可能会将其发送给您。您也可以根据自己的HEAD要求执行此操作。

  2. 使用最新版本的LWP::UserAgent时,您可以使用处理程序子例程在标头之后和内容正文之前中止请求的其余部分。

    use LWP::UserAgent;
    use Try::Tiny; 
    
    my $ua = LWP::UserAgent->new;
    $ua->add_handler( response_header => sub {
        my($response, $ua, $h) = @_;
    
        die "Not HTML" unless $response->content_type eq 'text/html';
    });
    
    my $url = "http://example.com/foo";
    
    my $html;
    my $head_response = $ua->head($url, Accept => "text/html");
    if ($head_response->is_success) {
        my $get_response = $ua->get($url, Accept => "text/html");
        if ($get_response->is_success) {
            $html = $get_response->content;
        }
    } 
    

有关处理程序的详细信息,请参阅 LWP::UserAgent 文档的处理程序部分。

我没有发现抛出的异常或确保在这里仔细处理 406 响应。我把它留给读者作为练习。

于 2012-07-30T15:27:27.777 回答
1

您可以使用 HEAD 请求来查询 URI 的标头信息。如果服务器响应头部,你将得到 GET 将返回的所有内容,除了那个讨厌的身体。

然后,您可以根据 MIME 类型决定要做什么。

否则,在请求之前,您必须依赖文件的扩展名。

于 2012-07-30T15:01:10.083 回答
0

如果您使用的是最小子LWP::Simple类,LWP则该head函数将内容类型作为列表的第一个元素返回。

所以你可以写

use strict;
use warnings;

use LWP::Simple;

for my $url ('http://www.bbc.co.uk') {
  my ($ctype) = head $url;
  my $content = get $url if $ctype eq 'text/html';
}
于 2012-07-30T15:07:49.787 回答