很久以前,我使用php中的一些简单函数访问Maxmind本地GeoIP数据库副本。
基本上,他们的数据库使用的模式如下:
CREATE TABLE `geoip_city_blocks` (
`startIpNum` INT(10) UNSIGNED NOT NULL,
`endIpNum` INT(10) UNSIGNED NOT NULL,
`locId` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`startIpNum`, `endIpNum`),
INDEX `startIpNum` (`startIpNum`),
INDEX `endIpNum` (`endIpNum`),
INDEX `locId` (`locId`)
)为了获取某个IP的国家/城市信息,您只需将其转换为与之对应的数字类型:
$numeric_ip = ip2num($ip);其中ip2num()是:
function ip2num($ip) {
$ip = explode(".",$ip);
return (( (int) $ip[0] ) * 16777216) + (( (int) $ip[1] ) * 65536) + (( (int) $ip[2] ) * 256) + (( (int) $ip[3] ) * 1);
}然后进行一个简单的查询:
SELECT * FROM geoip_city_blocks AS blocks LEFT JOIN geoip_city_locations AS locations ON (blocks.locId = locations.locId) WHERE ".$numeric_ip." >= startIpNum AND ".$numeric_ip." <= endIpNum LIMIT 1这是好的,因为任何数据库MySQL,SQLite,Postgre..。等等,你可以用这个查询来比较两个整数。
与新版本的GeoIP,您有这种新的模式:
CREATE TABLE blocks(
"network" TEXT,
"geoname_id" TEXT,
"registered_country_geoname_id" TEXT,
"represented_country_geoname_id" TEXT,
"is_anonymous_proxy" TEXT,
"is_satellite_provider" TEXT
);其中网络以类似于120.120.120.120/8的方式被抑制,比如CIDR地址。没有StartIpNum和EndIpNum
你可以在图像中看到它:

既然我不能通过StartIPNum和EndIpNum进行搜索,我又如何进行查询呢?
发布于 2018-08-22 20:12:44
这是我用自己做的一件事:
没有办法知道网络是什么,所以最简单的解决方案就是把ip地址看作是这样格式化的:a.b.c.d,它可以是24.185.38.192,其中a= 24,c= 38等等。
获取一个只包含a、b和c的子字符串:
$ip_substring = 'a.b.c.';然后执行一个do-while循环,该循环将在返回有效值或检查所有网络时结束。该查询将在数据库中搜索具有%通配符的子字符串之类的任何值,以包括任何主机和掩码:
$ip_substring .= '%';
$search_ip = (string)$ip_substring;
$sql = "SELECT * FROM blocks WHERE network LIKE $search_ip";执行此查询后,将结果捕获为数组,然后预先检查每个单独的网络,以查看您的ip是否存在于其中:
foreach ( $result as $r ) {
$network = $r['network'];
// converts the network (CIDR) to an ip range
$range = array();
$cidr = explode( '/', $network );
$range[0] = long2ip( ( ip2long( $cidr[0] )) & (( -1 << ( 32 - (int)$cidr[1] ) )) );
$range[1] = long2ip( ( ip2long( $range[0] )) + pow( 2, (32 - (int)$cidr[1])) - 1 );
// check that ip is within range
if ( ( ip2long( $ip ) >= ip2long( $range[0] ) ) &&
( ip2long( $ip ) <= ip2long( $range[1] ) ) ) {
// you can use the associated postal_code etc this is the row you were looking for
echo $r['postal_code'];
}
}有一些逻辑来处理您的foreach没有返回有效网络的实例,在这种情况下,您需要通过删除ip_substring中的最后一个字符来扩大搜索范围:
意思:在最后一个循环中,您搜索24.185.38,没有返回任何内容,然后这次将搜索扩展到24.185.3。这只是一种粗糙且并非完全有效的方法,但如果您现在需要一个解决方案,它可以工作。
https://stackoverflow.com/questions/51935541
复制相似问题