PHP 404 için bir URL test etmek kolay yolu?


152

Kendime bazı temel kazıma öğretiyorum ve bazen kodumu beslemek URL'lerin kodumu geri kalanını sakız 404, döndürdüğünü buldum.

Bu yüzden URL 404 döndürüp döndürmediğini kontrol etmek için kodun üst kısmında bir teste ihtiyacım var.

Bu oldukça basit bir görev gibi görünebilir, ancak Google bana herhangi bir cevap vermiyor. Endişeleniyorum yanlış şeyler arıyorum.

Bir blog bunu kullanmam önerilir:

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

ve sonra $ 'ın boş olup olmadığını test edin.

Ama bana sorun veren URL'nin bir yönlendirme olduğunu düşünüyorum, bu yüzden $ geçerli tüm değerler için boş geliyor. Ya da belki yanlış bir şey yapıyorum.

Ben de bir "kafa isteği" içine baktım ama ben oynamak ya da deneyebilirsiniz herhangi bir gerçek kod örnekleri bulmak için henüz.

Öneriler? Peki bu kıvrılma hakkında ne?

Yanıtlar:


276

PHP'nin curlbağlarını kullanıyorsanız, hata kodunu aşağıdaki curl_getinfogibi kullanarak kontrol edebilirsiniz :

$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. */

1
Henüz cURL hakkında bilgi sahibi değilim, bu yüzden birkaç kavram eksik. Aşağıdaki $ response değişkeni ile ne yapacağım? Ne içerir?

1
@bflora, kodda bir hata yaptım. (Saniyeler içinde düzeltilecektir.) PHP'nin sitesinde curl_exec belgelerini görebilirsiniz.
Strager

4
@bflora $ yanıtında $ url içeriği bulunacak, böylece içeriği belirli dizeler veya başka şeyler için kontrol etme gibi ek şeyler yapabilirsiniz. Sizin durumunuzda, sadece 404 durumunu önemsiyorsunuz, bu yüzden muhtemelen $ yanıtı hakkında endişelenmenize gerek yok.
Beau Simensen

5
Yalnızca dosyanın tamamını indirmek yerine başlıkların yüklenmesini istiyorsanız ne olur?
patrick

13
@patrick o zaman curl_setopt($handle, CURLOPT_NOBODY, true);çalıştırmadan önce belirtmeniz gerekircurl_exec
kullanıcı

101

Eğer çalışan php5 kullanabilirsiniz:

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

Alternatif olarak php4 ile bir kullanıcı aşağıdakilere katkıda bulunmuştur:

/**
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;
        }
    }
}

Her ikisinin de benzer bir sonucu olacaktır:

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
)

Bu nedenle, başlık yanıtının iyi olup olmadığını kontrol edebilirsiniz, örneğin:

$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 Kodları ve Tanımları


Cevabınızda birkaç biçimlendirme iyileştirmesi yaptım, ayrıca https yeteneğine de ekledim: get_headers($https_url,1,443);Standart get_headers()işlevde olmasa da çalışacağından eminim .. Bunu test etmekten çekinmeyin ve bunun için bir durumla yanıt verin.
JamesM-SiteGen

1
php4 için güzel bir çözüm, ancak bu gibi durumlarda HEAD http yöntemi var.
vidstige

Peki bu aslında curl yönteminden daha hızlı mı olacak?
FLY

4
Hedef URL 404'e yönlendirme yaptığında bu çözüm geçerli değildir. Bu durumda $ headers [0] bir yönlendirme kodu olacak ve son 404 kodu daha sonra dönen diziye bir yere eklenecektir.
roomcays

1
Bu, okumak için sonucu yankılamak yerine, bir koddaki durum kodu ile uğraşmaya çalışırken, ortaya çıkan dizeden gerçek kodu filtrelemek için php değerinden daha fazla sorun çıkarır.
Kzqai

37

Strager koduyla CURLINFO_HTTP_CODE ürününü diğer kodlar için de kontrol edebilirsiniz. Bazı web siteleri bir 404 bildirmez, bunun yerine özel bir 404 sayfasına yönlendirir ve 302 (yönlendirme) veya benzer bir şey döndürür. Bunu, sunucuda gerçek bir dosyanın (örn. Robots.txt) olup olmadığını kontrol etmek için kullandım. Açıkçası, bu tür bir dosya varsa yeniden yönlendirmeye neden olmaz, ancak olmasaydı 404 sayfasına yönlendirirdi, daha önce de söylediğim gibi 404 kodu olmayabilir.

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

5
404 yerine "başarı" HTTP kodlarının kullanımı için +1 ... Kullanıcı, a 408 Request Timeoutdeğil404
aillaume olabilir

Lika bir cazibe çalıştı. Bunu ebay ile ilgili bir makalenin hala çevrimiçi olup olmadığını kontrol etmek için kullanıyorum.
Nerdkowski

Yukarıdaki kodun https ile çalışmasını bekleyenler için aşağıdakileri eklemeye çalışın:curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, FALSE);
Kirk Hammett

ancak meşru bir 302 yönlendirmesi varsa bu da 404 = true değerini döndürür mü?
Robert Sinclair

22

Strager'ın da belirttiği gibi, cURL kullanmaya bakın. Ayrıca , tüm sayfayı indirmeyi atlamak için CURLOPT_NOBODY'yi curl_setopt ile ayarlamak da ilginizi çekebilir (sadece başlıkları istiyorsunuz).


1
Benden bahsettiğiniz için +1 ^ W ^ Sadece başlığın kontrol edilmesi gerektiğinde daha verimli bir alternatif sunmak. =]
strager

16

Eğer kolay bir çözüm arıyorsanız ve bir denemek php5 do denemek

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

3
btw, bunu ve url 404'leri yaparsa, çıktıya neden olan bir uyarı verilir.
Chris K

$ yapmak daha kolay isExists = @file_get_contents ('www.yoursite.com'); if ($ isExists! == true) {echo "404 verir"}
Tebe

denemek yakalamak koymak, sonra yakalamak ile 404 ele
Garet Claborn

7

Bu cevabı burada buldum :

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

Esasen, http yanıt başlığı değişkenini otomatik olarak durum koduyla dolduran URL'yi almak için "file get content" yöntemini kullanırsınız.


2
İlginç - Bu büyüyü daha önce hiç duymamıştım. php.net/manual/tr/reserved.variables.httpresponseheader.php
Frank Farmer

2
ironi - bağlantı bir 404
Hamzah Malik

6

URL 200 geri dönmezse bu size doğru gelecektir

function check_404($url) {
   $headers=get_headers($url, 1);
   if ($headers[0]!='HTTP/1.1 200 OK') return true; else return false;
}

Bir url üzerinde basit bir bool kontrolü yapmak istiyorsanız, cURL kullanmaktan çok daha hızlıdır. Teşekkür ederim.
Drmzindec

5

Zeyilname; performansı dikkate alarak bu 3 yöntemi test etmiştir.

Sonuç, en azından test ortamımda:

Kıvırmak kazanır

Bu test sadece başlıklara (noBody) ihtiyaç duyulduğu düşünülerek yapılır. Kendini test et:

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

3

Büyük kabul edilen cevaba ek bir ipucu olarak:

Önerilen çözümün bir varyasyonunu kullanırken, 'max_execution_time' php ayarı nedeniyle hatalar aldım. Yani yaptığım şey şuydu:

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);

İlk önce zaman sınırını daha yüksek bir saniye sayısına ayarladım, sonunda php ayarlarında tanımlanan değere geri ayarladım.


hhhmmmm ... ayrıca ... kodunuz daha az kaynak tüketiyor çünkü içeriği döndürmüyorsunuz ... yine de yanlışa dönüş transferi ekleyebiliyorsanız, birden fazla çağrı kullanan insanlar çok fazla kaynak tasarrufu sağlayabilir ... yeni başlayanlar fazla düşünmez ve böylece 40 yukarı oyun sebebi ... bu iyi ...
Jayapal Chandran

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

3

İşte kısa bir çözüm.

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

Sizin durumunuzda, application/rdf+xmlkullandığınız her şeye değiştirebilirsiniz .


2

Bu işlev PHP 7'de bir URL'nin durum kodunu döndürür:

/**
 * @param string $url
 * @return int
 */
function getHttpResponseCode(string $url): int
{
    $headers = get_headers($url);
    return substr($headers[0], 9, 3);
}

Misal:

echo getHttpResponseCode('https://www.google.com');
//displays: 200

1

Herhangi bir bağlantının durumunu görmek için bu kodu da kullanabilirsiniz:

<?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');
?>

0

bu sadece ve bir dilim dilim, umut sizin için çalışıyor

            $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'];

0

İşte bir yol!

<?php

$url = "http://www.google.com";

if(@file_get_contents($url)){
echo "Url Exists!";
} else {
echo "Url Doesn't Exist!";
}

?>

Bu basit komut dosyası, kaynak kodu için URL'ye bir istekte bulunur. İstek başarıyla tamamlanırsa, "URL Var!" Aksi takdirde, "URL Var Değil!"

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.