162 votes

Un moyen simple de tester une URL pour 404 en PHP ?

Je suis en train de m'initier au scraping et j'ai constaté que parfois les URL que j'introduis dans mon code renvoient 404, ce qui gomme tout le reste de mon code.

J'ai donc besoin d'un test en haut du code pour vérifier si l'URL renvoie 404 ou non.

Cela semble être une tâche assez simple, mais Google ne me donne aucune réponse. J'ai peur de chercher les mauvaises choses.

Un blog m'a recommandé d'utiliser ceci :

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

et ensuite tester pour voir si $valid est vide ou non.

Mais je pense que l'URL qui me pose problème a une redirection, donc $valid est vide pour toutes les valeurs. Ou peut-être que je fais quelque chose d'autre de mal.

J'ai également cherché une "demande principale", mais je n'ai pas encore trouvé d'exemples concrets de code avec lesquels je puisse jouer ou que je puisse essayer.

Des suggestions ? Et c'est quoi cette histoire de boucles ?

8voto

Ross Points 4080

J'ai trouvé cette réponse ici :

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

Essentiellement, vous utilisez la méthode "file get contents" pour récupérer l'URL, ce qui remplit automatiquement la variable d'en-tête de la réponse http avec le code d'état.

6voto

Email Points 604

Addendum ; testé ces 3 méthodes en considérant la performance.

Le résultat, du moins dans mon environnement de test :

La boucle est bouclée

Ce test est effectué en considérant que seul l'en-tête (noBody) est nécessaire. Faites le test vous-même :

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

2voto

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

2voto

markus Points 22871

Comme un indice supplémentaire à la grande réponse acceptée :

Lorsque j'ai utilisé une variante de la solution proposée, j'ai eu des erreurs à cause du paramètre php 'max_execution_time'. J'ai donc fait ce qui suit :

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

J'ai d'abord fixé la limite de temps à un nombre de secondes plus élevé, puis je l'ai remise à la valeur définie dans les paramètres php.

2voto

Andreas Points 159
$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) ;

Dans votre cas, vous pouvez changer application/rdf+xml à ce que vous utilisez.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X