PHP:cURL和跟踪所有重定向

10

我想使用cURL获取一个URL,并跟踪它通过的每个独立的URL。但是我无法做到这一点,而不进行递归的cURL调用,这并不理想。也许我错过了一些简单的选项。你有什么想法吗?

 $url = "some url with redirects";
 $ch = curl_init($url);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
 curl_setopt($ch, CURLOPT_HEADER, true);
 curl_setopt($ch, CURLOPT_NOBODY, false);
 curl_setopt($ch, CURLOPT_TIMEOUT, 10);
 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
 curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1) Gecko/20061024 BonEcho/2.0");

 $html = curl_exec($ch);
 $info = array();
 if(!curl_errno($ch))
 {
      $info = curl_getinfo($ch);
      echo "<pre>";
      print_r($info);
      echo "</pre>";
 }

我得到了这样的回复

Array
(
    [url] => THE LAST URL THAT WAS HIT
    [content_type] => text/html; charset=utf-8
    [http_code] => 200
    [header_size] => 1942
    [request_size] => 1047
    [filetime] => -1
    [ssl_verify_result] => 0
    [redirect_count] => 2   <---- I WANT THESE
    [total_time] => 0.799589
    [namelookup_time] => 0.000741
    [connect_time] => 0.104206
    [pretransfer_time] => 0.104306
    [size_upload] => 0
    [size_download] => 49460
    [speed_download] => 61856
    [speed_upload] => 0
    [download_content_length] => 49460
    [upload_content_length] => 0
    [starttransfer_time] => 0.280781
    [redirect_time] => 0.400723
)
3个回答

13
你有。
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

这意味着cURL将跟随重定向并只返回最终页面,而没有任何位置头。

手动跟踪位置:

function getWebPage($url, $redirectcallback = null){
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_NOBODY, false);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1) Gecko/20061024 BonEcho/2.0");

    $html = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    if ($http_code == 301 || $http_code == 302) {
        list($httpheader) = explode("\r\n\r\n", $html, 2);
        $matches = array();
        preg_match('/(Location:|URI:)(.*?)\n/', $httpheader, $matches);
        $nurl = trim(array_pop($matches));
        $url_parsed = parse_url($nurl);
        if (isset($url_parsed)) {
            if($redirectcallback){ // callback
                 $redirectcallback($nurl, $url);
            }
            $html = getWebPage($nurl, $redirectcallback);
        }
    }
    return $html;
}

function trackAllLocations($newUrl, $currentUrl){
    echo $currentUrl.' ---> '.$newUrl."\r\n";
}

getWebPage('some url with redirects', 'trackAllLocations');

例如,$redirectcallback会是什么? - ChristoKiwi

6
使用libcurl,您可以使用CURLINFO_REDIRECT_URL getinfo变量来查找它如果启用会重定向到的URL。这使得程序可以轻松地遍历重定向。

这种方法比其他人在此建议的解析Location:头部要好得多,因为那样您的代码必须重新构建相对路径等。 CURLINFO_REDIRECT_URL会自动为您解决这个问题。

PHP / CURL绑定在PHP 5.3.7中添加了支持此功能

$url = curl_getinfo($ch, CURLINFO_REDIRECT_URL)

修复此问题的提交:

https://github.com/php/php-src/commit/689268a0ba4259c8f199cae6343b3d17cab9b6a5


嘿,链接不再起作用了。这个功能已经实现了吗?如果是的话,你知道如何从PHP中使用它吗? - The Onin
1
我很感激这个见解,它比手动循环状态码并查找重定向URL更让我喜欢。 - The Onin

3

我可以提出一些建议吗...

 preg_match('/(Location:|URI:)(.*?)\n/', $httpheader, $matches);

将正则表达式更改为/(Location:|URI:)(.*?)\n/i,以使其不区分大小写。我注意到有一些站点/地方使用小写字母的location:。
只是一个想法,帮助那些想知道为什么有时它不起作用的人...研究一下吧。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接