168 Stimmen

Einfacher Weg, um eine URL für 404 in PHP zu testen?

Ich bringe mir gerade einige grundlegende Scraping-Funktionen bei und habe festgestellt, dass die URLs, die ich in meinen Code eingebe, manchmal 404 zurückgeben, was den Rest meines Codes blockiert.

Ich brauche also einen Test am Anfang des Codes, um zu prüfen, ob die URL 404 zurückgibt oder nicht.

Das scheint eine ziemlich einfache Aufgabe zu sein, aber Google gibt mir keine Antworten. Ich befürchte, dass ich nach den falschen Dingen suche.

Ein Blog empfahl mir, dies zu verwenden:

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

und dann prüfen, ob $valid leer ist oder nicht.

Aber ich denke, die URL, die mir Probleme gibt, hat eine Umleitung auf es, so $valid kommt leer für alle Werte. Oder vielleicht tue ich etwas anderes falsch.

Ich habe mich auch mit einem "Head Request" beschäftigt, aber ich habe noch keine konkreten Codebeispiele gefunden, mit denen ich spielen oder die ich ausprobieren könnte.

Vorschläge? Und was hat es mit der Locke auf sich?

301voto

strager Punkte 86191

Wenn Sie die PHP-Funktion curl Bindungen können Sie den Fehlercode überprüfen, indem Sie curl_getinfo als solche:

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

110voto

Asciant Punkte 2120

Wenn Sie php5 benutzen, können Sie verwenden:

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

Alternativ hat ein Benutzer mit php4 das Folgende beigetragen:

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

Beide würden zu einem ähnlichen Ergebnis führen:

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
)

Daher könnten Sie einfach überprüfen, ob die Header-Antwort OK war, z. B:

$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-Codes und Definitionen

40voto

Aram Kocharyan Punkte 19721

Mit dem Code von strager können Sie auch den CURLINFO_HTTP_CODE auf andere Codes überprüfen. Einige Websites melden keine 404, sondern leiten einfach auf eine benutzerdefinierte 404-Seite um und geben 302 (redirect) oder etwas Ähnliches zurück. Ich habe dies benutzt, um zu überprüfen, ob eine tatsächliche Datei (z. B. robots.txt) auf dem Server existiert oder nicht. Wenn eine solche Datei existiert, würde sie natürlich keine Weiterleitung verursachen, aber wenn sie nicht existiert, würde sie auf eine 404-Seite weiterleiten, die, wie ich bereits sagte, keinen 404-Code haben darf.

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

24voto

Beau Simensen Punkte 4498

Wie strager vorschlägt, sollten Sie die Verwendung von cURL in Betracht ziehen. Sie könnten auch daran interessiert sein, CURLOPT_NOBODY mit curl_setopt um das Herunterladen der gesamten Seite zu überspringen (Sie wollen nur die Kopfzeilen).

16voto

Nasaralla Punkte 1839

Wenn Sie nach einer einfachen Lösung suchen, die Sie in einem Zug mit php5 ausprobieren können, tun Sie dies

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X