php根據ip查詢所在地區(非常有用,趕集網就用到)


dat文件,關於ip對應地區的信息文件

qqwry.dat文件

網上自己下載

 

class類文件,解析qqwry.data文件的

IpLocation.php文件

  1. <?php  
  2. class IpLocation {  
  3.     /** 
  4.     * @var resource 指針 
  5.     */  
  6.     private $fp;  
  7.   
  8.     /** 
  9.     * 第一條IP記錄的偏移地址 
  10.     * @var int 
  11.     */  
  12.     private $firstip;  
  13.   
  14.     /** 
  15.     * 最后一條IP記錄的偏移地址 
  16.     * @var int 
  17.     */  
  18.     private $lastip;  
  19.   
  20.     /** 
  21.     * IP記錄的總條數(不包含版本信息記錄) 
  22.     * @var int 
  23.     */  
  24.     private $totalip;  
  25.   
  26.     /** 
  27.     * 構造函數,打開 QQWry.Dat 文件並初始化類中的信息 
  28.     * @param string $filename 
  29.     * @return IpLocation 
  30.     */  
  31.     public function __construct($filename = "qqwry.dat") {  
  32.         $this->fp = 0;  
  33.         if (($this->fp = @fopen($filename'rb')) !== false) {  
  34.             $this->firstip = $this->getlong();  
  35.             $this->lastip = $this->getlong();  
  36.             $this->totalip = ($this->lastip - $this->firstip) / 7;  
  37.         }  
  38.     }  
  39.   
  40.     /** 
  41.     * 返回讀取的長整型數 
  42.     * @access private 
  43.     * @return int 
  44.     */  
  45.     public function getlong() {  
  46.         //將讀取的little-endian編碼的4個字節轉化為長整型數  
  47.         $result = unpack('Vlong'fread($this->fp, 4));  
  48.         return $result['long'];  
  49.     }  
  50.   
  51.     /** 
  52.     * 返回讀取的3個字節的長整型數 
  53.     * 
  54.     * @access private 
  55.     * @return int 
  56.     */  
  57.     public function getlong3() {  
  58.         //將讀取的little-endian編碼的3個字節轉化為長整型數  
  59.         $result = unpack('Vlong'fread($this->fp, 3).chr(0));  
  60.         return $result['long'];  
  61.     }  
  62.   
  63.     /** 
  64.     * 返回壓縮后可進行比較的IP地址 
  65.     * 
  66.     * @access private 
  67.     * @param string $ip 
  68.     * @return string 
  69.     */  
  70.     public function packip($ip) {  
  71.         // 將IP地址轉化為長整型數,如果在PHP5中,IP地址錯誤,則返回False,  
  72.         // 這時intval將Flase轉化為整數-1,之后壓縮成big-endian編碼的字符串  
  73.         return pack('N'intval(ip2long($ip)));  
  74.     }  
  75.   
  76.     /** 
  77.     * 返回讀取的字符串 
  78.     * 
  79.     * @access private 
  80.     * @param string $data 
  81.     * @return string 
  82.     */  
  83.     public function getstring($data = "") {  
  84.         $char = fread($this->fp, 1);  
  85.         while (ord($char) > 0) { // 字符串按照C格式保存,以\0結束  
  86.             $data .= $char// 將讀取的字符連接到給定字符串之后  
  87.             $char = fread($this->fp, 1);  
  88.         }  
  89.         return mb_convert_encoding($data'utf-8''gb2312');  
  90.     }  
  91.   
  92.     /** 
  93.     * 返回地區信息 
  94.     * 
  95.     * @access private 
  96.     * @return string 
  97.     */  
  98.     public function getarea() {  
  99.         $byte = fread($this->fp, 1); // 標志字節  
  100.         switch (ord($byte)) {  
  101.             case 0: // 沒有區域信息  
  102.                 $area = "";  
  103.             break;  
  104.             case 1:  
  105.             case 2: // 標志字節為1或2,表示區域信息被重定向  
  106.                 fseek($this->fp, $this->getlong3());  
  107.                 $area = $this->getstring();  
  108.             break;  
  109.             default// 否則,表示區域信息沒有被重定向  
  110.                 $area = $this->getstring($byte);  
  111.             break;  
  112.         }  
  113.         return $area;  
  114.     }  
  115.   
  116.     /** 
  117.     * 根據所給 IP 地址或域名返回所在地區信息 
  118.     * @access public 
  119.     * @param string $ip 
  120.     * @return array 
  121.     */  
  122.     function getlocation($ip) {  
  123.         if (!$this->fp) return null; // 如果數據文件沒有被正確打開,則直接返回空  
  124.         $location['ip'] = gethostbyname($ip); // 將輸入的域名轉化為IP地址  
  125.         $ip = $this->packip($location['ip']); // 將輸入的IP地址轉化為可比較的IP地址  
  126.         // 不合法的IP地址會被轉化為255.255.255.255  
  127.         // 對分搜索  
  128.         $l = 0; // 搜索的下邊界  
  129.         $u = $this->totalip; // 搜索的上邊界  
  130.         $findip = $this->lastip; // 如果沒有找到就返回最后一條IP記錄(QQWry.Dat的版本信息)  
  131.         while ($l <= $u) { // 當上邊界小於下邊界時,查找失敗  
  132.             $i = floor(($l + $u) / 2); // 計算近似中間記錄  
  133.             fseek($this->fp, $this->firstip + $i * 7);  
  134.             $beginip = strrev(fread($this->fp, 4)); // 獲取中間記錄的開始IP地址  
  135.             // strrev函數在這里的作用是將little-endian的壓縮IP地址轉化為big-endian的格式  
  136.             // 以便用於比較,后面相同。  
  137.             if ($ip < $beginip) { // 用戶的IP小於中間記錄的開始IP地址時  
  138.                 $u = $i - 1; // 將搜索的上邊界修改為中間記錄減一  
  139.             }else{  
  140.                 fseek($this->fp, $this->getlong3());  
  141.                 $endip = strrev(fread($this->fp, 4)); // 獲取中間記錄的結束IP地址  
  142.                 if ($ip > $endip) { // 用戶的IP大於中間記錄的結束IP地址時  
  143.                     $l = $i + 1; // 將搜索的下邊界修改為中間記錄加一  
  144.                 }else// 用戶的IP在中間記錄的IP范圍內時  
  145.                     $findip = $this->firstip + $i * 7;  
  146.                     break// 則表示找到結果,退出循環  
  147.                 }  
  148.             }  
  149.         }  
  150.   
  151.         //獲取查找到的IP地理位置信息  
  152.         fseek($this->fp, $findip);  
  153.         $location['beginip'] = long2ip($this->getlong()); // 用戶IP所在范圍的開始地址  
  154.         $offset = $this->getlong3();  
  155.         fseek($this->fp, $offset);  
  156.         $location['endip'] = long2ip($this->getlong()); // 用戶IP所在范圍的結束地址  
  157.         $byte = fread($this->fp, 1); // 標志字節  
  158.   
  159.         switch (ord($byte)) {  
  160.             case 1: // 標志字節為1,表示國家和區域信息都被同時重定向  
  161.                 $countryOffset = $this->getlong3(); // 重定向地址  
  162.                 fseek($this->fp, $countryOffset);  
  163.                 $byte = fread($this->fp, 1); // 標志字節  
  164.                 switch (ord($byte)) {  
  165.                     case 2: // 標志字節為2,表示國家信息又被重定向  
  166.                         fseek($this->fp, $this->getlong3());  
  167.                         $location['country'] = $this->getstring();  
  168.                         fseek($this->fp, $countryOffset + 4);  
  169.                         $location['area'] = $this->getarea();  
  170.                         break;  
  171.                     default// 否則,表示國家信息沒有被重定向  
  172.                         $location['country'] = $this->getstring($byte);  
  173.                         $location['area'] = $this->getarea();  
  174.                         break;  
  175.                 }  
  176.                 break;  
  177.             case 2: // 標志字節為2,表示國家信息被重定向  
  178.                 fseek($this->fp, $this->getlong3());  
  179.                 $location['country'] = $this->getstring();  
  180.                 fseek($this->fp, $offset + 8);  
  181.                 $location['area'] = $this->getarea();  
  182.                 break;  
  183.             default// 否則,表示國家信息沒有被重定向  
  184.                 $location['country'] = $this->getstring($byte);  
  185.                 $location['area'] = $this->getarea();  
  186.                 break;  
  187.         }  
  188.         if ($location['country'] == " CZ88.NET") { // CZ88.NET表示沒有有效信息  
  189.             $location['country'] = "未知";  
  190.         }  
  191.         if ($location['area'] == " CZ88.NET") {  
  192.             $location['area'] = "";  
  193.         }  
  194.         return $location;  
  195.     }  
  196.   
  197.       
  198.     /** 
  199.     * 析構函數,用於在頁面執行結束后自動關閉打開的文件。 
  200.     * 
  201.     */  
  202.     function __desctruct() {  
  203.         if ($this->fp) {  
  204.             fclose($this->fp);  
  205.         }  
  206.         $this->fp = 0;  
  207.     }  
  208. }  
  209. ?>   

這個也可以網上下載,也可以copy這里的,這里的也是很全的。

 

執行文件,我這里叫ip_location.php文件

    1. <?php   
    2. function getIpPlace(){  
    3.     require_once("IpLocation.php")//加載類文件IpLocation.php  
    4.     $ipfile = "qqwry.dat";      //獲取ip對應地區的信息文件  
    5.     $iplocation = new IpLocation($ipfile);  //new IpLocation($ipfile) $ipfile ip對應地區信息文件  
    6.     $ipresult = $iplocation->getlocation("ip地址"); //根據ip地址獲得地區 getlocation("ip地區")  
    7.     return $ipresult;  
    8. }  
    9. print_r($getIpPlace()); //調用方法  
    10. ?> 
http://blog.csdn.net/motian06/article/details/7919675


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM