PHP에서 404에 대한 URL을 쉽게 테스트하는 방법?
-
03-07-2019 - |
문제
나는 기본적인 스크래핑을 가르치고 있으며 때로는 코드 리턴 404에 공급되는 URL이 내 코드의 나머지 부분을 모두 껌으로 만들었다는 것을 알았습니다.
따라서 URL이 404인지 아닌지 확인하려면 코드 상단에서 테스트가 필요합니다.
이것은 꽤 직선적인 작업처럼 보이지만 Google은 나에게 답을주지 않습니다. 나는 잘못된 것을 찾고있는 것을 걱정합니다.
하나의 블로그가 권장합니다.
$valid = @fsockopen($url, 80, $errno, $errstr, 30);
비어있는 경우 $ 유효한 지 확인하기 위해 테스트하십시오.
그러나 나에게 문제를주는 URL에 문제가 다시 리디렉션되어 있으므로 모든 값에 대해 $ Valid가 비어 있습니다. 아니면 내가 다른 잘못을하고있을 것입니다.
나는 또한 "헤드 요청"을 살펴 보았지만 아직 플레이하거나 시험해 볼 수있는 실제 코드 예제를 아직 찾지 못했습니다.
제안? 그리고 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
}
Strager의 코드를 사용하면 다른 코드에 대해 Curlinfo_http_code를 확인할 수도 있습니다. 일부 웹 사이트는 404를보고하지 않고 오히려 사용자 정의 404 페이지로 리디렉션하고 302 (리디렉션) 또는 이와 유사한 것을 반환합니다. 이것을 사용하여 실제 파일 (예 : robots.txt)이 서버에 존재했는지 확인했습니다. 분명히 이런 종류의 파일은 존재하는 경우 리디렉션을 유발하지 않지만, 그렇지 않은 경우 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;
}
기본적으로 "파일 get contents"메소드를 사용하여 URL을 검색하여 상태 코드와 함께 HTTP 응답 헤더 변수를 자동으로 채 웁니다.
부록; 성능을 고려한 3 가지 방법을 테스트했습니다.
결과는 적어도 내 테스트 환경에서 :
컬이 승리합니다
이 테스트는 헤더 (아무도 없음) 만 필요하다는 고려에 따라 수행됩니다. 스스로 테스트하십시오 :
$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
$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;
?>
URL이 200 OK를 반환하지 않으면 진실을 줄 것입니다.
function check_404($url) {
$headers=get_headers($url, 1);
if ($headers[0]!='HTTP/1.1 200 OK') return true; else return false;
}
이 코드를 사용하여 링크의 상태를 확인할 수 있습니다.
<?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');
?>
다음은 짧은 솔루션입니다.
$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;
}