• 使用免费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
    
  • 相关阅读:
    sed命令:删除匹配行和替换
    使用git rebase合并多次commit
    解决flask中文乱码的问题
    PyCharm 2017: Remote debugging using remote interpreter doesn't work
    ansible小结(八)ansible-playbook简单使用
    ansible命令参数介绍
    eclipse 代码自动提示
    oracle start with connect by prior 递归查询
    Android九宫图(draw9patch)
    Android 通过按钮弹出系统菜单(通过Button显示菜单)转
  • 原文地址:https://www.cnblogs.com/zhangchaocoming/p/13338493.html
Copyright © 2020-2023  润新知