閒來無事,整理了平時用到的一些代碼,順便在github上發布了自己第一個開源項目,項目很簡單,使用不同的辦法來從純真IP數據庫中獲取IP地址所對應的地理位置信息,同時還可以把純真數據庫裡面記錄的亂七八糟的位置信息轉變成對應的國內的省份信息,以方便進行統計
通過PHP操作純真數據庫的代碼可以很容易從網上找到的,我這裡的算法也是參照網上的代碼實現的,具體代碼可以到github上下載,項目地址:https://github.com/starfalling/php-IpLocationSeeker。純真數據庫的下載地址:http://update.cz88.net/soft/qqwry.rar,因轉換之後的sqlite文件比較大,這裡就不提供下載了,大家可以從前面的連接下載到最新的純真數據庫二進制文件,然後轉換一下就可以了。
這三種不同情況下,性能最優的為qqwry擴展,畢竟,機器碼的運行速度肯定是要超過動態語言的腳本的,也當超過sqlite去做sql分析然後執行的。不過sqlite版本的性能已經跟qqwry擴展比較接近,想要更好的性能又不方便自行編譯php擴展的就完全可以用sqlite版本來進行替代了:
[binary] times:10000 2.53s used # 注意,這裡只重復運行了1萬次,而下面兩個運行了十萬次 [binary-e] times:100000 4.29s used # 擴展 + 二進制文件 [sqlite] times:100000 5.40s used # PHP + sqlite
這裡再簡單介紹一下轉化之後的數據在sqlite中的存儲格式
create table qqwry ( ip integer primary key, country varchar(255), area varchar(255) )
這個表總共有三個字段,主鍵ip存儲了這條記錄所對應的轉化成為有符號整數之後的ip地址,在php裡面,要把字符串形式的IP地址轉化成整數非常簡單,有自帶函數ip2long;country字段存儲了qqwry裡面的一級地址信息,area存儲了二級地址信息。
我們取其中的幾條記錄來進行分析:
sqlite> select * from qqwry limit 10; -2147483648|歐洲| # 128.0.0.0 -2147418112|美國| CZ88.NET # 128.1.0.0 -2147352576|美國|卡耐基·梅隆大學 # 128.2.0.0 -2147301276|美國|卡耐基·梅隆大學DNS服務器 -2147301275|美國|卡耐基·梅隆大學 -2147287040|美國|能源部勞倫斯伯克利國家實驗室 -2147221504|美國|特拉華大學 -2147155968|美國| CZ88.NET -2147090432|美國|羅格斯大學 -2147024896|德國|夫琅和費應用研究促進學會
第一條記錄所對應的IP地址為128.0.0.0,第二條記錄對應的IP地址為128.1.0.0,根據qqwry存儲規則,這兩條記錄之間的所有IP地址的地理位置信息都按第一條處理,也即128.0.1.1這個IP地址所對應的地理位置為歐洲。這樣我們在查詢一個IP地址所對應的地理位置就很簡單了,如代碼裡面所寫到的,只要用一個sql查詢就既可以解決了:
$sql = "select * from qqwry where ip<{$ip_int} order by ip desc limit 1";