| 注册 | 忘记密码
奇技淫巧 - 阅读主题
<<  <  1  >  >>

打造MySQL版的最新IP数据库

好(0) 差(0) 阅读(11131) 评论(2)
Wen 给 Wen 发消息 给 Wen 发email
作者头像
等级:◆◆◆◆◇◇◇

现在不少人上QQ都用显IP版,不仅能显示好友的IP地址,还能够显示其IP对应的地方,有时可以精确到某城市的某个网吧,甚至可以精确到某栋楼的某房间。

这项功能还可以放到论坛或其他网页上用于显示来客的位置,也可以放在计数统计系统中用于统计客流来源。

对于PHP+MySQL构建的网站,如果我们能把IP数据库存储在MySQL数据库中,就能方便的实现上述功能。但是网上找的MySQL版的IP数据库往往比较陈旧,而IP地址数据库却日新月异。既然没有现成的,咱们就来DIY一个最新的好了。

材料:获取最新IP数据库的工具,现在很多显IP版的QQ都自带,在QQ的文件夹下找找有没有下图的这个showip.exe文件:

showip.exe

如果没有,就到纯真网络金狐软件栏目下载最新的QQ IP数据库纯真版,内包含showip.exe。运行这个showip.exe,软件界面如下图:

http://www.wensh.net/up/2/img/274_2.gif

如果你觉得现在的数据库还不够新(界面上有显示更新日期),就点下方的“在线更新”,静候至更新完毕。

接着点击“解压”按钮,可以把数据库保存为文本格式,输入文件名保存。

这个文本文件是很大的(10余M),我们用一个能打开大文本的编辑器打开,例如UltraEdit,可以看到数据是用如下格式排列的:

0.0.0.0         0.255.255.255   IANA  CZ88.NET
1.0.0.0         1.0.0.0         IANA  CZ88.NET
1.0.0.1         1.255.255.255   美国  CZ88.NET
2.0.0.0         2.255.255.255   IANA  CZ88.NET
3.0.0.0         3.255.255.255   美国 新泽西通用电气公司
4.0.0.0         4.10.255.255    美国  CZ88.NET
4.11.0.0        4.11.255.255    美国 夏威夷
4.12.0.0        4.19.77.255     美国  CZ88.NET
4.19.78.0       4.19.78.255     美国 西南政法大学
4.19.79.0       4.19.79.63      美国 Armed Forces Radio/Television
4.19.79.64      4.21.177.111    美国  CZ88.NET
4.21.177.112    4.21.177.127    美国 Kraft Group
4.21.177.128    4.21.177.255    美国 南新汉普郡学院
...

每一行是一个ip段,数据依次是段起始地址、段结束地址、地理位置。数据与数据之间是数量不等的若干的空格,而不是tab。我们用查找替换把不确定数目的连续空格全部替换为一种统一的分隔符,这里以“||”为例,这可以用正则表达式实现。我这里用一种土方法,在文本编辑器的“查找”栏中输入“         ”(9个空格,因为最大的间隔就是9个空格),“替换”栏输入分隔符“||”,然后全部替换。完成后把“查找”改成8个空格,“替换”不改,再全部替换。然后再7个、6个空格,直到全部空格都变成分隔符。这时文本变成如下格式:

0.0.0.0||0.255.255.255||IANA||CZ88.NET
1.0.0.0||1.0.0.0||IANA||CZ88.NET
1.0.0.1||1.255.255.255||美国||CZ88.NET
2.0.0.0||2.255.255.255||IANA||CZ88.NET
3.0.0.0||3.255.255.255||美国||新泽西通用电气公司
4.0.0.0||4.10.255.255||美国||CZ88.NET
4.11.0.0||4.11.255.255||美国||夏威夷
4.12.0.0||4.19.77.255||美国||CZ88.NET
4.19.78.0||4.19.78.255||美国||西南政法大学
4.19.79.0||4.19.79.63||美国||Armed||Forces||Radio/Television
4.19.79.64||4.21.177.111||美国||CZ88.NET
4.21.177.112||4.21.177.127||美国||Kraft||Group
4.21.177.128||4.21.177.255||美国||南新汉普郡学院
...

文件末尾还有些垃圾,删掉后,把这个文件保存为ip.txt。接着我们用一段php脚本把这个ip.txt转换成sql语句脚本,好导入到MySQL。首先要设计一个MySQL表用于存放ip数据。我的是这样设计的:

CREATE TABLE ip_data (
    ipstart INT UNSIGNED NOT NULL,
    ipend INT UNSIGNED NOT NULL,
    region VARCHAR(50) NOT NULL,
    address VARCHAR(100) NOT NULL,
    PRIMARY KEY (ipstart, ipend)
) TYPE = MyISAM;

由于ip地址本质上是一个32位的2进制整数,所以我们用INT UNSIGNED整形来存储。我将每个ip段(就是ip.txt的一行)的段结束地址后第一个分隔符前的内容作为region,剩余部分作为address。读者在实际使用时应根据具体情况设计具体的数据表,相应地,转换格式的php脚本也应修改。下面给出根据我的数据表制作的php脚本:

<?php
function EncodeIp($strDotquadIp) { // 把点格式的ip地址转换成整数表示的ip地址
    $arrIpSep = explode('.', $strDotquadIp);
    if (count($arrIpSep) != 4) return 0;
    $intIp = 0;    
    foreach ($arrIpSep as $k => $v) $intIp += (int)$v * pow(256, 3 - $k);
    return $intIp;
}

$arrLines = file("ip.txt");
$intLen = 0;
$i = 1;
$resFile = fopen("ip".$i.".sql", "w");
foreach ($arrLines as $k => $strLine) {
    $arrElements = explode("||", addslashes($strLine));
    $intIpStart = EncodeIp($arrElements[0]);
    $intIpEnd = EncodeIp($arrElements[1]);
    $j = 3;
    $strAddress = "";
    while ($arrElements[$j]) {
        $strAddress .= " ".$arrElements[$j];
        $j++;
    }
    $strSql = "INSERT INTO ip_data (ipstart, ipend, region, address) VALUES (".$intIpStart.", ".$intIpEnd.", '".trim($arrElements[2])."', '".trim($strAddress)."');\r\n";
    fwrite($resFile, $strSql);
    $intLen += strlen($strSql);
    if ($intLen > 921600) { // 当正在写入的sql文件超过900K时结束当前文件而开始写入新的sql文件
        fclose($resFile);
        $resFile = fopen("ip".(++$i).".sql", "w");
        $intLen = 0;
    }
}
?>

脚本保存为ip.php,然后在命令行下执行php ip.php,稍等片刻,即生成若干个sql文件。我的这个php脚本按900K大小分割文件,最后生成了34个sql文件。读者实际使用时应根据服务器的PHP和MySQL接收数据的配置选择分割文件依据的大小。

最后把这些sql文件送到MySQL执行即可得到DIY的MySQL版的最新IP数据库。

后续相关:IP地址->地理位置转换的测评

Share/Save/Bookmark
最后修改:Wen 于 2005-09-02 12:47:59

发表于 2005-08-11 11:50:20

评论:Re: 打造MySQL版的最新IP数据库

好(0) 差(0) #1
lostgdi (过客)

function EncodeIp($strDotquadIp) { // 把点格式的ip地址转换成整数表示的ip地址
    $arrIpSep = explode('.', $strDotquadIp);
    if (count($arrIpSep) != 4) return 0;
    $intIp = 0;
    foreach ($arrIpSep as $k => $v) $intIp += (int)$v * pow(256, 3 - $k);
    return $intIp;
}

$arrLines = file("ip.txt");
$intLen = 0;
$i = 1;
$resFile = fopen("ips\ip".$i.".sql", "w");
foreach ($arrLines as $k => $strLine) {
   
    $intIpStart = substr($strLine,0,15);
    $intIpStart = EncodeIp($intIpStart);

    $intIpEnd = substr($strLine,16,15);
    $intIpEnd = EncodeIp($intIpEnd);

    $tmp = substr($strLine,32);
    $tmp = explode(" ", $tmp ,2);
    $region = trim($tmp[0]);
    $strAddress = trim($tmp[1]);

    $strSql = "INSERT INTO ip_data (ipstart, ipend, region, address) VALUES (".$intIpStart.", ".$intIpEnd.", '".$region."', '".$strAddress."');\r\n";
    fwrite($resFile, $strSql);
    $intLen += strlen($strSql);
    if ($intLen > 921600) { // 当正在写入的sql文件超过900K时结束当前文件而开始写入新的sql文件
        fclose($resFile);
        $resFile = fopen("ips\ip".(++$i).".sql", "w");
        $intLen = 0;
    }
}

//我这样不用写字板,直接转换,更快更方便


发表于 2008-01-03 20:33:21

评论:Re: 打造MySQL版的最新IP数据库

好(0) 差(0) #2
k (过客)

and we have a function "ip2long" to encode ip address.


发表于 2008-04-19 07:10:24
奇技淫巧 - 阅读主题
<<  <  1  >  >>

Valid XHTML 1.0 | Valid CSS2 | WAI-A WCAG 1.0

Copyright 2005-2018 WEN'S Horizon [34/0.186]