web-dev-qa-db-ja.com

cURLを使用してリンク先URLを取得するにはどうすればよいですか?

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

次を使用できます。

echo curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
49
Tamik Soziev
$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';
22
Leksat

少し古い回答ですが、完全な実例を示すことを望んでいましたが、いくつかの解決策があります:

    $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が返されます(見つからなかったため)。これは、サイトのリンクを更新または削除するために使用できます。とにかくこれは私の必要でした。

8
Shawn

リダイレクトされたURLのLocationヘッダーを取得する必要があります。

5
raspi

Tamik Sozievの答えに対するuser437797のコメントに対する回答(残念ながら、直接コメントする評判はありません):

CURLINFO_EFFECTIVE_URLは正常に機能しますが、opが望むようにするためには、もちろんCURLOPT_FOLLOWLOCATIONをTRUEに設定する必要があります。これは、CURLINFO_EFFECTIVE_URLが正確に、実際にロードされる有効なURLを返すためです。リダイレクトに従わない場合、これは要求されたURLになり、リダイレクトに従う場合、リダイレクト先の最終URLになります。

このアプローチの良い点は、複数のリダイレクトでも機能することです。一方、HTTPヘッダーを自分で取得および解析するときは、最終的な宛先URLが公開される前にそれを複数回行う必要があります。

また、curlが従うリダイレクトの最大数は、CURLOPT_MAXREDIRSを介して制御できることに注意してください。デフォルトでは無制限(-1)ですが、誰かが(おそらく意図的に)構成したURLに無限のリダイレクトループがあると、問題が発生する可能性があります。

3
Arthur

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

とにかく、HTTP Statuscode 302は一時リダイレクトに過ぎないため、新しいURIを使用しないでください。

2
echox

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);
}
1
GZipp

curl_getinfo($ch)を使用すると、最初の要素(url)は有効なURLを示します。

0
Sabeen Malik