Как я могу проверить, существует ли URL через PHP?
на некоторых веб-сайтах есть разные $file_headers[0] на странице ошибок. например, youtube.com. его страница с ошибкой имеет значение HTTP/1.0 404 Not Found (разница составляет 1,0 и 1,1). что делать то?
@KrishnaRajK Вместо if ($ file_headers [0] == ‘HTTP / 1.1 404 Not Found’) вы должны сделать if (($ file_headers [0] == ‘HTTP / 1.1 404 Not Found’) || ($ file_headers [ 0] == ‘HTTP / 1.0 404 Not Found’)) Возможно, есть еще более простой метод, но это должно помочь вам.
@alexandru.topliceanualexandru.topliceanu Текстовое состояние «Не найдено» не является обязательным; разработчики могут положить туда все, что хотят, это все еще действует.
Помните, что get_headers вернет логическое значение false, если произойдет ошибка (например, DNS не разрешается). Поэтому убедитесь, что сначала проверили, не является ли get_headers логическим значением false, прежде чем тестировать, если он содержит коды ответов HTTP.
Чтобы сэкономить время и пропускную способность, вы можете использовать запрос HEAD вместо GET с: stream_context_set_default (array (‘http’ => array (‘method’ => ‘HEAD’, ‘timeout’ => 1.5, ‘ignore_errors’ => true, )));
Когда выясняется, существует ли url из php, есть несколько вещей, на которые следует обратить внимание:
- Является ли сам URL действительным (строка, а не пустой, хороший синтаксис), это быстро проверить сервер.
- Ожидание ответа может занять время и выполнить блок-код.
- Не все заголовки, возвращенные get_headers(), хорошо сформированы.
- Используйте curl (если можете).
- Предотвратить выборку всего тела/содержимого, но запрашивать только заголовки.
- Рассмотрим перенаправление URL-адресов:
- Вы хотите вернуть первый код?
- Или выполните все переадресации и верните последний код?
- У вас может быть 200, но он может перенаправляться с помощью метатег или javascript. Выяснение того, что происходит после, непросто.
Имейте в виду, что любой метод, который вы используете, требует времени, чтобы дождаться ответа.
Весь код может (и, вероятно, будет) останавливаться до тех пор, пока вы не узнаете результат или не запрограммировали запросы.Например: приведенный ниже код может занять долгое время, чтобы отобразить страницу, если URL-адреса являются недопустимыми или недоступными:
$url) < // this could potentially take 0-30 seconds each // (more or less depending on connection, target site, timeout settings. ) if( ! isValidUrl($url) )< unset($urls[$k]); >> echo "yay all done! now show my site"; foreach($urls as $url)< echo "\">
"; >Функции ниже могут быть полезными, вы, вероятно, захотите изменить их в соответствии с вашими потребностями:
function isValidUrl($url) < // first do some quick sanity checks: if(!$url || !is_string($url))< return false; >// quick check url is roughly a valid http request: ( http://blah/. ) if( ! preg_match('/^http(s)?:\/\/[a-z0-9-]+(\.[a-z0-9-]+)*(:3+)?(\/.*)?$/i', $url) ) < return false; >// the next bit could be slow: if(getHttpResponseCode_using_curl($url) != 200) < // if(getHttpResponseCode_using_getheaders($url) != 200)< // use this one if you cant use curl return false; >// all good! return true; > function getHttpResponseCode_using_curl($url, $followredirects = true) < // returns int responsecode, or false (if url does not exist or connection timeout occurs) // NOTE: could potentially take up to 0-30 seconds , blocking further code execution (more or less depending on connection, target site, and local timeout settings)) // if $followredirects == false: return the FIRST known httpcode (ignore redirects) // if $followredirects == true : return the LAST known httpcode (when redirected) if(! $url || ! is_string($url))< return false; >$ch = @curl_init($url); if($ch === false) < return false; >@curl_setopt($ch, CURLOPT_HEADER ,true); // we want headers @curl_setopt($ch, CURLOPT_NOBODY ,true); // dont need body @curl_setopt($ch, CURLOPT_RETURNTRANSFER ,true); // catch output (do NOT print!) if($followredirects)< @curl_setopt($ch, CURLOPT_FOLLOWLOCATION ,true); @curl_setopt($ch, CURLOPT_MAXREDIRS ,10); // fairly random number, but could prevent unwanted endless redirects with followlocation=true >else < @curl_setopt($ch, CURLOPT_FOLLOWLOCATION ,false); >// @curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,5); // fairly random number (seconds). but could prevent waiting forever to get a result // @curl_setopt($ch, CURLOPT_TIMEOUT ,6); // fairly random number (seconds). but could prevent waiting forever to get a result // @curl_setopt($ch, CURLOPT_USERAGENT ,"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1"); // pretend we're a regular browser @curl_exec($ch); if(@curl_errno($ch)) < // should be 0 @curl_close($ch); return false; >$code = @curl_getinfo($ch, CURLINFO_HTTP_CODE); // note: php.net documentation shows this returns a string, but really it returns an int @curl_close($ch); return $code; > function getHttpResponseCode_using_getheaders($url, $followredirects = true) < // returns string responsecode, or false if no responsecode found in headers (or url does not exist) // NOTE: could potentially take up to 0-30 seconds , blocking further code execution (more or less depending on connection, target site, and local timeout settings)) // if $followredirects == false: return the FIRST known httpcode (ignore redirects) // if $followredirects == true : return the LAST known httpcode (when redirected) if(! $url || ! is_string($url))< return false; >$headers = @get_headers($url); if($headers && is_array($headers)) < if($followredirects)< // we want the the last errorcode, reverse array so we start at the end: $headers = array_reverse($headers); >foreach($headers as $hline) < // search for things like "HTTP/1.1 200 OK" , "HTTP/1.0 200 OK" , "HTTP/1.1 301 PERMANENTLY MOVED" , "HTTP/1.1 400 Not Found" , etc. // note that the exact syntax/version/output differs, so there is some string magic involved here if(preg_match('/^HTTP\/\S+\s+(765)\s+.*/', $hline, $matches) )/ "HTTP/*** ### ***" $code = $matches[1]; return $code; >> // no HTTP/xxx found in headers: return false; > // no headers : return false; >
если у кого-то есть такая же проблема, проверьте dns-nameservers .. используйте opendns без перенаправлений stackoverflow.com/a/11072947/1829460
+1 для того, чтобы быть единственным ответом, чтобы иметь дело с перенаправлениями. Изменен return $code if($code == 200)
return false; перебирать только успехи @PKHunter Нет. Мое быстрое регулярное выражение preg_match было простым примером и не будет соответствовать всем URL-адресам, перечисленным там. Посмотрите этот тестовый URL: regex101.com/r/EpyDDc/2 Если вы хотите лучший вариант , замените его на тот, который указан в вашей ссылке ( mathiasbynens.be/demo/url-regex ) из diegoperini; похоже, что они совпадают со всеми, смотрите эту тестовую ссылку: regex101.com/r/qMQp23/1
$headers = @get_headers($this->_value); if(strpos($headers[0],'200')===false)return false;
поэтому в любое время, когда вы связываетесь с сайтом и получаете что-то еще, чем 200, он будет работать
Выше в одной строке: return strpos(@get_headers($url)[0],’200′) === false ? false : true Может быть полезным.
$ this в PHP является ссылкой на текущий объект. Ссылка: php.net/manual/en/language.oop5.basic.php Учебник для начинающих : phpro.org/tutorials/Object-Oriented-Programming-with-PHP.html Скорее всего, фрагмент кода был взят из класса и не исправлен соответствующим образом ,
вы не можете использовать завиток на определенных серверах u можете использовать этот код
function URLIsValid($URL) < $exists = true; $file_headers = @get_headers($URL); $InvalidHeaders = array('404', '403', '500'); foreach($InvalidHeaders as $HeaderVal) < if(strstr($file_headers[0], $HeaderVal)) < $exists = false; break; >> return $exists; >
$url = 'http://google.com'; $not_url = 'stp://google.com'; if (@file_get_contents($url)): echo "Found '$url'!"; else: echo "Can't find '$url'."; endif; if (@file_get_contents($not_url)): echo "Found '$not_url!"; else: echo "Can't find '$not_url'."; endif; // Found 'http://google.com'!Can't find 'stp://google.com'.
/** * @param $url * @param array $options * @return string * @throws Exception */ function checkURL($url, array $options = array()) < if (empty($url)) < throw new Exception('URL is empty'); >// list of HTTP status codes $httpStatusCodes = array( 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-Status', 208 => 'Already Reported', 226 => 'IM Used', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Switch Proxy', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Payload Too Large', 414 => 'Request-URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Requested Range Not Satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 425 => 'Unordered Collection', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 449 => 'Retry With', 450 => 'Blocked by Windows Parental Controls', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 509 => 'Bandwidth Limit Exceeded', 510 => 'Not Extended', 511 => 'Network Authentication Required', 599 => 'Network Connect Timeout Error' ); $ch = curl_init($url); curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); if (isset($options['timeout'])) < $timeout = (int) $options['timeout']; curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); >curl_exec($ch); $returnedStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if (array_key_exists($returnedStatusCode, $httpStatusCodes)) < return "URL: '' - Error code: - Definition: "; > else < return "'' does not exist"; > >
Решение karim79 get_headers() не сработало для меня, поскольку я получил безумные результаты с Pinterest.
get_headers(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed Array ( [url] => https://www.pinterest.com/jonathan_parl/ [exists] => ) get_headers(): Failed to enable crypto Array ( [url] => https://www.pinterest.com/jonathan_parl/ [exists] => ) get_headers(https://www.pinterest.com/jonathan_parl/): failed to open stream: operation failed Array ( [url] => https://www.pinterest.com/jonathan_parl/ [exists] => )
В любом случае, этот разработчик демонстрирует, что cURL быстрее, чем get_headers():
Поскольку многие люди просили karim79 исправить решение cURL, вот решение, которое я построил сегодня.
/** * Send an HTTP request to a the $url and check the header posted back. * * @param $url String url to which we must send the request. * @param $failCodeList Int array list of code for which the page is considered invalid. * * @return Boolean */ public static function isUrlExists($url, array $failCodeList = array(404)) < $exists = false; if(!StringManager::stringStartWith($url, "http") and !StringManager::stringStartWith($url, "ftp"))< $url = "https://" . $url; >if (preg_match(RegularExpression::URL, $url)) < $handle = curl_init($url); curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($handle, CURLOPT_HEADER, true); curl_setopt($handle, CURLOPT_NOBODY, true); curl_setopt($handle, CURLOPT_USERAGENT, true); $headers = curl_exec($handle); curl_close($handle); if (empty($failCodeList) or !is_array($failCodeList))< $failCodeList = array(404); >if (!empty($headers)) < $exists = true; $headers = explode(PHP_EOL, $headers); foreach($failCodeList as $code)< if (is_numeric($code) and strpos($headers[0], strval($code)) !== false)< $exists = false; break; >> > > return $exists; >
Позвольте мне объяснить варианты завитка:
CURLOPT_RETURNTRANSFER: верните строку вместо отображения вызывающей страницы на экране.
CURLOPT_SSL_VERIFYPEER: cUrl не проверяет сертификат
CURLOPT_HEADER: включить заголовок в строку
CURLOPT_NOBODY: не включать тело в строку
CURLOPT_USERAGENT. Некоторым сайтам необходимо правильно функционировать (например: https://plus.google.com)
Дополнительная заметка. В этой функции я использую регулярное выражение Diego Perini для проверки URL-адреса перед отправкой запроса:
const URL = "%^(?:(?:https?|ftp)://)(?:\S+(. \S*)?@|\d(?:\.\d)|(?:(?:[a-z\d\x-\x]+-?)*[a-z\d\x-\x]+)(?:\.(?:[a-z\d\x-\x]+-?)*[a-z\d\x-\x]+)*(?:\.[a-z\x-\x]))(. \d+)?(?:[^\s]*)?$%iu"; //@copyright Diego Perini
Дополнительная заметка 2: я взорву строку заголовка и заголовки пользователя [0], чтобы убедиться, что только проверка только кода возврата и сообщения (пример: 200, 404, 405 и т.д.)
Дополнительная заметка 3. Иногда проверка только кода 404 недостаточна (см. unit test), так что необязательный параметр $failCodeList предоставляет все отклоненные коды.
И, конечно, здесь unit test (включая всю популярную социальную сеть), чтобы узаконить мое кодирование:
public function testIsUrlExists()< //invalid $this->assertFalse(ToolManager::isUrlExists("woot")); $this->assertFalse(ToolManager::isUrlExists("https://www.facebook.com/jonathan.parentlevesque4545646456")); $this->assertFalse(ToolManager::isUrlExists("https://plus.google.com/+JonathanParentL%C3%A9vesque890800")); $this->assertFalse(ToolManager::isUrlExists("https://instagram.com/mariloubiz1232132/", array(404, 405))); $this->assertFalse(ToolManager::isUrlExists("https://www.pinterest.com/jonathan_parl1231/")); $this->assertFalse(ToolManager::isUrlExists("https://regex101.com/546465465456")); $this->assertFalse(ToolManager::isUrlExists("https://twitter.com/arcadefire4566546")); $this->assertFalse(ToolManager::isUrlExists("https://vimeo.com/**($%?%$", array(400, 405))); $this->assertFalse(ToolManager::isUrlExists("https://www.youtube.com/user/Darkjo666456456456")); //valid $this->assertTrue(ToolManager::isUrlExists("www.google.ca")); $this->assertTrue(ToolManager::isUrlExists("https://www.facebook.com/jonathan.parentlevesque")); $this->assertTrue(ToolManager::isUrlExists("https://plus.google.com/+JonathanParentL%C3%A9vesque")); $this->assertTrue(ToolManager::isUrlExists("https://instagram.com/mariloubiz/")); $this->assertTrue(ToolManager::isUrlExists("https://www.facebook.com/jonathan.parentlevesque")); $this->assertTrue(ToolManager::isUrlExists("https://www.pinterest.com/")); $this->assertTrue(ToolManager::isUrlExists("https://regex101.com")); $this->assertTrue(ToolManager::isUrlExists("https://twitter.com/arcadefire")); $this->assertTrue(ToolManager::isUrlExists("https://vimeo.com/")); $this->assertTrue(ToolManager::isUrlExists("https://www.youtube.com/user/Darkjo666")); >
Джонатан Роланд-Левенк из Монреаля