curl
, похоже, не имеет функции или опции для получения цели перенаправления, его можно извлечь, используя различные методы:
Из ответа :
Apache может ответить HTML-страницей в случае перенаправления 301 (не похоже на 302).
Если ответ имеет формат, подобный следующему:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="http://www.xxx.yyy/zzz">here</a>.</p>
<hr>
<address>Apache/2.2.16 (Debian) Server at www.xxx.yyy Port 80</address>
</body></html>
Вы можете извлечь URL перенаправления, используя DOMXPath
:
$i = 0;
foreach($urls as $url) {
if(substr($url,0,4) == "http") {
$c = curl_init($url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
$result = @curl_exec($c);
$status = curl_getinfo($c,CURLINFO_HTTP_CODE);
curl_close($c);
$results[$i]['code'] = $status;
$results[$i]['url'] = $url;
if($status === 301) {
$xml = new DOMDocument();
$xml->loadHTML($result);
$xpath = new DOMXPath($xml);
$href = $xpath->query("//*[@href]")->item(0);
$results[$i]['target'] = $href->attributes->getNamedItem('href')->nodeValue;
}
$i++;
}
}
Использование CURLOPT_NOBODY
Однако есть более быстрый способ, как указывает @ gAMBOOKa ; Использование CURLOPT_NOBODY
. Этот подход просто отправляет запрос HEAD
вместо GET
(не загружая фактический контент, поэтому он должен быть быстрее и эффективнее) и сохраняет заголовок ответа.
Используя регулярное выражение, целевой URL можно извлечь из заголовка:
foreach($urls as $url) {
if(substr($url,0,4) == "http") {
$c = curl_init($url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_NOBODY,true);
curl_setopt($c, CURLOPT_HEADER, true);
$result = @curl_exec($c);
$status = curl_getinfo($c,CURLINFO_HTTP_CODE);
curl_close($c);
$results[$i]['code'] = $status;
$results[$i]['url'] = $url;
if($status === 301 || $status === 302) {
preg_match("@https?://([-\w\.]+)+(:\d+)?(/([\w/_\-\.]*(\?\S+)?)?)?@",$result,$m);
$results[$i]['target'] = $m[0];
}
$i++;
}
}