php判断网址是否存在/网页是否正确

2016年03月14日 | 0 条评论 | 3026

PHP 要判断网页是否存在, 简单的方法就是 fopen / file_get_contents .. 等等, 有一堆的方式可以做, 不过这些方式都会把整页 HTML 拉回来, 要判断的网址资料很多时, 就会有点慢.

要判断可以由 HTTP HEADER 来判断, 就不用把整页的内容都抓回来(详可见: Hypertext Transfer Protocol -- HTTP/1.1).

fsockopen 判断 HTTP Header

简单的范例如下(转载自: PHP Server Side Scripting - Checking if page exists

[php] view plain copy

  1. if ($sock = fsockopen('something.net', 80))  

  2. {  

  3.    fputs($sock"HEAD /something.html HTTP/1.0\r\n\r\n");  

  4.   

  5.    while(!feof($sock)) {  

  6.        echo fgets($sock);  

  7.     }  

  8. }   

  9. ?>  

会得到下述资料:

[plain] view plain copy

  1. HTTP/1.1 200 OK  

  2. Date: Mon, 06 Oct 2008 15:45:27 GMT  

  3. Server: Apache/2.2.9  

  4. X-Powered-By: PHP/5.2.6-4  

  5. Set-Cookie: PHPSESSID=4e037868a4619d6b4d8c52d0d5c59035; path=/  

  6. Expires: Thu, 19 Nov 1981 08:52:00 GMT  

  7. Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0  

  8. Pragma: no-cache  

  9. Vary: Accept-Encoding  

  10. Connection: close  

  11. Content-Type: text/html   


但是上述做法, 还是会有很多问题, 例如 302 redirect 等等, 简单点的方法, 还是靠 curl 来帮我们处理掉这些麻烦事吧~

PHP + Curl + Content-Type 判断

PHP + Curl 判断此网页是否存在, 详可见: How To Check If Page Exists With CURL | W-Shadow.com

此程式会判断 200 OK 等状态资讯(200 ~ 400 间都是正常的状态).

基本上, 上述那程式已经够用, 不过使用者输入的资料是千奇百怪的, 所以需要加上其它的判断, 下述是随便抓几个有问题的网址:

  • xxx@ooo.com # Email

  • http://xxx.ooo.com/abc.zip # 压缩档

  • # 帮你检查是否有 XSS 漏洞 =.=|||

因为上述资料, 所以要把上述资讯 Filter 掉, 所以要多检查是否是正常网址, 和 Content-Type 是否是我们要的.

于是程式修改如下(修改自: How To Check If Page Exists With CURL): 

[php] view plain copy

  1. function page_exists($url)  

  2. {  

  3.    $parts = parse_url($url);  

  4.    if (!$parts) {  

  5.       return false; /* the URL was seriously wrong */  

  6.    }  

  7.   

  8.    if (isset($parts['user'])) {  

  9.       return false; /* user@gmail.com */  

  10.    }  

  11.   

  12.    $ch = curl_init();  

  13.    curl_setopt($ch, CURLOPT_URL, $url);  

  14.   

  15.    /* set the user agent - might help, doesn't hurt */  

  16.    //curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)');  

  17.    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; wowTreebot/1.0; +http://wowtree.com)');  

  18.    curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);  

  19.   

  20.    /* try to follow redirects */  

  21.    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);  

  22.   

  23.    /* timeout after the specified number of seconds. assuming that this script runs 

  24.       on a server, 20 seconds should be plenty of time to verify a valid URL.  */  

  25.    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);  

  26.    curl_setopt($ch, CURLOPT_TIMEOUT, 20);  

  27.   

  28.    /* don't download the page, just the header (much faster in this case) */  

  29.    curl_setopt($ch, CURLOPT_NOBODY, true);  

  30.    curl_setopt($ch, CURLOPT_HEADER, true);  

  31.   

  32.    /* handle HTTPS links */  

  33.    if ($parts['scheme'] == 'https') {  

  34.       curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,  1);  

  35.       curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);  

  36.    }  

  37.   

  38.    $response = curl_exec($ch);  

  39.    curl_close($ch);  

  40.   

  41.    /* allow content-type list */  

  42.    $content_type = false;  

  43.    if (preg_match('/Content-Type: (.+\/.+?)/i'$response$matches)) {  

  44.        switch ($matches[1])  

  45.         {  

  46.            case 'application/atom+xml':  

  47.            case 'application/rdf+xml':  

  48.            //case 'application/x-sh':  

  49.            case 'application/xhtml+xml':  

  50.            case 'application/xml':  

  51.            case 'application/xml-dtd':  

  52.            case 'application/xml-external-parsed-entity':  

  53.            //case 'application/pdf':  

  54.            //case 'application/x-shockwave-flash':  

  55.               $content_type = true;  

  56.               break;  

  57.         }  

  58.   

  59.        if (!$content_type && (preg_match('/text\/.*/'$matches[1]) || preg_match('/image\/.*/'$matches[1]))) {  

  60.            $content_type = true;  

  61.         }  

  62.    }  

  63.   

  64.    if (!$content_type) {  

  65.       return false;  

  66.    }  

  67.   

  68.    /*  get the status code from HTTP headers */  

  69.    if (preg_match('/HTTP\/1\.\d+\s+(\d+)/'$response$matches)) {  

  70.       $code = intval($matches[1]);  

  71.    } else {  

  72.       return false;  

  73.    }  

  74.   

  75.    /* see if code indicates success */  

  76.    return (($code >= 200) && ($code < 400));  

  77. }  

  78.   

  79. // Test & 使用方法:  

  80. // var_dump(page_exists('http://tw.yahoo.com'));  

  81. ?>   


 

Content-Type information

上述 Content-Type 的资讯可由下述找到:

  • /etc/mime.types

  • /usr/share/doc/apache-common/examples/mime.types.gz

  • /usr/share/doc/apache2.2-common/examples/apache2/mime.types.gz # 建议是看这个

 

 

****************************************************************************************************

1.  网址的格式:

[javascript] view plain copy

  1. function checkUrl($weburl)      

  2. {      

  3.     return !ereg("^http(s)*://[_a-zA-Z0-9-]+(.[_a-zA-Z0-9-]+)*$", $weburl);      

  4. }    


 

2 . 判断http 地址是否有效

[php] view plain copy

  1. function url_exists($url)     

  2. {     

  3.     $ch = curl_init();     

  4.     curl_setopt($ch, CURLOPT_URL,$url);     

  5.     curl_setopt($ch, CURLOPT_NOBODY, 1); // 不下载     

  6.     curl_setopt($ch, CURLOPT_FAILONERROR, 1);     

  7.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);     

  8.     return (curl_exec($ch)!==false) ? true : false;     

  9. }    

或者

[php] view plain copy

  1. function img_exists($url)      

  2. {     

  3.     return file_get_contents($url,0,null,0,1) ? true : false;     

  4. }    

或者

[php] view plain copy

  1. function url_exists($url)      

  2. {     

  3.     $head = @get_headers($url);     

  4.     return is_array($head) ?  true : false;     

  5. }    

 

实例:

[php] view plain copy

  1. $url='http://www.sendnet.cn';     

  2. echo url_exists($url);    


技术咨询
换一个