如果发生重定向,如何在 file_get_contents 之后获取真实的 URL?
Posted
技术标签:
【中文标题】如果发生重定向,如何在 file_get_contents 之后获取真实的 URL?【英文标题】:How to get the real URL after file_get_contents if redirection happens? 【发布时间】:2011-05-18 11:05:31 【问题描述】:我正在使用 file_get_contents()
从站点中获取内容,令人惊讶的是,即使我作为参数传递的 URL 重定向到另一个 URL,它也能正常工作。
问题是我需要知道新的 URL,有没有办法做到这一点?
【问题讨论】:
【参考方案1】:如果您需要使用file_get_contents()
而不是 curl,请不要自动跟随重定向:
$context = stream_context_create(
array(
'http' => array(
'follow_location' => false
)
)
);
$html = file_get_contents('http://www.example.com/', false, $context);
var_dump($http_response_header);
答案灵感来自:How do I ignore a moved-header with file_get_contents in php?
【讨论】:
你从哪里得到$http_response_header
?
@PetrPeller 这是一个 PHP 特殊变量:php.net/manual/en/reserved.variables.httpresponseheader.php
我试过了,虽然它确实根据这个答案末尾链接的问题停止了重定向,但它没有提供这个问题中要求的“真实 URL”。不过,也可能是我尝试使用的服务器不支持它。在我看来,虽然 curl() 方法是唯一可靠的方法。
@RPorter 你需要提取$http_response_header
中的301位置。
具有保留名称的神奇局部变量,实际上是保存先前函数调用结果的全局变量... PHP 是一团乱七八糟的语言。【参考方案2】:
您可以使用 cURL 而不是 file_get_contents()
发出请求。
这样的东西应该可以工作......
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$a = curl_exec($ch);
if(preg_match('#Location: (.*)#', $a, $r))
$l = trim($r[1]);
Source
【讨论】:
谢谢.. 但是我从哪里获得 html 输出呢?在 $a 我只能看到标题。是否有可能只用一个请求就可以得到一切?编辑:好吧,那是愚蠢的。现在我明白了,无论如何都会有 2 个请求 =D。谢谢! 但是如果有多个重定向呢?如何获取最终到达网址? CURL 在 Google App 引擎中不可用,因此如果您需要使用 file_get_contents(),答案无济于事 @ixlli 对。我一定错过了 OP 所说的答案必须仅适用于 Google App Engine 环境。 @alex heh... 我认为关键是他在询问 file_get_contents() 所以当谷歌搜索问题时,这就是你发现的。【参考方案3】:一切尽在一个功能中:
function get_web_page( $url )
$res = array();
$options = array(
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_HEADER => false, // do not return headers
CURLOPT_FOLLOWLOCATION => true, // follow redirects
CURLOPT_USERAGENT => "spider", // who am i
CURLOPT_AUTOREFERER => true, // set referer on redirect
CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
CURLOPT_TIMEOUT => 120, // timeout on response
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
);
$ch = curl_init( $url );
curl_setopt_array( $ch, $options );
$content = curl_exec( $ch );
$err = curl_errno( $ch );
$errmsg = curl_error( $ch );
$header = curl_getinfo( $ch );
curl_close( $ch );
$res['content'] = $content;
$res['url'] = $header['url'];
return $res;
print_r(get_web_page("http://www.example.com/redirectfrom"));
【讨论】:
小心。 CURLOPT_FOLLOWLOCATION 在“open_base_dir”被填满或启用安全模式时是不允许的。【参考方案4】:使用裸file_get_contents
的完整解决方案(注意输入输出$url
参数):
function get_url_contents_and_final_url(&$url)
do
$context = stream_context_create(
array(
"http" => array(
"follow_location" => false,
),
)
);
$result = file_get_contents($url, false, $context);
$pattern = "/^Location:\s*(.*)$/i";
$location_headers = preg_grep($pattern, $http_response_header);
if (!empty($location_headers) &&
preg_match($pattern, array_values($location_headers)[0], $matches))
$url = $matches[1];
$repeat = true;
else
$repeat = false;
while ($repeat);
return $result;
请注意,这仅适用于 Location
标头中的绝对 URL。如果您需要支持相对 URL,请参阅
PHP: How to resolve a relative url.
例如,如果您使用answer by @Joyce Babu 中的解决方案,请替换:
$url = $matches[1];
与:
$url = getAbsoluteURL($matches[1], $url);
【讨论】:
【参考方案5】:我用get_headers($url, 1);
在我的情况下,get_headers($url, 1)['Location'][1];
中的重定向网址
【讨论】:
以上是关于如果发生重定向,如何在 file_get_contents 之后获取真实的 URL?的主要内容,如果未能解决你的问题,请参考以下文章
从file_get_contents()成功获取数据后,PHP重定向到另一个页面