所以一些其他公司的人認爲這將是可怕的,而不是使用soap或xml-rpc或休息或任何其他合理的通信協議,他只是嵌入他的所有響應作爲標頭中的Cookie。如何從一個PHP捲曲獲取cookie到一個變量
我需要從這個捲曲響應中拉出這些cookie作爲希望的數組。如果我不得不浪費大量時間爲此寫一個解析器,我會很不高興。
有誰知道這可以簡單地完成,最好不寫任何文件?
如果有人能幫助我解決這個問題,我將不勝感激。
所以一些其他公司的人認爲這將是可怕的,而不是使用soap或xml-rpc或休息或任何其他合理的通信協議,他只是嵌入他的所有響應作爲標頭中的Cookie。如何從一個PHP捲曲獲取cookie到一個變量
我需要從這個捲曲響應中拉出這些cookie作爲希望的數組。如果我不得不浪費大量時間爲此寫一個解析器,我會很不高興。
有誰知道這可以簡單地完成,最好不寫任何文件?
如果有人能幫助我解決這個問題,我將不勝感激。
$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);
如果使用CURLOPT_COOKIE_FILE和CURLOPT_COOKIE_JAR,curl將從文件讀取/寫入cookie。您可以在捲曲完成後,根據需要閱讀和/或修改它。
我認爲我們的目標是不使用這個文件 – 2013-01-04 15:54:46
我的理解是,必須將curl
的cookies寫入文件(curl -c cookie_file
)。如果你正在運行curl
通過PHP的exec
或system
功能(或該族中的任何東西),你應該能夠餅乾保存到一個文件,然後打開文件,並在閱讀它們。
他幾乎肯定是指php.net/curl :) – TML 2009-05-22 06:12:20
的libcurl也提供CURLOPT_COOKIELIST,提取所有已知的Cookie。所有你需要的是確保PHP/CURL綁定可以使用它。
這樣做沒有正則表達式,但需要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);
雖然這個問題很老了,該接受的反應是有效的,我覺得有點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被封裝到一個類中,你總是可以使用靜態方法和屬性。
某人在這裏可能會覺得它有用。 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;
}
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;
}
}
不幸的是,我有一種感覺,這是正確的答案。我認爲它的荒謬之處在於,curl不能只是給我一個映射數組。 – thirsty93 2009-05-22 15:26:53
我會給你,但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
不夠接近,那麼? – TML 2009-05-24 05:48:38