Я пытаюсь сделать завиток, следуя перенаправлению, но я не могу заставить его работать правильно. У меня есть строка, которую я хочу отправить как параметр GET на сервер и получить результирующий URL.
Пример:
Строка = Кобольдская паразита
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 возвращается до того, как произойдет внешнее перенаправление. Как я могу это исправить?
Чтобы сделать cURL, выполните перенаправление, используйте:
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
Эмм … Я не думаю, что вы на самом деле выполняете завиток … Попробуйте:
curl_exec($ch);
… после настройки параметров и перед curl_getinfo()
.
EDIT: Если вы просто хотите узнать, куда перенаправляется страница, я бы воспользовался здесь советом и просто использовал 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]); }
Добавьте эту строку для зависания инициализации
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
и используйте getinfo до curl_close
$redirectURL = curl_getinfo($ch,CURLINFO_EFFECTIVE_URL );
эс:
$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);
Ответ выше не работал для меня на одном из моих серверов, с чем-то с основами, поэтому я немного переделал его. Код ниже работает на всех моих серверах.
$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:
заголовки (что некоторые сайты делают) или страницы, на которых может быть фраза 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; }
Обратите внимание, что это все еще только одно перенаправление. Чтобы идти глубже, вам действительно нужно получить контент и следовать перенаправлениям.
Иногда вам нужно получить заголовки HTTP, но в то же время вы не хотите возвращать эти заголовки. **
Этот скелет заботится о файлах cookie и перенаправлении 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]); } }
Вы можете использовать:
$redirectURL = curl_getinfo($ch,CURLINFO_REDIRECT_URL);