如何使用cURL获取目标网址?

时间:2009-09-17 13:55:24

标签: php html http curl

当HTTP状态代码为302时,如何使用cURL获取目标URL?

<?PHP
$url = "http://www.ecs.soton.ac.uk/news/";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$html = curl_exec($ch);
$status_code = curl_getinfo($ch,CURLINFO_HTTP_CODE);

if($status_code=302 or $status_code=301){
  $url = "";
  // I want to to get the destination url
}
curl_close($ch);
?>

8 个答案:

答案 0 :(得分:47)

您可以使用:

echo curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);

答案 1 :(得分:22)

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, TRUE); // We'll parse redirect url from header.
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE); // We want to just get redirect url but not to follow it.
$response = curl_exec($ch);
preg_match_all('/^Location:(.*)$/mi', $response, $matches);
curl_close($ch);
echo !empty($matches[1]) ? trim($matches[1][0]) : 'No redirect found';

答案 2 :(得分:6)

有点过时的回复,但希望展示一个完整的工作示例,其中一些解决方案有:

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url); //set url
    curl_setopt($ch, CURLOPT_HEADER, true); //get header
    curl_setopt($ch, CURLOPT_NOBODY, true); //do not include response body
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //do not show in browser the response
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //follow any redirects
    curl_exec($ch);
    $new_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); //extract the url from the header response
    curl_close($ch);

这适用于任何重定向,例如301或302,但是在404上它只会返回请求的原始网址(因为找不到它)。这可用于更新或删除您网站的链接。无论如何,这是我的需要。

答案 3 :(得分:5)

您必须抓住重定向网址的位置标头。

答案 4 :(得分:2)

302重定向的新目标位于http标题字段“location”中。 例如:

HTTP/1.1 302 Found
Date: Tue, 30 Jun 2002 1:20:30 GMT
Server: Apache
Location: http://www.foobar.com/foo/bar
Content-Type: text/html; charset=iso-8859-1

只需用正则表达式进行grep。

要包含所有HTTP标头信息,请将其包含在curl选项 CURLOPT_HEADER 的结果中。设置为:

curl_setopt($c, CURLOPT_HEADER, true);

如果您只想让curl遵循重定向,请使用 CURLOPT_FOLLOWLOCATION

curl_setopt($c, CURLOPT_FOLLOWLOCATION, true);

无论如何,您不应该使用新的URI,因为HTTP状态码302只是临时重定向。

答案 5 :(得分:2)

回应用户437797对Tamik Soziev的回答的评论(遗憾的是我没有直接在那里发表评论的声誉):

CURLINFO_EFFECTIVE_URL工作正常,但要像op那样做,你当然也必须将CURLOPT_FOLLOWLOCATION设置为TRUE。这是因为CURLINFO_EFFECTIVE_URL完全返回它所说的内容,即最终加载的有效URL。如果您不遵循重定向,那么这将是您请求的URL,如果您确实遵循重定向,那么它将是重定向到的最终URL。

这种方法的好处在于它也适用于多个重定向,而在自己检索和解析HTTP头时,您可能需要多次执行此操作才能显示最终目标URL。

另请注意,可以通过CURLOPT_MAXREDIRS控制卷曲所遵循的最大重定向数。默认情况下它是无限制的(-1)但如果有人(可能是有意)配置并且为某些网址重复无限循环,这可能会让你陷入麻烦。

答案 6 :(得分:1)

这是一种获取curl http请求返回的所有标头的方法,以及每个标头的状态代码和标题行数组。

$url = 'http://google.com';
$opts = array(CURLOPT_URL => $url,
              CURLOPT_RETURNTRANSFER => true,
              CURLOPT_HEADER => true,
              CURLOPT_FOLLOWLOCATION => true);

$ch = curl_init();
curl_setopt_array($ch, $opts);
$return = curl_exec($ch);
curl_close($ch);

$headers = http_response_headers($return);
foreach ($headers as $header) {
    $str = http_response_code($header);
    $hdr_arr = http_response_header_lines($header);
    if (isset($hdr_arr['Location'])) {
        $str .= ' - Location: ' . $hdr_arr['Location'];
    }
    echo $str . '<br />';
}

function http_response_headers($ret_str)
{
    $hdrs = array();
    $arr = explode("\r\n\r\n", $ret_str);
    foreach ($arr as $each) {
        if (substr($each, 0, 4) == 'HTTP') {
            $hdrs[] = $each;
        }
    }
    return $hdrs;
}

function http_response_header_lines($hdr_str)
{
    $lines = explode("\n", $hdr_str);
    $hdr_arr['status_line'] = trim(array_shift($lines));
    foreach ($lines as $line) {
        list($key, $val) = explode(':', $line, 2);
        $hdr_arr[trim($key)] = trim($val);
    }
    return $hdr_arr;
}

function http_response_code($str)
{
    return substr(trim(strstr($str, ' ')), 0, 3);
}

答案 7 :(得分:0)

使用curl_getinfo($ch),第一个元素(url)表示有效网址。