कैसे एक चर में php कर्ल से कुकीज़ प्राप्त करने के लिए


126

तो किसी अन्य कंपनी के कुछ लड़के ने सोचा कि अगर साबुन या xml-rpc या रेस्ट या किसी अन्य वाजिब संचार प्रोटोकॉल का उपयोग करने के बजाय वह कमाल हो जाए, तो उसने हेडर में कुकीज़ के रूप में अपनी सभी प्रतिक्रिया को एम्बेड कर दिया।

मुझे इन कुकीज़ को इस कर्ल प्रतिक्रिया से एक सरणी के रूप में बाहर खींचने की आवश्यकता है। अगर मुझे अपने जीवन का एक गुच्छा बर्बाद करना है तो इसके लिए एक पार्सर लिखना होगा जिससे मैं बहुत दुखी हो जाऊंगा।

क्या किसी को पता है कि यह कैसे किया जा सकता है, अधिमानतः एक फ़ाइल के लिए कुछ भी लिखे बिना?

अगर कोई मेरी मदद कर सकता है तो मैं बहुत आभारी रहूंगा।

जवाबों:


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

31
दुर्भाग्य से मुझे लग रहा है कि यह सही उत्तर है। मुझे लगता है कि यह हास्यास्पद है कि कर्ल मुझे केवल एक मैप्ड सरणी नहीं सौंप सकता है।
प्यास

3
मैं तुम्हें दे दूँगा लेकिन preg_match गलत था। मैं सिर्फ सत्र नहीं चाहता था, मैं समझता हूं कि आप ऐसा क्यों सोचेंगे। लेकिन जिन प्रतिभाओं ने अपनी प्रणाली बनाई है वे कुकी को एक संपूर्ण प्रतिक्रिया मानचित्र के साथ लोड कर रहे हैं जैसे कि एक पोस्ट या पोस्ट के साथ। इस तरह से शिट करें: सेट-कुकी: मूल्य = 1 सेट-कुकी: स्टेटस = स्वीकार करें कि मुझे '/ ^ सेट-कुकी: (? *?) = (? *?) $ /
Sm

7
@ प्यासा कर्ल नहीं कर सकते हाथ आप एक सरणी सरणी। लेकिन आपको इसे बचाने का एक तरीका दिखाता हैcurl_setopt($ch, CURLOPT_HEADERFUNCTION, 'callback_SaveHeaders');
शिप्पू मोकादिम

2
कुकी संरचना के आधार पर, अंतिम पंक्ति को कुछ इस तरह से संशोधित करने की आवश्यकता हो सकती है parse_str($m[1], $cookies), जो कुकीज़ को $cookiesचर में एक साहचर्य सरणी में भर
देगी

7
: संयुक्त फिक्स के लिए है कि अधिक से अधिक एक कुकी पकड़ लेता है 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); }
Combuster

39

हालाँकि यह प्रश्न काफी पुराना है, और स्वीकृत प्रतिक्रिया मान्य है, मुझे यह थोड़ा असंयमित लगता है क्योंकि HTTP प्रतिक्रिया (HTML, XML, JSON, बाइनरी या जो कुछ भी) की सामग्री हेडर के साथ मिश्रित हो जाती है।

मुझे एक अलग विकल्प मिला है। CURL CURLOPT_HEADERFUNCTIONएक कॉलबैक सेट करने के लिए एक विकल्प ( ) प्रदान करता है जिसे प्रत्येक प्रतिक्रिया हेडर लाइन के लिए कहा जाएगा। फ़ंक्शन को कर्ल ऑब्जेक्ट और हेडर लाइन के साथ एक स्ट्रिंग प्राप्त होगा।

आप इस तरह एक कोड का उपयोग कर सकते हैं (टीएमएल प्रतिक्रिया से अनुकूलित):

$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
}

इस समाधान में एक वैश्विक चर का उपयोग करने का दोष है, लेकिन मुझे लगता है कि यह लघु लिपियों के लिए एक मुद्दा नहीं है। और आप हमेशा स्थैतिक तरीकों और विशेषताओं का उपयोग कर सकते हैं यदि कर्ल को एक वर्ग में लपेटा जा रहा है।


10
एक वैश्विक के बजाय, आप एक संदर्भ को धारण करने वाले क्लोजर का उपयोग कर सकते हैं $cookies$curlResponseHeaderCallback = function ($ch, $headerLine) use (&$cookies) {तब curl_setopt($ch, CURLOPT_HEADERFUNCTION, $curlResponseHeaderCallback);
सिपाही

यदि आपके पास एक कक्षा में यह सब है तो क्या होगा? आप क्लास फंक्शन का संदर्भ कैसे देते हैं $class->curlResponseHeaderCallback()? या आप सिर्फ curlResponseHeaderCallbackकक्षा से बाहर हैं?
सात

13

यह इसे regexps के बिना करता है, लेकिन इसके लिए PECL HTTP एक्सटेंशन की आवश्यकता होती है ।

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

2
इसके लिए धन्यवाद। एक स्पष्ट, अर्थ समाधान एक एक्सटेंशन को स्थापित करने की परेशानी के लायक है।
बेन जैकब्स

2
यह सबसे अच्छा समाधान होगा, अगर केवल pecl installवास्तव में काम किया जाए। गरर।
रॉबिन विंसलो

11

यदि आप CURLOPT_COOKIE_FILE का उपयोग करते हैं और CURLOPT_COOKIE_JAR कर्ल / फ़ाइल से कुकीज़ को पढ़ / लिख देगा। आप इसके साथ कर्ल करने के बाद, इसे पढ़ सकते हैं और / या इसे संशोधित कर सकते हैं, हालांकि आप चाहते हैं।


12
मुझे लगता है कि लक्ष्य इस फ़ाइल का उपयोग नहीं करना है
निकोलस थेरी

3

libcurl CURLOPT_COOKIELIST भी प्रदान करता है जो सभी ज्ञात कुकीज़ को निकालता है। आपको केवल यह सुनिश्चित करना है कि PHP / CURL बाइंडिंग इसका उपयोग कर सकती है।


12
यह PHP एपीआई के माध्यम से प्रयोग करने योग्य नहीं है।
एम्रे यज़ीसी

1

यहाँ कोई इसे उपयोगी पा सकता है। hhb_curl_exec2 curl_exec की तरह बहुत काम करता है, लेकिन arg3 एक ऐसा सरणी है जो लौटे हुए HTTP हेडर (संख्यात्मक सूचकांक) के साथ पॉपुलेटेड होगा, और arg4 एक सरणी है जो लौटे कुकीज़ ($ कुकीज ["एक्सपायर"] => ">" ") से पॉपुलेटेड होगा। शुक्र, 06-मई -2016 05:58:51 जीएमटी "), और arg5 के साथ आबाद हो जाएगा ... कर्ल द्वारा किए गए कच्चे अनुरोध के बारे में जानकारी।

नकारात्मक पक्ष यह है कि इसके लिए CURLOPT_RETURNTRANSFER की आवश्यकता होती है, अन्यथा यह त्रुटि हो जाती है, और यह कि CURLOPT_STDERR और CURLOPT_VERBREE को अधिलेखित कर देगा , यदि आप पहले से ही उन्हें किसी और चीज़ के लिए उपयोग कर रहे थे .. (मैं इसे बाद में ठीक कर सकता हूं)

इसका उपयोग कैसे करें के उदाहरण:

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

स्वीकृत उत्तर ऐसा लगता है कि यह संपूर्ण प्रतिक्रिया संदेश के माध्यम से खोज करेगा। यह आपको कुकी हेडर के लिए गलत मैच दे सकता है यदि शब्द "सेट-कुकी" एक पंक्ति की शुरुआत में है। जबकि यह ज्यादातर मामलों में ठीक होना चाहिए। शुरुआत से संदेश को पढ़ने के लिए सुरक्षित तरीका हो सकता है जब तक कि पहली खाली लाइन जो संदेश हेडर के अंत को इंगित न करे। यह केवल एक वैकल्पिक समाधान है जिसे पहले रिक्त रेखा के लिए देखना चाहिए और फिर "सेट-कुकी" खोजने के लिए उन लाइनों पर preg_grep का उपयोग करना चाहिए।

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

1
स्वीकृत उत्तर ऐसा लगता है कि यह संपूर्ण प्रतिक्रिया संदेश के माध्यम से खोज करेगा। यह आपको कुकी हेडर के लिए गलत मैच दे सकता है यदि शब्द "सेट-कुकी" एक पंक्ति की शुरुआत में है। जबकि यह ज्यादातर मामलों में ठीक होना चाहिए। शुरुआत से संदेश को पढ़ने के लिए सुरक्षित तरीका हो सकता है जब तक कि पहली खाली लाइन जो संदेश हेडर के अंत को इंगित न करे। यह केवल एक वैकल्पिक समाधान है जिसे पहले रिक्त रेखा के लिए देखना चाहिए और फिर "सेट-कुकी" खोजने के लिए उन लाइनों पर preg_grep का उपयोग करना चाहिए।
रिच वंडेल

0

मेरी समझ यह है कि कुकीज को curlफ़ाइल से बाहर लिखा जाना चाहिए ( curl -c cookie_file)। यदि आप curlPHP execया systemफ़ंक्शंस (या उस परिवार में कुछ भी) के माध्यम से चल रहे हैं , तो आपको कुकीज़ को किसी फ़ाइल में सहेजने में सक्षम होना चाहिए, फिर फ़ाइल खोलें और उन्हें पढ़ें।


4
वह लगभग निश्चित रूप से php.net/curl का उल्लेख कर रहा है :)
TML
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.