2009-05-21 128 views
103

所以一些其他公司的人認爲這將是可怕的,而不是使用soap或xml-rpc或休息或任何其他合理的通信協議,他只是嵌入他的所有響應作爲標頭中的Cookie。如何從一個PHP捲曲獲取cookie到一個變量

我需要從這個捲曲響應中拉出這些cookie作爲希望的數組。如果我不得不浪費大量時間爲此寫一個解析器,我會很不高興。

有誰知道這可以簡單地完成,最好不寫任何文件?

如果有人能幫助我解決這個問題,我將不勝感激。

回答

138
$ch = curl_init('http://www.google.com/'); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
// get headers too with this line 
curl_setopt($ch, CURLOPT_HEADER, 1); 
$result = curl_exec($ch); 
// get cookie 
// multi-cookie variant contributed by @Combuster in comments 
preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $result, $matches); 
$cookies = array(); 
foreach($matches[1] as $item) { 
    parse_str($item, $cookie); 
    $cookies = array_merge($cookies, $cookie); 
} 
var_dump($cookies); 
+24

不幸的是,我有一種感覺,這是正確的答案。我認爲它的荒謬之處在於,curl不能只是給我一個映射數組。 – thirsty93 2009-05-22 15:26:53

+3

我會給你,但preg_match是錯誤的。 我不只是想要會議,我明白你爲什麼會這麼想。 但是製作他們系統的天才是使用整個響應地圖加載cookie,就像get或post一樣。像這樣: Set-Cookie:price = 1 Set-Cookie:status = accept 我需要一個preg_match_all和'/^Set-Cookie:(。*?)=(。*?)$/sm' – thirsty93 2009-05-22 23:08:06

+0

不夠接近,那麼? – TML 2009-05-24 05:48:38

9

如果使用CURLOPT_COOKIE_FILE和CURLOPT_COOKIE_JAR,curl將從文件讀取/寫入cookie。您可以在捲曲完成後,根據需要閱讀和/或修改它。

+9

我認爲我們的目標是不使用這個文件 – 2013-01-04 15:54:46

0

我的理解是,必須將curl的cookies寫入文件(curl -c cookie_file)。如果你正在運行curl通過PHP的execsystem功能(或該族中的任何東西),你應該能夠餅乾保存到一個文件,然後打開文件,並在閱讀它們。

+4

他幾乎肯定是指php.net/curl :) – TML 2009-05-22 06:12:20

3

的libcurl也提供CURLOPT_COOKIELIST,提取所有已知的Cookie。所有你需要的是確保PHP/CURL綁定可以使用它。

11

這樣做沒有正則表達式,但需要PECL HTTP extension

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_HEADER, 1); 
$result = curl_exec($ch); 
curl_close($ch); 

$headers = http_parse_headers($result); 
$cookobjs = Array(); 
foreach($headers AS $k => $v){ 
    if (strtolower($k)=="set-cookie"){ 
     foreach($v AS $k2 => $v2){ 
      $cookobjs[] = http_parse_cookie($v2); 
     } 
    } 
} 

$cookies = Array(); 
foreach($cookobjs AS $row){ 
    $cookies[] = $row->cookies; 
} 

$tmp = Array(); 
// sort k=>v format 
foreach($cookies AS $v){ 
    foreach ($v AS $k1 => $v1){ 
     $tmp[$k1]=$v1; 
    } 
} 

$cookies = $tmp; 
print_r($cookies); 
27

雖然這個問題很老了,該接受的反應是有效的,我覺得有點unconfortable因爲HTTP響應的內容(HTML,XML,JSON,二進制或其他)變得與頭混合。

我發現了另一種選擇。 CURL提供了一個選項(CURLOPT_HEADERFUNCTION)來設置將針對每個響應標題行調用的回調。該函數將收到curl對象和一個帶有標題行的字符串。

您可以使用這樣的代碼(改編自TML響應):

$cookies = Array(); 
$ch = curl_init('http://www.google.com/'); 
// Ask for the callback. 
curl_setopt($ch, CURLOPT_HEADERFUNCTION, "curlResponseHeaderCallback"); 
$result = curl_exec($ch); 
var_dump($cookies); 

function curlResponseHeaderCallback($ch, $headerLine) { 
    global $cookies; 
    if (preg_match('/^Set-Cookie:\s*([^;]*)/mi', $headerLine, $cookie) == 1) 
     $cookies[] = $cookie; 
    return strlen($headerLine); // Needed by curl 
} 

該解決方案使用全局變量的缺點,但我想這不是短期腳本的問題。如果curl被封裝到一個類中,你總是可以使用靜態方法和屬性。

1

某人在這裏可能會覺得它有用。 hhb_curl_exec2與curl_exec非常類似,但arg3是一個數組,它將填充返回的http頭(數字索引),而arg4是一個數組,它將填充返回的cookie($ cookies [「expires」] =>「星期五,06-May-2016 05:58:51 GMT「),並且arg5將填充... curl提供的原始請求信息。

的缺點是,它需要CURLOPT_RETURNTRANSFER要上,否則報錯了,而且它會覆蓋CURLOPT_STDERR CURLOPT_VERBOSE,如果你已經在使用別的東西..(我以後可能會解決這個問題),如何使用它

例如:

<?php 
header("content-type: text/plain;charset=utf8"); 
$ch=curl_init(); 
$headers=array(); 
$cookies=array(); 
$debuginfo=""; 
$body=""; 
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); 
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); 
$body=hhb_curl_exec2($ch,'https://www.youtube.com/',$headers,$cookies,$debuginfo); 
var_dump('$cookies:',$cookies,'$headers:',$headers,'$debuginfo:',$debuginfo,'$body:',$body); 

和功能本身..

function hhb_curl_exec2($ch, $url, &$returnHeaders = array(), &$returnCookies = array(), &$verboseDebugInfo = "") 
{ 
    $returnHeaders = array(); 
    $returnCookies = array(); 
    $verboseDebugInfo = ""; 
    if (!is_resource($ch) || get_resource_type($ch) !== 'curl') { 
     throw new InvalidArgumentException('$ch must be a curl handle!'); 
    } 
    if (!is_string($url)) { 
     throw new InvalidArgumentException('$url must be a string!'); 
    } 
    $verbosefileh = tmpfile(); 
    $verbosefile = stream_get_meta_data($verbosefileh); 
    $verbosefile = $verbosefile['uri']; 
    curl_setopt($ch, CURLOPT_VERBOSE, 1); 
    curl_setopt($ch, CURLOPT_STDERR, $verbosefileh); 
    curl_setopt($ch, CURLOPT_HEADER, 1); 
    $html    = hhb_curl_exec($ch, $url); 
    $verboseDebugInfo = file_get_contents($verbosefile); 
    curl_setopt($ch, CURLOPT_STDERR, NULL); 
    fclose($verbosefileh); 
    unset($verbosefile, $verbosefileh); 
    $headers  = array(); 
    $crlf   = "\x0d\x0a"; 
    $thepos  = strpos($html, $crlf . $crlf, 0); 
    $headersString = substr($html, 0, $thepos); 
    $headerArr  = explode($crlf, $headersString); 
    $returnHeaders = $headerArr; 
    unset($headersString, $headerArr); 
    $htmlBody = substr($html, $thepos + 4); //should work on utf8/ascii headers... utf32? not so sure.. 
    unset($html); 
    //I REALLY HOPE THERE EXIST A BETTER WAY TO GET COOKIES.. good grief this looks ugly.. 
    //at least it's tested and seems to work perfectly... 
    $grabCookieName = function($str) 
    { 
     $ret = ""; 
     $i = 0; 
     for ($i = 0; $i < strlen($str); ++$i) { 
      if ($str[$i] === ' ') { 
       continue; 
      } 
      if ($str[$i] === '=') { 
       break; 
      } 
      $ret .= $str[$i]; 
     } 
     return urldecode($ret); 
    }; 
    foreach ($returnHeaders as $header) { 
     //Set-Cookie: crlfcoookielol=crlf+is%0D%0A+and+newline+is+%0D%0A+and+semicolon+is%3B+and+not+sure+what+else 
     /*Set-Cookie:ci_spill=a%3A4%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%22305d3d67b8016ca9661c3b032d4319df%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A14%3A%2285.164.158.128%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A109%3A%22Mozilla%2F5.0+%28Windows+NT+6.1%3B+WOW64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F43.0.2357.132+Safari%2F537.36%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1436874639%3B%7Dcab1dd09f4eca466660e8a767856d013; expires=Tue, 14-Jul-2015 13:50:39 GMT; path=/ 
     Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT; 
     //Cookie names cannot contain any of the following '=,; \t\r\n\013\014' 
     // 
     */ 
     if (stripos($header, "Set-Cookie:") !== 0) { 
      continue; 
      /**/ 
     } 
     $header = trim(substr($header, strlen("Set-Cookie:"))); 
     while (strlen($header) > 0) { 
      $cookiename     = $grabCookieName($header); 
      $returnCookies[$cookiename] = ''; 
      $header      = substr($header, strlen($cookiename) + 1); //also remove the = 
      if (strlen($header) < 1) { 
       break; 
      } 
      ; 
      $thepos = strpos($header, ';'); 
      if ($thepos === false) { //last cookie in this Set-Cookie. 
       $returnCookies[$cookiename] = urldecode($header); 
       break; 
      } 
      $returnCookies[$cookiename] = urldecode(substr($header, 0, $thepos)); 
      $header      = trim(substr($header, $thepos + 1)); //also remove the ; 
     } 
    } 
    unset($header, $cookiename, $thepos); 
    return $htmlBody; 
} 

function hhb_curl_exec($ch, $url) 
{ 
    static $hhb_curl_domainCache = ""; 
    //$hhb_curl_domainCache=&$this->hhb_curl_domainCache; 
    //$ch=&$this->curlh; 
    if (!is_resource($ch) || get_resource_type($ch) !== 'curl') { 
     throw new InvalidArgumentException('$ch must be a curl handle!'); 
    } 
    if (!is_string($url)) { 
     throw new InvalidArgumentException('$url must be a string!'); 
    } 

    $tmpvar = ""; 
    if (parse_url($url, PHP_URL_HOST) === null) { 
     if (substr($url, 0, 1) !== '/') { 
      $url = $hhb_curl_domainCache . '/' . $url; 
     } else { 
      $url = $hhb_curl_domainCache . $url; 
     } 
    } 
    ; 

    curl_setopt($ch, CURLOPT_URL, $url); 
    $html = curl_exec($ch); 
    if (curl_errno($ch)) { 
     throw new Exception('Curl error (curl_errno=' . curl_errno($ch) . ') on url ' . var_export($url, true) . ': ' . curl_error($ch)); 
     // echo 'Curl error: ' . curl_error($ch); 
    } 
    if ($html === '' && 203 != ($tmpvar = curl_getinfo($ch, CURLINFO_HTTP_CODE)) /*203 is "success, but no output"..*/) { 
     throw new Exception('Curl returned nothing for ' . var_export($url, true) . ' but HTTP_RESPONSE_CODE was ' . var_export($tmpvar, true)); 
    } 
    ; 
    //remember that curl (usually) auto-follows the "Location: " http redirects.. 
    $hhb_curl_domainCache = parse_url(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL), PHP_URL_HOST); 
    return $html; 
} 
1
curl_setopt($ch, CURLOPT_HEADER, 1); 
    //Return everything 
    $res = curl_exec($ch); 
    //Split into lines 
    $lines = explode("\n", $res); 
    $headers = array(); 
    $body = ""; 
    foreach($lines as $num => $line){ 
     $l = str_replace("\r", "", $line); 
     //Empty line indicates the start of the message body and end of headers 
     if(trim($l) == ""){ 
      $headers = array_slice($lines, 0, $num); 
      $body = $lines[$num + 1]; 
      //Pull only cookies out of the headers 
      $cookies = preg_grep('/^Set-Cookie:/', $headers); 
      break; 
     } 
    } 
相關問題