刮痧试图获得403错误

时间:2017-11-12 09:07:32

标签: php perl curl phantomjs scrape

我正在尝试抓取一个网站,无论我尝试什么,我都会收到403 Forbidden错误:

  1. wget的
  2. CURL(命令行和PHP)
  3. Perl WWW :: Mechanize
  4. PhantomJS
  5. 我尝试了以上所有代理,包括更改用户代理和添加引用标头。

    我甚至从我的Chrome浏览器复制了请求标题,并尝试使用PHP Curl发送我的请求,但我仍然收到403 Forbidden错误。

    有关触发网站阻止请求以及如何绕过的内容的任何输入或建议?

    PHP CURL示例:

    $url ='https://www.vitacost.com/productResults.aspx?allCategories=true&N=1318723&isrc=vitacostbrands%3aquadblock%3asupplements&scrolling=true&No=40&_=1510475982858';
    $headers = array(
                'accept:application/json, text/javascript, */*; q=0.01',
                'accept-encoding:gzip, deflate, br',
                'accept-language:en-US,en;q=0.9',               
                'referer:https://www.vitacost.com/productResults.aspx?allCategories=true&N=1318723&isrc=vitacostbrands:quadblock:supplements',
                'user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36',
                'x-requested-with:XMLHttpRequest',
    );
    
    $res = curl_get($url,$headers);
    print $res;
    exit;
    
    function curl_get($url,$headers=array(),$useragent=''){ 
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HEADER, true);           
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);   
        curl_setopt($curl, CURLOPT_ENCODING, '');            
        if($useragent)curl_setopt($curl, CURLOPT_USERAGENT,$useragent);             
        if($headers)curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    
        $response = curl_exec($curl);       
    
        $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
        $header = substr($response, 0, $header_size);
        $response = substr($response, $header_size);
    
    
        curl_close($curl);  
        return $response;
     }
    

    这是我一直得到的回应:

    <HTML><HEAD>
    <TITLE>Access Denied</TITLE>
    </HEAD><BODY>
    <H1>Access Denied</H1>
    
    You don't have permission to access     
    
      "http&#58;&#47;&#47;www&#46;vitacost&#46;com&#47;productResults&#46;aspx&#63;" 
    on this server.<P>
    Reference&#32;&#35;18&#46;55f50717&#46;1510477424&#46;2a24bbad
    </BODY>
    </HTML>
    

1 个答案:

答案 0 :(得分:2)

首先,请注意该网站不喜欢网页抓取。正如@KeepCalmAndCarryOn在评论中指出的,该网站有一个/robots.txt,它明确要求机器人不要抓取网站的特定部分,包括你想要抓取的部分。虽然没有法律约束力的好公民会坚持这样的要求。

此外,该网站似乎采用明确的防止抓取保护,并试图确保这是一个真正的浏览器。看起来该网站是Akamai CDN的幕后推手,因此防刮保护可能来自此CDN。

但是我已经接受了Firefox发送的请求(有效),然后尝试尽可能地简化它。以下工作目前适用于我,但如果站点更新其浏览器检测,则当然可能会失败:

use strict;
use warnings;
use IO::Socket::SSL;

(my $rq = <<'RQ') =~s{\r?\n}{\r\n}g;
GET /productResults.aspx?allCategories=true&N=1318723&isrc=vitacostbrands%3aquadblock%3asupplements&scrolling=true&No=40&_=151047598285 HTTP/1.1
Host: www.vitacost.com
Accept: */*
Accept-Language: en-US
Connection: keep-alive

RQ

my $cl = IO::Socket::SSL->new('www.vitacost.com:443') or die;
print $cl $rq;
my $hdr = '';
while (<$cl>) {
    $hdr .= $_;
    last if $_ eq "\r\n";
}
warn "[header done]\n";
my $len = $hdr =~m{^Content-length:\s*(\d+)}mi && $1 or die "no length";
read($cl,my $buf,$len);
print $buf;

有趣的是,如果删除Accept标题,我会收到403 Forbidden。如果我改为删除Accept-Language,它就会挂起。而且有趣的是它似乎不需要User-Agent标头。

编辑:看起来机器人检测也使用发件人的源IP作为功能。虽然上面的代码适用于两个不同的系统,但它无法用于第三个系统(在Digitalocean上托管)并且只是挂起。