PHP में 404 के लिए URL का परीक्षण करने का आसान तरीका?


152

मैं अपने आप को कुछ बुनियादी स्क्रैपिंग सिखा रहा हूं और मैंने पाया है कि कभी-कभी URL की मैं अपने कोड 404 में फीड करता हूं, जो मेरे बाकी सभी कोड को गम करता है।

इसलिए मुझे यह जांचने के लिए कोड के शीर्ष पर एक परीक्षण की आवश्यकता है कि URL 404 लौटाता है या नहीं।

यह एक बहुत ही सीधे काम की तरह प्रतीत होगा, लेकिन Google मुझे कोई जवाब नहीं दे रहा है। मुझे चिंता है कि मैं गलत सामान खोज रहा हूं।

एक ब्लॉग ने सिफारिश की कि मैं इसका उपयोग करूँ:

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

और फिर देखने के लिए परीक्षण करें कि क्या $ खाली है या नहीं।

लेकिन मुझे लगता है कि जो URL मुझे समस्याएं दे रहा है, उस पर पुनर्निर्देशित है, इसलिए सभी मान्य के लिए $ मान्य खाली आ रहा है। या शायद मैं कुछ और गलत कर रहा हूं।

मैंने एक "हेड रिक्वेस्ट" पर भी ध्यान दिया है, लेकिन मुझे अभी तक कोई वास्तविक कोड उदाहरण नहीं मिला है जिसके साथ मैं खेल सकूं या कोशिश कर सकता हूं।

सुझाव? और यह कर्ल के बारे में क्या है?

जवाबों:


276

यदि आप 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. */

1
मैं अभी तक cURL से परिचित नहीं हूँ, इसलिए मुझे कुछ अवधारणाएँ याद आ रही हैं। मैं नीचे $ प्रतिक्रिया चर के साथ क्या करूँ? इसमें क्या शामिल है?

1
@ बेलफ़ोरा, मैंने कोड में एक गलती की। (एक सेकंड में ठीक हो जाएगा।) आप PHP की साइट पर curl_exec के लिए दस्तावेज़ देख सकते हैं।
strager

4
@bflora $ रिस्पॉन्स में $ url की सामग्री होगी ताकि आप विशिष्ट स्ट्रिंग्स या जो कुछ भी हो, उसके लिए सामग्री की जाँच जैसे अतिरिक्त कार्य कर सकें। आपके मामले में, आप केवल 404 राज्य की परवाह करते हैं, इसलिए आपको शायद $ प्रतिक्रिया के बारे में चिंता करने की आवश्यकता नहीं है।
ब्यू सिमेंसन

5
क्या होगा यदि आप पूरी फ़ाइल डाउनलोड करने के बजाय केवल हेडर लोड करना चाहते हैं?
पैट्रिक

13
@patrick को curl_setopt($handle, CURLOPT_NOBODY, true);चलने से पहले आपको निर्दिष्ट करना होगाcurl_exec
उपयोगकर्ता

101

यदि आपका 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
}

W3C कोड और परिभाषाएँ


मैंने आपके उत्तर के कुछ प्रारूपण में सुधार किया है, मैंने https की क्षमता में भी जोड़ा: get_headers($https_url,1,443);मुझे यकीन है कि यह काम करेगा हालांकि यह मानक get_headers()फ़ंक्शन में नहीं है । इसे परीक्षण करने के लिए स्वतंत्र महसूस करें और इसके लिए एक स्थिति के साथ जवाब दें।
जेम्सएम-साइटगैन

1
php4 के लिए अच्छा वर्कअराउंड, लेकिन इस तरह के मामलों के लिए हमारे पास HEAD http विधि है।
vidstige

तो यह वास्तव में तेज होगा तो कर्ल विधि?
उड़ना

4
यह समाधान तब मान्य नहीं होता है जब लक्ष्य URL को 404 पर पुनर्निर्देशित किया जाता है। इस मामले में $ हेडर [0] एक रीडायरेक्ट कोड होगा, और अंतिम 404 कोड को बाद में रिटर्निंग एरे में कहीं जोड़ दिया जाएगा।
कमरा

1
पढ़ने के परिणाम को गूँजने का विरोध करते हुए परिणामी स्ट्रिंग से वास्तविक कोड को फ़िल्टर करने की तुलना में यह परिणामी स्ट्रिंग के वास्तविक कोड को फ़िल्टर करने की तुलना में अधिक परेशानी वाला होता है।
कजकाई

37

स्ट्रेजर के कोड के साथ, आप अन्य कोड्स के लिए CURLINFO_HTTP_CODE भी देख सकते हैं। कुछ वेबसाइट 404 की रिपोर्ट नहीं करती हैं, बल्कि वे केवल एक कस्टम 404 पेज पर रीडायरेक्ट करती हैं और 302 (रीडायरेक्ट) या कुछ इसी तरह वापस आती हैं। मैंने इसका उपयोग यह जांचने के लिए किया है कि सर्वर पर कोई वास्तविक फ़ाइल (उदाहरण के लिए। robots.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;
    }
}

5
404 के बजाय "सफलता" HTTP कोड के उपयोग के लिए +1 ... उपयोगकर्ता को एक मिल सकता है 408 Request Timeout, नहीं404
गिलोय

एक आकर्षण की तरह काम किया। मैं यह जांचने के लिए उपयोग करता हूं कि क्या eBay पर कोई लेख अभी भी ऑनलाइन है।
नर्डकोव्स्की

उन लोगों के लिए जो उपरोक्त कोड को https के साथ काम करने की उम्मीद करते हैं, निम्नलिखित जोड़ने की कोशिश करते हैं:curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, FALSE);
Kirk Hammett

लेकिन यह भी 404 = सही लौटाएगा यदि कोई वैध 302 रीडायरेक्ट है?
रॉबर्ट सिंक्लेयर

22

जैसा कि स्ट्रेजर बताता है, cURL का उपयोग करने पर ध्यान दें। आप पूरे पृष्ठ को डाउनलोड करने के लिए कर्ल_सेटॉप के साथ CURLOPT_NOBODY को सेट करने में दिलचस्पी ले सकते हैं (आप सिर्फ हेडर चाहते हैं)।


1
मुझे उल्लेख करने के लिए +1 ^ ^ ^ एक और अधिक कुशल विकल्प का निर्माण, उस मामले में जहां केवल हेडर को जांचना आवश्यक है। =]
जनवरी'09 स्ट्रगल

16

यदि आप एक आसान समाधान की तलाश कर रहे हैं और एक जिसे आप php5 पर एक में जाने की कोशिश कर सकते हैं

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

3
btw, अगर ऐसा कर रहे हैं और url 404's, एक चेतावनी उठाया जाता है, जिससे उत्पादन होता है।
क्रिस के

$ करना आसान है ।Exists = @file_get_contents ('www.yoursite.com'); if ($ isExists! == true) {echo "yields 404"}
Tebe

एक कोशिश की पकड़ में डाल दिया, फिर 404 पकड़ के साथ संभाल
Garet Claborn

7

मुझे यह उत्तर मिला यहाँ :

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

अनिवार्य रूप से, आप URL को पुनर्प्राप्त करने के लिए "फ़ाइल प्राप्त सामग्री" विधि का उपयोग करते हैं, जो स्वचालित रूप से स्थिति कोड के साथ http प्रतिक्रिया हेडर चर को पॉप्युलेट करता है।


2
रुचिकर - मैंने पहले कभी उस जादू के बारे में नहीं सुना था। php.net/manual/en/reserved.variables.httpresponseheader.php
फ्रैंक किसान

2
विडंबना - लिंक एक 404 है
हमजा मलिक

6

यह आपको सही देगा अगर url 200 ओके नहीं लौटाता है

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

यह cURL का उपयोग करने की तुलना में बहुत तेज़ है, यदि आप एक url पर एक साधारण बूल जाँच करना चाहते हैं। धन्यवाद।
Drmzindec

5

परिशिष्ट, प्रदर्शन पर विचार करने वाले उन 3 तरीकों का परीक्षण किया।

परिणाम, कम से कम मेरे परीक्षण वातावरण में:

कर्ल जीत गया

यह परीक्षण इस विचार के तहत किया जाता है कि केवल हेडर (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>";

3

महान स्वीकृत उत्तर के लिए एक अतिरिक्त संकेत के रूप में:

प्रस्तावित समाधान की भिन्नता का उपयोग करते समय, मुझे 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 सेटिंग्स में परिभाषित मूल्य पर वापस सेट किया।


hhhmmmm ... इसके अलावा ... आपका कोड कम संसाधनों का उपभोग करता है क्योंकि आप सामग्री नहीं लौटा रहे हैं ... फिर भी अगर आप झूठी ट्रांसफर जोड़ सकते हैं तो बहुत सारे संसाधनों को बचा सकते हैं जब लोग कई कॉल का उपयोग कर रहे हैं ... शुरुआती लोग ज्यादा नहीं सोचते हैं और इसलिए यह 40 अप वोटों का कारण है ... यह ठीक है ...
जयपाल चंद्रन

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

यहाँ एक छोटा उपाय है।

$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जो भी उपयोग करते हैं उसे बदल सकते हैं ।


2

यह फ़ंक्शन PHP 7 में एक URL का स्थिति कोड लौटाता है:

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

उदाहरण:

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

1

आप किसी भी लिंक की स्थिति देखने के लिए इस कोड का उपयोग कर सकते हैं:

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

यह सिर्फ और कोड का टुकड़ा है, आशा है कि आप के लिए काम करता है

            $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

यहाँ एक तरीका है!

<?php

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

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

?>

यह सरल स्क्रिप्ट केवल अपने स्रोत कोड के लिए URL के लिए अनुरोध करती है। यदि अनुरोध सफलतापूर्वक पूरा हो गया है, तो यह "URL एक्ज़िस्ट!" को आउटपुट देगा। यदि नहीं, तो यह "URL डोंट एक्ज़िस्ट!" आउटपुट करेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.