Как я могу найти, куда я буду перенаправлен с помощью cURL?

Я пытаюсь заставить curl следовать перенаправлению, но я не могу заставить его работать правильно. У меня есть строка, которую я хочу отправить в качестве параметра GET на сервер и получить полученный URL-адрес.

Пример:

Строка = Кобольд Паразиты
Url = www. Wowhead. ком / поиск? q = Кобольд + Рабочий

Если вы перейдете по этому URL, он перенаправит вас на "www. Wowhead. ком / ВСНП = 257" . Я хочу, чтобы curl возвращал этот 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. ком / поиск? q = кобольд + рабочий , а не www. Wowhead. com / npc = 257 .

Я подозреваю, что PHP возвращается до того, как произойдет внешнее перенаправление. Как я могу это исправить?

вопрос задан 19.08.2010
Thomas Van Nuffel
719 репутация

6 ответов


  • 227 рейтинг

    Чтобы cURL следовал за перенаправлением, используйте:

    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    

    Erm. , , Я не думаю, что вы на самом деле выполняете локон. , , Попробуйте:

    curl_exec($ch);

    . , , после настройки параметров и до вызова curl_getinfo().

    РЕДАКТИРОВАТЬ: Если вы просто хотите узнать, куда перенаправляется страница, я бы воспользовался советом здесь , и просто использовать Curl, чтобы захватить заголовки и извлечь из них заголовок Location:

    $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]);
    }
    
    ответ дан Matt Gibson, с репутацией 32295, 19.08.2010
  • 19 рейтинг

    Добавить эту строку для инициализации скручивания

    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    

    и используйте getinfo перед curl_close

    $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);
    
    ответ дан Luca Camillo, с репутацией 379, 11.02.2015
  • 8 рейтинг

    Ответ выше не работал для меня на одном из моих серверов, что-то, что связано с basedir, поэтому я немного перефразировал его. Код ниже работает на всех моих серверах.

    $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;
    
    ответ дан GR1NN3R, с репутацией 81, 22.03.2011
  • 4 рейтинг

    Иногда вам нужно получить заголовки HTTP, но в то же время вы не хотите возвращать эти заголовки. **

    Этот скелет заботится о куки и перенаправлениях HTTP с помощью рекурсии. Основная идея здесь - , чтобы избежать возврата HTTP-заголовков в код клиента.

    Вы можете создать очень сильный класс локонов над ним. Добавить функциональность POST и т. Д.

    ответ дан Igor Parra, с репутацией 7013, 5.02.2014
  • 4 рейтинг

    Выбранный здесь ответ является приличным, но учитывает регистр, не защищает от относительных заголовков 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 перенаправление глубоко. Чтобы пойти глубже, вам действительно нужно получить контент и следовать перенаправлениям.

    ответ дан broox, с репутацией 2263, 23.10.2013
  • -3 рейтинг

    Вы можете использовать:

    $redirectURL = curl_getinfo($ch,CURLINFO_REDIRECT_URL);
    
    ответ дан Abhilash Nayak, с репутацией 1, 18.12.2014