Простой способ проверить URL для 404 в PHP?
Я учусь некоторым базовым выскабливаниям, и я обнаружил, что иногда URL-адрес, который я загружаю в свой код, возвращает 404, который впитывает весь остальной мой код.
поэтому мне нужен тест в верхней части кода, чтобы проверить, возвращает ли URL 404 или нет.
Это было бы похоже на довольно прямолинейную задачу, но Google не дает мне никаких ответов. Я волнуюсь, что ищу не те вещи.
один блог рекомендовал мне использовать это:
$valid = @fsockopen($url, 80, $errno, $errstr, 30);
и затем проверьте, действительно ли$, если пустой или нет.
но я думаю, что URL, который дает мне проблемы, имеет перенаправление на него, поэтому $valid подходит пустым для всех значений. Или, возможно, я делаю что-то еще не так.
Я также изучил "head request", но мне еще предстоит найти какие-либо фактические примеры кода, с которыми я могу играть или попробовать.
предложения? А что там с керлом?
13 ответов:
Если вы используете PHP
curlпривязки, вы можете проверить код ошибки, используя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 }
С кодом strager, вы также можете проверить CURLINFO_HTTP_CODE для других кодов. Некоторые веб-сайты не сообщают о 404, а просто перенаправляют на пользовательскую страницу 404 и возвращают 302 (перенаправление) или что-то подобное. Я использовал это, чтобы проверить, если файл (например. микророботы.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 do
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; }по существу, вы используете метод "file get contents" для получения URL-адреса, который автоматически заполняет переменную заголовка ответа http кодом состояния.
добавление; протестированы эти 3 метода с учетом производительности.
результат, по крайней мере в моей среде испытания:
Curl выигрывает
этот тест выполняется с учетом того, что нужны только заголовки (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 '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.
вы также можете использовать этот код, чтобы увидеть статус любой ссылки:
<?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; }
Comments