मैं कैसे पा सकता हूं कि मुझे CURL का उपयोग करके पुनर्निर्देशित किया जाएगा?


149

मैं कर्ल को पुनर्निर्देशित करने की कोशिश कर रहा हूं, लेकिन मैं इसे सही काम करने के लिए नहीं पा सकता हूं। मेरे पास एक स्ट्रिंग है जिसे मैं एक सर्वर पर GET परम के रूप में भेजना चाहता हूं और परिणामी URL प्राप्त करना चाहता हूं।

उदाहरण:

स्ट्रिंग = कोबोल्ड वर्मिन यूरल
= www.wowhead.com/search?q=Kobold+Worker

यदि आप उस url पर जाते हैं, तो यह आपको "www.wowhead.com/npc=257" पर पुनर्निर्देशित करेगा। मैं इस URL को अपने PHP कोड में वापस करना चाहता हूं ताकि मैं "npc = 257" निकाल सकूं और इसका उपयोग कर सकूं।

वर्तमान कोड:

function npcID($name) {
    $urltopost = "http://www.wowhead.com/search?q=" . $name;
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1");
    curl_setopt($ch, CURLOPT_URL, $urltopost);
    curl_setopt($ch, CURLOPT_REFERER, "http://www.wowhead.com");
    curl_setopt($ch, CURLOPT_HTTPHEADER, Array("Content-Type:application/x-www-form-urlencoded"));
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
    return curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
}

हालांकि यह www.wowhead.com/search?q=Kobold+Worker और न कि www.wowhead.com/npc=257 देता है

मुझे संदेह है कि बाहरी रीडायरेक्ट होने से पहले PHP वापस आ रहा है। मैं इसे कैसे ठीक करूं?


8
यह "कर्ल फॉलो रिडायरेक्ट्स" के लिए शीर्ष प्रश्नों में से एक है। स्वचालित रूप से curlकमांड का उपयोग करके रीडायरेक्ट का पालन करने के लिए, -Lया --locationध्वज को पास करें । जैसेcurl -L http://example.com/
रॉब डब्ल्यू

जवाबों:


256

CURL को पुनर्निर्देशित करने के लिए उपयोग करें:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

एर्म ... मुझे नहीं लगता कि आप वास्तव में कर्ल निष्पादित कर रहे हैं ... कोशिश करें:

curl_exec($ch);

... विकल्प सेट करने के बाद, और curl_getinfo()कॉल से पहले ।

संपादित करें: यदि आप केवल यह जानना चाहते हैं कि कोई पृष्ठ कहां पर पुनर्निर्देशित करता है, तो मैं यहां सलाह का उपयोग करूंगा , और हेडर को हथियाने और स्थान निकालने के लिए कर्ल का उपयोग करूंगा: उनमें से शीर्ष लेख:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
if (preg_match('~Location: (.*)~i', $result, $match)) {
   $location = trim($match[1]);
}

2
यह php को रीडायरेक्ट करता है। मैं रीडायरेक्ट का अनुसरण नहीं करना चाहता, मैं केवल रीडायरेक्ट किए गए पृष्ठ का url जानना चाहता हूं।
थॉमस वान नफेल

9
ओह, तो आप वास्तव में पृष्ठ प्राप्त नहीं करना चाहते हैं? बस स्थान का पता लगाएं? उस स्थिति में, मैं यहाँ इस्तेमाल की जाने वाली युक्ति का सुझाव दूंगा : zzz.rezo.net/HowTo-Expand-Short-URLs.html - मूल रूप से पृष्ठ को रीडायरेक्ट करने वाले हेडर को फिर से पकड़ो, और उसके स्थान को खोजें: हेडर। किसी भी तरह से, हालांकि, आपको अभी भी कर्ल के लिए निष्पादन () वास्तव में कुछ भी करने की ज़रूरत है ...
मैट गिब्सन

1
मेरा सुझाव है कि नीचे दिए गए लुका कैमिलोस समाधान पर एक नज़र डालें, क्योंकि यह समाधान कई पुनर्निर्देशन को ध्यान में नहीं रखता है।
ईसाई एंगेल

यह समाधान उसी url के भीतर नया वेबपृष्ठ खोलता है। मैं उस url के मापदंडों को पोस्ट करने के साथ url को भी बदलना चाहता हूं। मैं उसे कैसे प्राप्त कर सकता हूं?
अमनपुरोहित

@MattGibson जब मैं $ httpCode = curl_getinfo ($ हैंडल, CURLINFO_HTTP_CODE) का उपयोग करता हूं; CURLOPT_FOLLOWLOCATION के साथ सही करने के लिए सेट करें कि httpcode क्या होगा। मेरा मतलब है कि यह पहले url के लिए होगा या रीडायरेक्ट url के लिए होगा
Manigandan Arjunan

26

इस लाइन को कर्लिज़ेशन को कर्ल करने के लिए जोड़ें

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

और curl_close से पहले getinfo का उपयोग करें

$redirectURL = curl_getinfo($ch,CURLINFO_EFFECTIVE_URL );

es:

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,0); 
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
$html = curl_exec($ch);
$redirectURL = curl_getinfo($ch,CURLINFO_EFFECTIVE_URL );
curl_close($ch);

2
मुझे लगता है कि यह एक बेहतर उपाय है, क्योंकि यह कई पुनर्निर्देशन को भी उजागर करता है।
ईसाई एंगेल

याद रखें: (ok, duh) POST डेटा को रीडायरेक्ट के बाद फिर से सबमिट नहीं किया जाएगा। मेरे मामले में ऐसा हुआ और मुझे बाद में बेवकूफी महसूस हुई क्योंकि: बस उचित यूआरएल का उपयोग करें और यह तय हो गया है।
जूनियर

का उपयोग करना curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);सुरक्षा भेद्यता है। यह अनिवार्य रूप से कहता है कि "एसएसएल त्रुटियों को अनदेखा करें यदि यह टूटा हुआ है - जैसा कि आप एक अनएन्क्रिप्टेड URL पर भरोसा करेंगे।"
चालाकी

8

ऊपर दिए गए जवाब ने मेरे एक सर्वर पर, कुछ के लिए, आधार के साथ काम नहीं किया, इसलिए मैंने इसे फिर से छोटा कर दिया। नीचे दिया गया कोड मेरे सभी सर्वरों पर काम करता है।

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$a = curl_exec($ch);
curl_close( $ch ); 
// the returned headers
$headers = explode("\n",$a);
// if there is no redirection this will be the final url
$redir = $url;
// loop through the headers and check for a Location: str
$j = count($headers);
for($i = 0; $i < $j; $i++){
// if we find the Location header strip it and fill the redir var       
if(strpos($headers[$i],"Location:") !== false){
        $redir = trim(str_replace("Location:","",$headers[$i]));
        break;
    }
}
// do whatever you want with the result
echo redir;

Location: हैडर हमेशा एक रीडायरेक्ट पालन करने के लिए नहीं है। कृपया एक प्रश्न भी देखें जो स्पष्ट रूप से इस बारे में है: कर्ल फॉलो लोकेशन एरर
hakre

5

यहाँ चुना गया उत्तर शालीन है, लेकिन इसका मामला संवेदनशील है, रिश्तेदार location:हेडर (जो कुछ साइटें करते हैं) या उन पेजों से रक्षा नहीं करता है, जो वास्तव Location:में उनकी सामग्री में वाक्यांश हो सकते हैं ... (जो वर्तमान में zillow करता है)।

थोड़ा टेढ़ा है, लेकिन एक जोड़े को यह थोड़ा होशियार बनाने के लिए संपादन करता है:

function getOriginalURL($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    $result = curl_exec($ch);
    $httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    // if it's not a redirection (3XX), move along
    if ($httpStatus < 300 || $httpStatus >= 400)
        return $url;

    // look for a location: header to find the target URL
    if(preg_match('/location: (.*)/i', $result, $r)) {
        $location = trim($r[1]);

        // if the location is a relative URL, attempt to make it absolute
        if (preg_match('/^\/(.*)/', $location)) {
            $urlParts = parse_url($url);
            if ($urlParts['scheme'])
                $baseURL = $urlParts['scheme'].'://';

            if ($urlParts['host'])
                $baseURL .= $urlParts['host'];

            if ($urlParts['port'])
                $baseURL .= ':'.$urlParts['port'];

            return $baseURL.$location;
        }

        return $location;
    }
    return $url;
}

ध्यान दें कि यह अभी भी केवल 1 पुनर्निर्देशन गहरा जाता है। गहराई तक जाने के लिए, आपको वास्तव में सामग्री प्राप्त करने और रीडायरेक्ट का पालन करने की आवश्यकता है।


5

कभी-कभी आपको HTTP हेडर प्राप्त करने की आवश्यकता होती है, लेकिन साथ ही आप उन हेडर को वापस नहीं चाहते हैं।

यह कंकाल पुनरावर्तन का उपयोग करके कुकीज़ और HTTP पुनर्निर्देशन का ध्यान रखता है। यहाँ मुख्य विचार क्लाइंट कोड में HTTP हेडर वापस करने से बचना है

आप इसके ऊपर एक बहुत मजबूत कर्ल क्लास बना सकते हैं। POST कार्यक्षमता जोड़ें, आदि।

<?php

class curl {

  static private $cookie_file            = '';
  static private $user_agent             = '';  
  static private $max_redirects          = 10;  
  static private $followlocation_allowed = true;

  function __construct()
  {
    // set a file to store cookies
    self::$cookie_file = 'cookies.txt';

    // set some general User Agent
    self::$user_agent = 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)';

    if ( ! file_exists(self::$cookie_file) || ! is_writable(self::$cookie_file))
    {
      throw new Exception('Cookie file missing or not writable.');
    }

    // check for PHP settings that unfits
    // correct functioning of CURLOPT_FOLLOWLOCATION 
    if (ini_get('open_basedir') != '' || ini_get('safe_mode') == 'On')
    {
      self::$followlocation_allowed = false;
    }    
  }

  /**
   * Main method for GET requests
   * @param  string $url URI to get
   * @return string      request's body
   */
  static public function get($url)
  {
    $process = curl_init($url);    

    self::_set_basic_options($process);

    // this function is in charge of output request's body
    // so DO NOT include HTTP headers
    curl_setopt($process, CURLOPT_HEADER, 0);

    if (self::$followlocation_allowed)
    {
      // if PHP settings allow it use AUTOMATIC REDIRECTION
      curl_setopt($process, CURLOPT_FOLLOWLOCATION, true);
      curl_setopt($process, CURLOPT_MAXREDIRS, self::$max_redirects); 
    }
    else
    {
      curl_setopt($process, CURLOPT_FOLLOWLOCATION, false);
    }

    $return = curl_exec($process);

    if ($return === false)
    {
      throw new Exception('Curl error: ' . curl_error($process));
    }

    // test for redirection HTTP codes
    $code = curl_getinfo($process, CURLINFO_HTTP_CODE);
    if ($code == 301 || $code == 302)
    {
      curl_close($process);

      try
      {
        // go to extract new Location URI
        $location = self::_parse_redirection_header($url);
      }
      catch (Exception $e)
      {
        throw $e;
      }

      // IMPORTANT return 
      return self::get($location);
    }

    curl_close($process);

    return $return;
  }

  static function _set_basic_options($process)
  {

    curl_setopt($process, CURLOPT_USERAGENT, self::$user_agent);
    curl_setopt($process, CURLOPT_COOKIEFILE, self::$cookie_file);
    curl_setopt($process, CURLOPT_COOKIEJAR, self::$cookie_file);
    curl_setopt($process, CURLOPT_RETURNTRANSFER, 1);
    // curl_setopt($process, CURLOPT_VERBOSE, 1);
    // curl_setopt($process, CURLOPT_SSL_VERIFYHOST, false);
    // curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);
  }

  static function _parse_redirection_header($url)
  {
    $process = curl_init($url);    

    self::_set_basic_options($process);

    // NOW we need to parse HTTP headers
    curl_setopt($process, CURLOPT_HEADER, 1);

    $return = curl_exec($process);

    if ($return === false)
    {
      throw new Exception('Curl error: ' . curl_error($process));
    }

    curl_close($process);

    if ( ! preg_match('#Location: (.*)#', $return, $location))
    {
      throw new Exception('No Location found');
    }

    if (self::$max_redirects-- <= 0)
    {
      throw new Exception('Max redirections reached trying to get: ' . $url);
    }

    return trim($location[1]);
  }

}

0

यहाँ वास्तव में मैं उन्हें इस तरह से अधिक स्थिर हो सकता है, इस तथ्य के बावजूद लॉट रेगेक्स के यहाँ,:

$resultCurl=curl_exec($curl); //get curl result
//Optional line if you want to store the http status code
$headerHttpCode=curl_getinfo($curl,CURLINFO_HTTP_CODE);

//let's use dom and xpath
$dom = new \DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML($resultCurl, LIBXML_HTML_NODEFDTD);
libxml_use_internal_errors(false);
$xpath = new \DOMXPath($dom);
$head=$xpath->query("/html/body/p/a/@href");

$newUrl=$head[0]->nodeValue;

स्थान भाग HTML में एक लिंक है जिसे अपाचे द्वारा भेजा गया है। तो Xpath इसे पुनर्प्राप्त करने के लिए एकदम सही है।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.