Простой способ проверить URL-адрес для 404 в PHP?

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

Поэтому мне нужно проверить в верхней части кода, чтобы проверить, возвращает ли URL 404 или нет.

Это похоже на довольно прямолинейную задачу, но Google не дает мне никаких ответов. Я беспокоюсь, что искал неправильный материал.

В одном блоге рекомендуется использовать это:

$valid = @fsockopen($url, 80, $errno, $errstr, 30); 

а затем проверить, есть ли $ valid, если пусто или нет.

Но я думаю, что URL-адрес, который дает мне проблемы, имеет перенаправление на него, поэтому значение $ valid становится пустым для всех значений. Или, возможно, я делаю что-то еще неправильно.

Я также рассмотрел «запрос главы», но мне еще не удалось найти какие-либо примеры кода, с которыми я могу играть или попробовать.

Предложения? И что это за скручивание?

Если вы используете привязки curl PHP, вы можете проверить код ошибки с помощью curl_getinfo как таковой:

 $handle = curl_init($url); curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE); /* Get the HTML or whatever is linked in $url. */ $response = curl_exec($handle); /* Check for 404 (file not found). */ $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE); if($httpCode == 404) { /* Handle 404 here. */ } curl_close($handle); /* Handle $response here. */ 

Если вы используете php5, вы можете использовать:

 $url = 'http://www.example.com'; print_r(get_headers($url, 1)); 

Кроме того, с помощью php4 пользователь внес вклад в следующее:

 /** This is a modified version of code from "stuart at sixletterwords dot com", at 14-Sep-2005 04:52. This version tries to emulate get_headers() function at PHP4. I think it works fairly well, and is simple. It is not the best emulation available, but it works. Features: - supports (and requires) full URLs. - supports changing of default port in URL. - stops downloading from socket as soon as end-of-headers is detected. Limitations: - only gets the root URL (see line with "GET / HTTP/1.1"). - don't support HTTPS (nor the default HTTPS port). */ if(!function_exists('get_headers')) { function get_headers($url,$format=0) { $url=parse_url($url); $end = "\r\n\r\n"; $fp = fsockopen($url['host'], (empty($url['port'])?80:$url['port']), $errno, $errstr, 30); if ($fp) { $out = "GET / HTTP/1.1\r\n"; $out .= "Host: ".$url['host']."\r\n"; $out .= "Connection: Close\r\n\r\n"; $var = ''; fwrite($fp, $out); while (!feof($fp)) { $var.=fgets($fp, 1280); if(strpos($var,$end)) break; } fclose($fp); $var=preg_replace("/\r\n\r\n.*\$/",'',$var); $var=explode("\r\n",$var); if($format) { foreach($var as $i) { if(preg_match('/^([a-zA-Z -]+): +(.*)$/',$i,$parts)) $v[$parts[1]]=$parts[2]; } return $v; } else return $var; } } } 

Оба результата будут иметь следующий результат:

 Array ( [0] => HTTP/1.1 200 OK [Date] => Sat, 29 May 2004 12:28:14 GMT [Server] => Apache/1.3.27 (Unix) (Red-Hat/Linux) [Last-Modified] => Wed, 08 Jan 2003 23:11:55 GMT [ETag] => "3f80f-1b6-3e1cb03b" [Accept-Ranges] => bytes [Content-Length] => 438 [Connection] => close [Content-Type] => text/html ) 

Поэтому вы можете просто проверить, что ответ заголовка был ОК, например:

 $headers = get_headers($url, 1); if ($headers[0] == 'HTTP/1.1 200 OK') { //valid } if ($headers[0] == 'HTTP/1.1 301 Moved Permanently') { //moved or redirect page } 

W3C-коды и определения

С кодом строгана вы также можете проверить CURLINFO_HTTP_CODE для других кодов. Некоторые веб-сайты не сообщают о 404, а просто перенаправляют на пользовательскую страницу 404 и возвращают 302 (перенаправление) или что-то подобное. Я использовал это, чтобы проверить, существует ли на сервере фактический файл (например, robots.txt) или нет. Очевидно, что этот вид файла не вызвал бы перенаправления, если бы он существовал, но если бы он этого не сделал, он перенаправил бы на страницу 404, которая, как я уже сказал, может не иметь кода 404.

 function is_404($url) { $handle = curl_init($url); curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE); /* Get the HTML or whatever is linked in $url. */ $response = curl_exec($handle); /* Check for 404 (file not found). */ $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE); curl_close($handle); /* If the document has loaded successfully without any redirection or error */ if ($httpCode >= 200 && $httpCode < 300) { return false; } else { return true; } } 

Как предлагает strager, изучите использование cURL. Вы также можете быть заинтересованы в установке CURLOPT_NOBODY с curl_setopt, чтобы пропустить загрузку всей страницы (вам просто нужны заголовки).

Если вы ищете самое простое решение и которое вы можете попробовать в один раз на php5, сделайте

 file_get_contents('www.yoursite.com'); //and check by echoing echo $http_response_header[0]; 

Я нашел этот ответ здесь :

 if(($twitter_XML_raw=file_get_contents($timeline))==false){ // Retrieve HTTP status code list($version,$status_code,$msg) = explode(' ',$http_response_header[0], 3); // Check the HTTP Status code switch($status_code) { case 200: $error_status="200: Success"; break; case 401: $error_status="401: Login failure. Try logging out and back in. Password are ONLY used when posting."; break; case 400: $error_status="400: Invalid request. You may have exceeded your rate limit."; break; case 404: $error_status="404: Not found. This shouldn't happen. Please let me know what happened using the feedback link above."; break; case 500: $error_status="500: Twitter servers replied with an error. Hopefully they'll be OK soon!"; break; case 502: $error_status="502: Twitter servers may be down or being upgraded. Hopefully they'll be OK soon!"; break; case 503: $error_status="503: Twitter service unavailable. Hopefully they'll be OK soon!"; break; default: $error_status="Undocumented error: " . $status_code; break; } 

По сути, вы используете метод «получить содержимое» для получения URL-адреса, который автоматически заполняет переменную заголовка ответа HTTP с кодом состояния.

В качестве дополнительного намека на большой принятый ответ:

При использовании варианта предлагаемого решения я получил ошибки из-за установки php «max_execution_time». Итак, я сделал следующее:

 set_time_limit(120); $curl = curl_init($url); curl_setopt($curl, CURLOPT_NOBODY, true); $result = curl_exec($curl); set_time_limit(ini_get('max_execution_time')); curl_close($curl); 

Сначала я установил ограничение по времени на большее количество секунд, в конце я вернул его к значению, определенному в настройках php.

добавлено, проверено эти 3 метода с учетом производительности.

Результат, по крайней мере, в моей тестовой среде:

Керл побеждает

Этот тест проводится с учетом того, что нужны только заголовки (noBody). Попробуй себя:

 $url = "http://de.wikipedia.org/wiki/Pinocchio"; $start_time = microtime(TRUE); $headers = get_headers($url); echo $headers[0]."<br>"; $end_time = microtime(TRUE); echo $end_time - $start_time."<br>"; $start_time = microtime(TRUE); $response = file_get_contents($url); echo $http_response_header[0]."<br>"; $end_time = microtime(TRUE); echo $end_time - $start_time."<br>"; $start_time = microtime(TRUE); $handle = curl_init($url); curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($handle, CURLOPT_NOBODY, 1); // and *only* get the header /* Get the HTML or whatever is linked in $url. */ $response = curl_exec($handle); /* Check for 404 (file not found). */ $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE); // if($httpCode == 404) { // /* Handle 404 here. */ // } echo $httpCode."<br>"; curl_close($handle); $end_time = microtime(TRUE); echo $end_time - $start_time."<br>"; 

Вы также можете использовать этот код, чтобы увидеть статус любой ссылки:

 <?php function get_url_status($url, $timeout = 10) { $ch = curl_init(); // set cURL options $opts = array(CURLOPT_RETURNTRANSFER => true, // do not output to browser CURLOPT_URL => $url, // set URL CURLOPT_NOBODY => true, // do a HEAD request only CURLOPT_TIMEOUT => $timeout); // set timeout curl_setopt_array($ch, $opts); curl_exec($ch); // do it! $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); // find HTTP status curl_close($ch); // close handle echo $status; //or return $status; //example checking if ($status == '302') { echo 'HEY, redirection';} } get_url_status('http://yourpage.comm'); ?> 
 <?php $url= 'www.something.com'; $ch = curl_init($url); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.4"); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_TIMEOUT,10); curl_setopt($ch, CURLOPT_ENCODING, "gzip"); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); $output = curl_exec($ch); $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); echo $httpcode; ?> 

Вот короткое решение.

 $handle = curl_init($uri); curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($handle,CURLOPT_HTTPHEADER,array ("Accept: application/rdf+xml")); curl_setopt($handle, CURLOPT_NOBODY, true); curl_exec($handle); $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE); if($httpCode == 200||$httpCode == 303) { echo "you might get a reply"; } curl_close($handle); 

В вашем случае вы можете изменить application/rdf+xml на все, что вы используете.

это просто и фрагмент кода, надежда работает для вас

  $ch = @curl_init(); @curl_setopt($ch, CURLOPT_URL, 'http://example.com'); @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_RETURNTRANSFER, 1); @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); @curl_setopt($ch, CURLOPT_TIMEOUT, 10); $response = @curl_exec($ch); $errno = @curl_errno($ch); $error = @curl_error($ch); $response = $response; $info = @curl_getinfo($ch); return $info['http_code']; 

Чтобы поймать все ошибки: 4XX и 5XX, я использую этот маленький скрипт:

 function URLIsValid($URL){ $headers = @get_headers($URL); preg_match("/ [45][0-9]{2} /", (string)$headers[0] , $match); return count($match) === 0; }