使用免费GeoLite2-City.mmdb进行IP信息解析和地理定位
通过输入一个IP地址,解析并获取信息,比如国家、国家代码、省份、省份代码、城市、邮政编码、经纬度等等信息
例如,解析ip(128.101.101.101)的信息如下:
实现方式及区别
使用在线第三方提供的api:
- ip-api.com
- ip.taotao.com
- 百度地图api
- 新浪 iplookup
使用离线查询方式:
- 纯真库
- GeoLite2
- 埃文科技
数据丰富度对比:
查询准确率比较:
查询速度比较:
总结: 需要速度用离线,需要准确率用在线,需要数据丰富性GeoLite2、埃文科技,需要免费用GeoLite2(埃文科技虽说国内头头,奈何收费)
python代码实现
本文介绍使用离线的GeoLite2来解析IP获取目标的地理位置
需要下载GeoLite2-City.mmdb,地址:https://github.com/wp-statistics/GeoLite2-City.git,并将该包解压与下述代码放置同一文件夹。
需要安装geoip2模块:pip install geoip2
import re import geoip2.database reader = geoip2.database.Reader('GeoLite2-City.mmdb') # 查询IP地址对应的物理地址 def ip_get_location(ip_address): # 载入指定IP相关数据 response = reader.city(ip_address) #读取国家代码 Country_IsoCode = response.country.iso_code #读取国家名称 Country_Name = response.country.name #读取国家名称(中文显示) Country_NameCN = response.country.names['zh-CN'] #读取州(国外)/省(国内)名称 Country_SpecificName = response.subdivisions.most_specific.name #读取州(国外)/省(国内)代码 Country_SpecificIsoCode = response.subdivisions.most_specific.iso_code #读取城市名称 City_Name = response.city.name #读取邮政编码 City_PostalCode = response.postal.code #获取纬度 Location_Latitude = response.location.latitude #获取经度 Location_Longitude = response.location.longitude if(Country_IsoCode == None): Country_IsoCode = "None" if(Country_Name == None): Country_Name = "None" if(Country_NameCN == None): Country_NameCN = "None" if(Country_SpecificName == None): Country_SpecificName = "None" if(Country_SpecificIsoCode == None): Country_SpecificIsoCode = "None" if(City_Name == None): City_Name = "None" if(City_PostalCode == None): City_PostalCode = "None" if(Location_Latitude == None): Location_Latitude = "None" if(Location_Longitude == None): Location_Longitude = "None" print('================Start===================') print('[*] Target: ' + ip_address + ' GeoLite2-Located ') print(u' [+] 国家编码: ' + Country_IsoCode) print(u' [+] 国家名称: ' + Country_Name) print(u' [+] 国家中文名称: ' + Country_NameCN) print(u' [+] 省份或州名称: ' + Country_SpecificName) print(u' [+] 省份或州编码: ' + Country_SpecificIsoCode) print(u' [+] 城市名称 : ' + City_Name) print(u' [+] 城市邮编 : ' + City_PostalCode) print(u' [+] 纬度: ' + str(Location_Latitude)) print(u' [+] 经度 : ' + str(Location_Longitude)) print('===============End======================') # 检验和处理ip地址 def seperate_ip(ip_address): ip_match = r"^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[1-9]|0?[1-9]0)\.)(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){2}(?:25[0-4]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[1-9]|0?[1-9]0)$" ip_match_list = r"^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[1-9]|0?[1-9]0)\.)(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){2}(?:25[0-4]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[1-9])-(?:25[0-4]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[1-9]|0?[1-9]0)$" if re.match(ip_match, ip_address): try: ip_get_location(ip_address) except Exception as e: print(e) elif re.match(ip_match_list, ip_address): ip_start = ip_address.split('-')[0].split('.')[3] ip_end = ip_address.split('-')[1] # 如果ip地址范围一样,则直接执行 if(ip_start == ip_end): try: seperate_ip(ip_address.split('-')[0]) except Exception as e: print(e) elif ip_start > ip_end: print('the value of ip, that you input, has been wrong! try again!') exit(0) else: ip_num_list = ip_address.split('-')[0].split('.') ip_num_list.pop() for ip_last in range(int(ip_start), int(ip_end)+1): ip_add = '.'.join(ip_num_list)+'.'+str(ip_last) try: ip_get_location(ip_add) except Exception as e: print(e) else: print('Wrong type of ip address!') print('100.8.11.58 100.8.11.58-100 alike!') if __name__ == '__main__': seperate_ip('39.99.228.188') ''' ================Start=================== [*] Target: 39.99.228.188 GeoLite2-Located [+] 国家编码: CN [+] 国家名称: China [+] 国家中文名称: 中国 [+] 省份或州名称: Zhejiang [+] 省份或州编码: ZJ [+] 城市名称 : Hangzhou [+] 城市邮编 : None [+] 纬度: 30.294 [+] 经度 : 120.1619 ===============End====================== '''
django 中从META中获取IP
ip = x_forwarded_for.split(',')[0] # 所以这里是真实的ip ip = request.META.get('REMOTE_ADDR') # 这里获得代理ip
def get_ip(request): """获取访问页面及客户端ip地址""" ip = None proxy_ip = None server_name = request.META.get('SERVER_NAME') if request.META.get('HTTP_X_FORWARDED_FOR'): ip = request.META.get("HTTP_X_FORWARDED_FOR") proxy_ip = request.META.get("REMOTE_ADDR") else: ip = request.META.get("REMOTE_ADDR") # 获取物理地址 try: address = ip_address(ip) except: address = '获取失败' # 写入日志文件 log_init().info(f'{server_name} {ip} {address}') return HttpResponse(ip)
IP地址定位查询
@retry(stop_max_attempt_number=5) def ip_address(ip): """ip地址查询物理地址""" url = f'http://api.map.*****.com/location/ip?ak=*******j&ip={ip}&coor=bd09ll' rsp = requests.get(url, timeout=10).text content = json.loads(rsp) # 请求状态 0有数据 1无数据 status = content['status'] if status: return content['message'] address = content['content']['address'] return address
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!