如何使用 cURL 获取目标 URL?

Posted

技术标签:

【中文标题】如何使用 cURL 获取目标 URL?【英文标题】:How can I get the destination URL using cURL? 【发布时间】:2010-11-29 04:05:12 【问题描述】:

当 HTTP 状态码为 302 时,

<?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);
?>

【问题讨论】:

其他未解决的问题有什么好运气吗? 你应该接受正确答案(-1) 【参考方案1】:

你可以使用:

echo curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);

【讨论】:

这种方法比从 Location 标头中解析出 url 要干净得多/通常更好。 CURLINFO_EFFECTIVE_URL 为我返回当前(请求的)页面。 curl_getinfo 结果中没有重定向 (Location:) url。看来,解析标头是最好的做法...... CURLINFO_EFFECTIVE_URL 在某些情况下并不总是有效,尤其是那些不使用标头重定向的情况。 对于那些正在获取当前(请求)页面的人,在调用 curl_exec($ch); 后使用此代码 很好,比自己解析要干净得多。感谢分享!【参考方案2】:
$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';

【讨论】:

完美!感谢分享 如果没有位置标头? 有时网站会使用元重定向或window.location.replace 来重定向页面。在这种情况下,请替换正则表达式以捕获结果。【参考方案3】:

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

    $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 上它只会返回请求的原始 url(因为它没有找到)。这可用于更新或删除您网站上的链接。无论如何,这是我的需要。

【讨论】:

【参考方案4】:

您必须获取重定向 URL 的 Location 标头。

【讨论】:

这需要进一步的麻烦,比如检查它是否是相对的,解决它(如果有多个等,则在中间重定向中可能是以前的基本 URL 等。pp。),它更容易使用@ 987654321@.【参考方案5】:

作为对 user437797 对 Tamik Soziev 回答的评论的回应(不幸的是,我没有直接在那里发表评论的声誉):

CURLINFO_EFFECTIVE_URL 可以正常工作,但要按照操作的要求进行操作,您当然还必须将 CURLOPT_FOLLOWLOCATION 设置为 TRUE。这是因为 CURLINFO_EFFECTIVE_URL 准确地返回它所说的,最终被加载的有效 url。如果您不遵循重定向,那么这将是您请求的 url,如果您遵循重定向,那么它将是重定向到的最终 url。

这种方法的好处是它也适用于多个重定向,而当您自己检索和解析 HTTP 标头时,您可能必须在最终目标 URL 公开之前多次执行此操作。

另请注意,curl 遵循的最大重定向数可以通过 CURLOPT_MAXREDIRS 控制。默认情况下它是无限制的(-1),但如果有人(可能是故意)为某些 url 配置了无限的重定向循环,这可能会给您带来麻烦。

【讨论】:

【参考方案6】:

302 重定向的新目的地位于 http 标头字段“位置”中。 示例:

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 只是一个临时重定向。

【讨论】:

【参考方案7】:

这是一种获取 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);

【讨论】:

【参考方案8】:

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

【讨论】:

以上是关于如何使用 cURL 获取目标 URL?的主要内容,如果未能解决你的问题,请参考以下文章

如何在curl方式下url请求域名使用指定ip地址来访问某个服务器

如何在 PowerShell 中将 curl 结果作为变量获取

如何在脚本中获取“作为cURL复制”?

php如何获取远程文件内容的函数

如何从 URL 获取 JSON 参数

如何使用动态 URL 从 webview 获取 JSON?