2011-02-23 10 views
6

curl_getinfo 함수는 HTTP 요청 결과에 대한 많은 메타 데이터를 반환합니다. 그러나 어떤 이유로 요청에 HTTP 리디렉션 코드가 반환되면 대상 URL 인 원하는 정보가 포함되지 않습니다.PHP cURL : 리디렉션 대상을 따르지 않고

특별한 리디렉션 코드를 특별한 경우로 처리하기 때문에 CURLOPT_FOLLOWLOCATION을 사용하지 않습니다.

cURL이 리디렉션을 추적 할 수있는 경우 리디렉션을 따르지 않을 때 리다이렉트하는 내용을 말해 줄 수없는 이유는 무엇입니까?

물론 CURLOPT_HEADER 플래그를 설정하고 Location 헤더를 선택할 수 있습니다. 그러나 더 효율적인 방법이 있습니까?

+0

CURLOPT_NOBODY에서 사용할 수 있습니까? – HyderA

+0

내 프로그램은 실제로 URL이 리디렉션이 아닌 경우 본문을 사용합니다. 그래서 이것은 전혀 문제를 개선시키지 못합니다. 내 쿼리는 기본적으로 PHP 코드에서 수행하는 오버 헤드를 줄이는 Location 헤더를 추출하는 방법이 있는지 여부에 관한 것입니다. – Stewart

+0

http://stackoverflow.com/questions/1439040/how-can-i-get-the-destination-url-using-curl –

답변

0

없음 더 효율적으로 귀하의 변수에 CURLOPT_WRITEHEADER + VariableStream
그래서 .. 당신이 쓸 수있는 헤더를 사용하고 구문 분석 할 수있는 방법
없다

+0

내 목표를 위해 과잉으로 보입니다 ... 어쩌면 간단한 콜백을 사용할 것입니다. 그 (것)들을 이해하는 것을 처리했다. – Stewart

2

curl 얻을 수있는 기능이나 옵션을하지 않는 것

아파치가 응답 할 수 있습니다 : 응답에서

: 리디렉션 대상, 그것은 다양한 기술을 사용하여 추출 할 수있다 301 리디렉션의 경우 HTML 페이지가 표시됩니다 (302의 경우는 아닙니다). DOMXPath를 사용하여 당신은 리디렉션 URL을 추출 할 수 있습니다

<!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> 

:

$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을 사용하십시오. 이 방법은 GET (실제 콘텐츠를 다운로드하지 않으므로보다 빠르고 효율적이어야 함) 대신 HEAD 요청을 보내고 응답 헤더를 저장합니다. 정규식을 대상 URL을 사용하여

헤더에서 추출 할 수 있습니다

이는 간단한 4 단계로 수행 할 수 있습니다
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+)?)?)[email protected]",$result,$m); 
      $results[$i]['target'] = $m[0]; 
     } 
     $i++; 
    } 
} 
+0

승리를위한 CURLOPT_NOBODY! 빠뜨릴 수없는 ... 감사합니다 !!! – Gor

4

: 1. 초기화가

curl_init($ch); //initialise the curl handle 
//COOKIESESSION is optional, use if you want to keep cookies in memory 
curl_setopt($this->ch, CURLOPT_COOKIESESSION, true); 

단계를 곱슬 곱슬

단계 2. 헤더 가져 오기 $url

curl_setopt($ch, CURLOPT_URL, $url); //specify your URL 
curl_setopt($ch, CURLOPT_HEADER, true); //include headers in http data 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); //don't follow redirects 
$http_data = curl_exec($ch); //hit the $url 
$curl_info = curl_getinfo($ch); 
$headers = substr($http_data, 0, $curl_info['header_size']); //split out header 

단계 3. 올바른 응답 코드

if (!($curl_info['http_code']>299 && $curl_info['http_code']<309)) { 
    //return, echo, die, whatever you like 
    return 'Error - http code'.curl_info['http_code'].' received.'; 
} 

4 단계를해야합니다.새로운 URL을 얻기 위해 헤더를 구문 분석하십시오.

preg_match("!\r\n(?:Location|URI): *(.*?) *\r\n!", $headers, $matches); 
$url = $matches[1]; 

일단 새 URL을 얻은 후에는 2-4 단계를 원하는만큼 자주 반복 할 수 있습니다.

0

나는 동일한 문제가 있었고 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);은 도움이되었습니다.

그래서 내가 대신 CURL하지만 file_get_contents를 사용하지 않기로 결정 :

$data = file_get_contents($url); 
$data = str_replace("<meta http-equiv=\"Refresh\" content=\"0;","<meta",$data); 

마지막 줄 제품이 깨끗한 HTML 코드는 아니지만 리디렉션을 차단하도록 도와주었습니다.

나는 데이터를 파싱하여 얻고 자하는 리디렉션 URL을 검색 할 수있었습니다.

+0

리디렉션을 차단하려는 페이지가 HTTP 리디렉션이 아닌 메타 새로 고침을 사용하고있는 것처럼 보입니다. 후자는 내가 다루고있는 것이다. – Stewart

1

당신은 간단하게 사용할 수 있습니다 : 당신이 언급 한 바와 같이 (CURLINFO_REDIRECT_URL는)

$info = curl_getinfo($ch, CURLINFO_REDIRECT_URL); 
echo $info; // the redirect URL without following it 

, (실행 전) CURLOPT_FOLLOWLOCATION 옵션을 해제하고 실행 한 후 내 코드를 넣습니다.

CURLINFO_REDIRECT_URL - 장애인 CURLOPT_FOLLOWLOCATION 옵션 으로 : 마지막 트랜잭션에있는 URL을 리디렉션, 수동으로 다음 요청해야합니다. CURLOPT_FOLLOWLOCATION 옵션이 인 경우 : 비어 있습니다. 이 경우 리디렉션 URL은 CURLINFO_EFFECTIVE_URL

Refrence