কীভাবে পিএইচপি কার্ল থেকে কৌনিকগুলি ভেরিয়েবলের মধ্যে পাবেন


126

সুতরাং অন্য কোনও সংস্থার কিছু লোক ভেবেছিল যে যদি সাবান বা এক্সএমএল-আরপিসি বা বিশ্রাম বা অন্য কোনও যুক্তিসঙ্গত যোগাযোগ প্রোটোকল ব্যবহার না করে তিনি কেবলমাত্র শিরোনামের কুকি হিসাবে তার সমস্ত প্রতিক্রিয়া এম্বেড করেছিলেন।

আমি এই কুকিগুলি এই কার্ল প্রতিক্রিয়া থেকে আশাকরি একটি অ্যারে হিসাবে আউট টান প্রয়োজন। এর জন্য পার্সার লেখার জন্য যদি আমার জীবনের একগুচ্ছ অপচয় করতে হয় তবে আমি খুব অসন্তুষ্ট হব।

কেউ কি জানেন যে কীভাবে এটি সহজেই করা যায়, কোনও ফাইলে কিছু না লিখে?

কেউ যদি আমাকে এটির জন্য সাহায্য করতে পারে তবে আমি অত্যন্ত কৃতজ্ঞ হব।

উত্তর:


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
আমি এটি আপনাকে দেব তবে পূর্ববর্তী ম্যাচটি ভুল ছিল। আমি কেবল অধিবেশনটি চাইনি, আপনি কেন এমনটি ভাবেন তা আমি বুঝতে পারি। তবে যে সিস্টেমটি তাদের সিস্টেম তৈরি করেছে তারা কোনও গ্রীক বা পোস্টের মতো পুরো প্রতিক্রিয়া মানচিত্রে কুকিটি লোড করছে। এইরকম ছিলে: সেট-কুকি: দাম = 1 সেট-কুকি: স্থিতি = গ্রহণ আমার '/ ^ সেট-কুকি: (। *?) = (। *?) $ /
এসএম

7
@ তৃষ্ণার্ত93 কার্ল আপনাকে ম্যাপ করা অ্যারে দেয় না। তবে আপনাকে এটি সংরক্ষণের একটি উপায় দেখায়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); }
কম্বাস্টার

39

যদিও এই প্রশ্নটি বেশ পুরানো, এবং স্বীকৃত প্রতিক্রিয়াটি বৈধ, তবে আমি এটি কিছুটা অস্বস্তিকর বলে মনে করি কারণ এইচটিটিপি প্রতিক্রিয়া (এইচটিএমএল, এক্সএমএল, জেএসএন, বাইনারি বা যাই হোক না কেন) এর সামগ্রীগুলি শিরোনামের সাথে মিশে যায়।

আমি একটি ভিন্ন বিকল্প খুঁজে পেয়েছি। সিআরএল 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);
Seph

আপনার যদি ক্লাসে এই সব থাকে তবে কি হবে? আপনি কিভাবে ক্লাস ফাংশন রেফারেন্স $class->curlResponseHeaderCallback()? বা আপনার কি curlResponseHeaderCallbackক্লাসের বাইরে আছে ?
সিরিয়েনার্থস

13

এটি রিজেক্সপস ছাড়াই এটি করে, তবে পিইসিএল এইচটিটিপি এক্সটেনশন প্রয়োজন

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
এর জন্য ধন্যবাদ. একটি স্পষ্ট, অর্থপূর্ণ সমাধানটি কোনও এক্সটেনশন ইনস্টল করার সমস্যার জন্য মূল্যবান।
বেন জ্যাকবস 18

2
এটি সর্বোত্তম সমাধান হবে, যদি কেবল pecl installবাস্তবে কাজ করা হয়। গরগর।
রবিন উইনস্লো

11

আপনি যদি CURLOPT_COOKIE_FILE এবং CURLOPT_COOKIE_JAR কার্ল ব্যবহার করেন তবে / থেকে কোনও ফাইল থেকে কুকিগুলি পড়বে / লিখবে। আপনি এটির সাথে কার্ল হয়ে যাওয়ার পরে, আপনি চান তবে এটি পড়তে এবং / বা সংশোধন করতে পারেন।


12
আমি মনে করি লক্ষ্য এই ফাইলটি ব্যবহার করা নয়
নিকোলাস থেরি

3

libcurl এছাড়াও CURLOPT_COOKIELIST সরবরাহ করে যা সমস্ত পরিচিত কুকিগুলি নিষ্কাশন করে। আপনার কেবলমাত্র পিএইচপি / সিআরএল বাইন্ডিং এটি ব্যবহার করতে পারে তা নিশ্চিত করা।


12
এটি পিএইচপি এপিআইয়ের মাধ্যমে ব্যবহারযোগ্য নয়।
এমেরে ইয়াজিসি

1

এখানে কেউ এটি দরকারী মনে হতে পারে। hhb_curl_exec2 curl_exec এর মতো বেশ কাজ করে তবে arg3 একটি অ্যারে যা প্রত্যাবর্তিত HTTP শিরোনাম (সংখ্যা সূচক) দিয়ে পপুলেশন হবে এবং আরজি 4 একটি অ্যারে যা ফিরিয়ে দেওয়া কুকিজের সাহায্যে (pop কুকিজ ["মেয়াদ শেষ হবে"] => " শুক্র, 06-মে -2016 05:58:51 GMT "), এবং আরজি 5 ... কার্ল দ্বারা করা কাঁচা অনুরোধ সম্পর্কে তথ্য দিয়ে পপুলেশন হবে।

downside হয় যে 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

গৃহীত উত্তরটি দেখে মনে হচ্ছে এটি পুরো প্রতিক্রিয়া বার্তার মাধ্যমে অনুসন্ধান করবে। "সেট-কুকি" শব্দটি যদি কোনও লাইনের শুরুতে থাকে তবে এটি আপনাকে কুকি শিরোলেখগুলির জন্য মিথ্যা ম্যাচ দিতে পারে। যদিও এটি বেশিরভাগ ক্ষেত্রেই ঠিক থাকতে হবে। নিরাপদ উপায় হতে পারে বার্তাটি শুরু থেকে প্রথম খালি লাইন পর্যন্ত পড়া যা বার্তা শিরোনামের শেষটি নির্দেশ করে। এটি কেবলমাত্র একটি বিকল্প সমাধান যা প্রথম ফাঁকা রেখার সন্ধান করা উচিত এবং তারপরে কেবল "সেট-কুকি" সন্ধানের জন্য সেই লাইনে 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 ব্যবহার করা উচিত।
ধনী ওয়ান্ডেল 18

0

আমার বোঝার হ'ল কুকিজ থেকে curl অবশ্যই কোনও ফাইল ( curl -c cookie_file) এ লেখা উচিত । আপনি যদি curlপিএইচপি execবা systemফাংশনগুলি (বা সেই পরিবারের কোনও কিছু) দিয়ে চালিয়ে যাচ্ছেন তবে আপনার কুকিজ কোনও ফাইলে সংরক্ষণ করতে হবে, তারপরে ফাইলটি খুলুন এবং সেগুলি পড়তে পারা উচিত।


4
তিনি প্রায় অবশ্যই php.net/curl উল্লেখ করছেন :)
টিএমএল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.