PHPPython二分查找法获取IP地理位置
最近今日头条上线了在创作者个人主页"更多信息"里显示创作者的地理位置。今日头条是为了加强建设健康、优质、有益、多元的网络生态。但功能上线后曝光了一些人性虚伪的层面。有些V账号的个人主页的地理位置与创作内容说的地理位置不同。让大众着实笑笑解千仇了一下。今天为大家介绍PHP/Python两种编程语言利用二分查找法获取IP地理位置。功能考虑IP段和指定IP两种情况的地理位置处理。
一、PHP二分查找法获取IP地理位置
1、PHP获取用户客户端IP地址<?php function getClientIp() { $strUip = ""; if (isset($_SERVER["HTTP_X_BD_USERIP"]) && $_SERVER["HTTP_X_BD_USERIP"] && strcasecmp($_SERVER["HTTP_X_BD_USERIP"], "unknown")) { $strUip = $_SERVER["HTTP_X_BD_USERIP"]; } else if (!empty($_SERVER["HTTP_CLIENTIP6"])) { $strUip = $_SERVER["HTTP_CLIENTIP6"]; } else if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"]) && strcasecmp($_SERVER["HTTP_X_FORWARDED_FOR"], "unknown")) { $strUip = $_SERVER["HTTP_X_FORWARDED_FOR"]; strpos($strUip, ",") && list($strUip) = explode(",", $strUip); } else if (!empty($_SERVER["HTTP_CLIENT_IP"]) && strcasecmp($_SERVER["HTTP_CLIENT_IP"], "unknown")) { $strUip = $_SERVER["HTTP_CLIENT_IP"]; } else if (!empty($_SERVER["REMOTE_ADDR"]) && strcasecmp($_SERVER["REMOTE_ADDR"], "unknown")) { $strUip = $_SERVER["REMOTE_ADDR"]; } return $strUip; } $strUip = getClientIp(); var_dump($strUip); 执行结果: string(15) "183.199.168.188"
2、PHP二分查找法获取IP地理位置<?php function search_ip_addr_recursion($arrIp, $intLow, $intHigh, $intIp) { $intMiddle = intval(($intLow + $intHigh) / 2); if ($intLow > $intHigh) { return -1; } //处理指定ip逻辑 if (isset($arrIp[$intMiddle]["ip"])) { $intMiddleIp = ip2long($arrIp[$intMiddle]["ip"]); } else { //处理ip段逻辑 $intMiddleStartIp = ip2long($arrIp[$intMiddle]["range"]["s"]); $intMiddleEndIp = ip2long($arrIp[$intMiddle]["range"]["e"]); } if (isset($intMiddleIp) && $intMiddleIp == $intIp) { return $intMiddle; } if (isset($intMiddleStartIp) && $intIp >= $intMiddleStartIp && $intIp <= $intMiddleEndIp) { return $intMiddle; } //处理指定ip逻辑 if (isset($intMiddleIp) && $intIp > $intMiddleIp) { return search_ip_addr_recursion($arrIp, $intMiddle + 1, $intHigh, $intIp); } elseif (isset($intMiddleIp) && $intIp < $intMiddleIp) { return search_ip_addr_recursion($arrIp, $intLow, $intMiddle - 1, $intIp); } //处理ip段逻辑 if (isset($intMiddleEndIp) && $intIp > $intMiddleEndIp) { return search_ip_addr_recursion($arrIp, $intMiddle + 1, $intHigh, $intIp); } elseif (isset($intMiddleEndIp) && $intIp < $intMiddleEndIp) { return search_ip_addr_recursion($arrIp, $intLow, $intMiddle - 1, $intIp); } //if代码是一条垂线下来 } //ip测试 $arrIp = array( array("ip" => "202.132.13.12", "addr" => "北京"), array("range" => array("s" => "212.12.24.12", "e" => "212.13.25.14"), "addr" => "山西"), array("range" => array("s" => "212.13.25.15", "e" => "212.15.25.14"), "addr" => "河北"), ); $intIp = ip2long("212.12.24.13"); //$intIp = ip2long("202.132.13.12"); $intIndex = search_ip_addr_recursion($arrIp, 0, count($arrIp), $intIp); var_dump($intIndex); if (-1 === $intIndex) { var_dump("None"); } else { var_dump($arrIp[$intIndex]); } 执行结果: int(1) array(2) { ["range"]=> array(2) { ["s"]=> string(12) "212.12.24.12" ["e"]=> string(12) "212.13.25.14" } ["addr"]=> string(6) "山西" }
二、Python二分查找法获取IP地理位置
1、Python获取用户客户端IP地址import requests def getClientIp(res): strUip = ""; if res.headers.get("HTTP_CLIENTIP6") is not None: strUip = res.headers.get("HTTP_CLIENTIP6") elif res.headers.get("HTTP_X_FORWARDED_FOR") is not None and res.headers.get("HTTP_X_FORWARDED_FOR") != "unknown": strUip = res.headers.get("HTTP_X_FORWARDED_FOR") elif res.headers.get("HTTP_CLIENT_IP") is not None and res.headers.get("HTTP_CLIENT_IP") != "unknown": strUip = res.headers.get("HTTP_CLIENT_IP") elif res.headers.get("REMOTE_ADDR") is not None and res.headers.get("REMOTE_ADDR") != "unknown": strUip = res.headers.get("REMOTE_ADDR") elif res.headers.get("HTTP_X_BD_USERIP") and res.headers.get("HTTP_X_BD_USERIP") != "unknown": strUip = res.headers.get("HTTP_X_BD_USERIP") return strUip; res = requests.get("https://www.baidu.com") strUip = getClientIp(res); print(strUip); 执行结果: 183.199.168.188
2、Python二分查找法获取IP地理位置import socket, struct def isset(arr, key): try: type(arr[key]) except: return False return True def ip2long(strIp): return struct.unpack("!L", socket.inet_aton(strIp))[0] def search_ip_addr_recursion(arrIp, intLow, intHigh, intIp): intMiddle = int((intLow + intHigh) / 2) if intLow > intHigh: return -1 if isset(arrIp[intMiddle], "ip"): intMiddleIp = ip2long(arrIp[intMiddle]["ip"]) if intMiddleIp == intIp: return intMiddle if intIp > intMiddleIp: return search_ip_addr_recursion(arrIp, intMiddle + 1, intHigh, intIp) elif intIp < intMiddleIp: return search_ip_addr_recursion(arrIp, intLow, intMiddle - 1, intIp) else: intMiddleStartIp = ip2long(arrIp[intMiddle]["range"]["s"]) intMiddleEndIp = ip2long(arrIp[intMiddle]["range"]["e"]) if intIp >= intMiddleStartIp and intIp <= intMiddleEndIp: return intMiddle if intIp > intMiddleEndIp: return search_ip_addr_recursion(arrIp, intMiddle + 1, intHigh, intIp) elif intIp < intMiddleEndIp: return search_ip_addr_recursion(arrIp, intLow, intMiddle - 1, intIp) arrIp = [ {"ip": "202.132.13.12", "addr":"北京"}, {"range": {"s": "212.12.24.12", "e": "212.13.25.14"}, "addr": "山西"}, {"range": {"s": "212.13.25.15", "e": "212.15.25.14"}, "addr": "河北"}, ] intIp = ip2long("212.12.24.13"); #intIp = ip2long("202.132.13.12"); intIndex = search_ip_addr_recursion(arrIp, 0, len(arrIp), intIp); print(intIndex) if -1 == intIndex: print("None") else: print(arrIp[intIndex]) 执行结果: 1 {"range": {"s": "212.12.24.12", "e": "212.13.25.14"}, "addr": "山西"}
三、总结Python的代码是根据PHP代码平移过来的。PHP函数用Python函数替换或def定义。语言语法按标准替换就行。 查找方法需要将ip段按从小到大排好顺序可以写入内存中减少不必要的查询。 头条有定义"I P属地以运营商信息为准,境内显示到省(区、市),境外显示到国家(地区) "。表示IP需要实时或定时的与运营商IP信息同步。数据上可能存在时差的情况。IP信息的定义可以更丰富更全个人只是测试代码用。
大家有什么更好的解决方案或算法可以发评论沟通。业务上都是调别人的接口像百度都是调用百度地图的开放API接口。
Go语言的等我把Golang学的再深入一点再介绍给大家[呲牙]。
感谢大家的评论、点赞、分享、关注…