简单的方法来在PHP中testing404的URL?

我在教自己一些基本的拼写,我发现有时候我input到代码中的URL返回404,这就把所有剩下的代码都弄糟了。

所以我需要在代码的顶部进行testing,以检查URL是否返回404。

这似乎是一个相当直接的任务,但Google不给我任何答案。 我担心我正在寻找错误的东西。

一个博客推荐我使用这个:

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

然后testing看看$ valid是否为空。

但我认为给我的问题的URL有一个redirect,所以$有效是空的所有值。 或者也许我做了一些其他的错误。

我也研究过一个“头部请求”,但我还没有find任何我可以玩或试用的实际代码示例。

build议? 这是关于curl的?

如果您使用的是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 } 

W3C代码和定义

用strager的代码,你也可以检查CURLINFO_HTTP_CODE的其他代码。 有些网站不报告404,而只是redirect到自定义404页面,并返回302(redirect)或类似的东西。 我用这个来检查服务器上是否存在一个实际的文件(例如robots.txt)。 很明显,这种文件如果存在就不会导致redirect,但是如果没有,它会redirect到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所build议的那样,使用cURL来查看。 你也可能有兴趣用curl_setopt设置CURLOPT_NOBODY跳过下载整个页面(你只是想要标题)。

如果你正在寻找一个最简单的解决scheme,你可以尝试在一个去php5做的

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

我在这里find了这个答案:

 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响应头variables。

作为一个被广泛接受的答案的附加提示:

当使用提出的解决scheme的变体时,由于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'); ?> 

增编;考虑性能testing这3种方法。

结果,至less在我的testing环境中:

curl胜利

这个testing是在只考虑头部(noBody)的情况下完成的。 testing自己:

 $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 $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; ?> 

这是一个简短的解决scheme。

 $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; }