404의 URL을 PHP로 테스트하는 쉬운 방법?
기본적인 스크래핑을 독학하고 있는데, 가끔 코드에 입력한 URL이 404를 반환하고, 그 URL이 코드의 나머지 부분을 모두 집어삼킨다는 것을 알게 되었습니다.
그래서 URL이 404를 반환하는지 확인하기 위해 코드 상단에 테스트가 필요합니다.
이것은 꽤 쉬운 일처럼 보이지만 구글은 나에게 아무런 답을 주지 않고 있다.잘못된 물건을 찾고 있는 것 같아서 걱정이에요.
한 블로그에서는 이 기능을 사용할 것을 권장합니다.
$valid = @fsockopen($url, 80, $errno, $errstr, 30);
빈 경우 $valid 여부를 테스트합니다.
그러나 문제가 발생한 URL에 리다이렉트가 있다고 생각하기 때문에 $valid는 모든 값에 대해 비어 있습니다.아니면 내가 다른 일을 하고 있는지도 몰라.
"헤드 리퀘스트"도 조사했습니다만, 아직 실제로 사용할 수 있는 코드 예를 찾을 수 없습니다.
제안사항?컬이 왜 이래?
PHP 바인딩을 사용하는 경우 다음과 같이 에러 코드를 확인할 수 있습니다.
$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
)
따라서 헤더 응답이 OK인지 확인할 수 있습니다.예를 들어 다음과 같습니다.
$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
}
스트레이저 코드를 사용하여 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_NOBDY를 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;
}
기본적으로 "file get contents" 메서드를 사용하여 URL을 가져오면 http 응답 헤더 변수에 상태 코드가 자동으로 채워집니다.
url이 200 OK를 반환하지 않으면 true가 됩니다.
function check_404($url) {
$headers=get_headers($url, 1);
if ($headers[0]!='HTTP/1.1 200 OK') return true; else return false;
}
부록; 퍼포먼스를 고려하여 이들 세 가지 방법을 제시합니다.
그 결과, 적어도 테스트 환경에서는 다음과 같이 됩니다.
컬이 이기다
이 테스트는 헤더(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 7의 URL 상태 코드를 반환합니다.
/**
* @param string $url
* @return bool
*/
function isHttpStatusCode200(string $url): bool
{
return getHttpResponseCode($url) === 200;
}
/**
* @param string $url
* @return int
*/
function getHttpResponseCode(string $url): int
{
$headers = get_headers($url);
return substr($headers[0], 9, 3);
}
예:
echo isHttpStatusCode200('https://www.google.com');
//displays: true
좋은 답변에 대한 추가 힌트:
제안 솔루션의 변형을 사용할 때 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;
?>
여기 간단한 해결책이 있습니다.
$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
사용할 수 있습니다.
다음 코드를 사용하여 링크의 상태를 확인할 수도 있습니다.
<?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 = "http://www.google.com";
if(@file_get_contents($url)){
echo "Url Exists!";
} else {
echo "Url Doesn't Exist!";
}
?>
이 간단한 스크립트는 단순히 URL에 소스 코드를 요청합니다.요청이 정상적으로 완료되면 "URL Exists!"가 출력됩니다.그렇지 않으면 "URL Does not Exist!" 라고 출력됩니다.
이건 그냥 코드 조각이야, 희망은 너에게 효과가 있어
$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'];
언급URL : https://stackoverflow.com/questions/408405/easy-way-to-test-a-url-for-404-in-php
'source' 카테고리의 다른 글
MySQL 데이터 원본이 Visual Studio에 나타나지 않음 (0) | 2022.10.19 |
---|---|
각도 2를 사용하여 인도 형식으로 숫자 표시 (0) | 2022.10.19 |
PHP 변수는 값으로 전달됩니까, 참조로 전달됩니까? (0) | 2022.10.19 |
Gson이 "<"와 ">"를 Unicode 이스케이프 시퀀스로 변환하는 것을 피할 수 있습니까? (0) | 2022.10.19 |
json_encode PHP 어레이를 JSON 개체가 아닌 JSON 어레이로 코드합니다. (0) | 2022.10.19 |