Python离线解析IP地址

首先要介绍一家公司,总部位于波士顿和马萨诸塞州的 MaxMind 公司成立于2002年,在提供几何定位和在线欺诈工具方面处于领先地位,主要提供以下两项服务:

  • minFraud:帮助企业防止网上信用卡交易中的欺诈行为,通过其全面的欺诈检测系统,企业可以准确地检测并自动对欺诈性质的 “卡不在场交易” 进行标注。
  • GeoIP:可以按国家、地域位置甚至精确到城市,对企业用户和网站的访客进行精准实时的定位。

为啥要介绍这家公司呢?因为他们除了 GeoIP 这个付费服务,另外还提供可以 免费本地部署GeoLite2 离线 数据库,可以让我们在不使用第三方接口的情况,解析 IP 地址的地理位置数据。

下载数据库

需要一个注册 MaxMind 账户才能下载 GeoLite2 免费地理位置数据文件。注册时除了 “邮箱” 需要认真填写(登录时使用 “邮箱” 作为账户名称)之外,其它可以随意,提交注册后 MaxMind 会给你的邮箱发一封邮件,需要点击邮件里的链接以完成注册。

登录后可以打开 GeoLite2 离线数据库下载页面 找到需要的数据库文件:

Database 包含信息 数据库格式
GeoLite2 ASN 自治域 AS 或者运营商 ISP MaxMind DB 格式
GeoLite2 ASN: CSV Format IP 地址所属的自治域 AS 或者运营商 ISP CSV 文件格式
GeoLite2 City IP 地址所在的国家、地区、城市、经纬度和邮政编码等信息 MaxMind DB 格式
GeoLite2 City: CSV Format IP 地址所在的国家、地区、城市、经纬度和邮政编码等信息 CSV 文件格式
GeoLite2 Country IP 地址所在的国家和洲 MaxMind DB 格式
GeoLite2 Country: CSV Format IP 地址所在的国家和洲 CSV 文件格式

两种数据库格式的差别:

  • CSV 文件格式:需要自己实现掩码解析和 ID 查询。
  • MaxMind DB 格式:借助 GeoIP2 库提供的方法,输入 IP 地址就可以进行本地 IP 信息查询。

下面的例子里,需要下载 GeoLite2 City 数据文件,因为它较其他两者而言,包含的信息更丰富。

安装 GeoIP2 库

使用下面的命令直接安装,或者到 PyPI geoip2 下载文件安装。

pip install geoip2

使用 GeoIP2 数据库

把下载好的 MaxMind DB 格式 数据库压缩文件解压到项目目录下面,并将数据库的文件路径配置到 geoip2.database.Reader 对象中,再向其传递我们要查询的 IP 地址,如果查询成功,变量 response 将会是一个 geoip2.models.City 类型的数据:

import geoip2.database

# 这里只是演示,实际应用时,数据库 Reader 对象应该要重用, 因为它的创建成本很高
with geoip2.database.Reader('GeoLite2-City_20230314/GeoLite2-City.mmdb') as reader:
    response = reader.city('128.101.101.101')
    print(f'城市 = {
      
      response.city.names["zh-CN"]}')
    print(f'大洲 = {
      
      response.continent.names["zh-CN"]}')
    print(f'国家 = {
      
      response.country.names["zh-CN"]}')
    print('位置:')
    print(f'---- 精度半径 = {
      
      response.location.accuracy_radius}')
    print(f'---- 纬度 = {
      
      response.location.latitude}')
    print(f'---- 经度 = {
      
      response.location.longitude}')
    print(f'---- 时区 = {
      
      response.location.time_zone}')
    print(f'邮政编码 = {
      
      response.postal.code}')
    print(f'注册国家 = {
      
      response.registered_country.names["zh-CN"]}')
    print('地区细分:')
    for subdivision in response.subdivisions:
        print(f'.... {
      
      subdivision.names["zh-CN"]}')

执行上面的代码,会输出下面的内容:

城市 = 明尼阿波利斯
大洲 = 北美洲
国家 = 美国
位置:
---- 精度半径 = 10
---- 纬度 = 44.9402
---- 经度 = -93.2188
---- 时区 = America/Chicago
邮政编码 = 55406
注册国家 = 美国
地区细分:
.... 明尼苏达州

跑通之后可以全面的看一下 geoip2.models.City 类型的 response 变量中,包含哪些数据:

geoip2.models.City(
    {
    
    
        'city': {
    
    
            'geoname_id': 5037649,
            'names': {
    
    
                'de': 'Minneapolis',
                'en': 'Minneapolis',
                'es': 'Mineápolis',
                'fr': 'Minneapolis',
                'ja': 'ミネアポリス',
                'pt-BR': 'Minneapolis',
                'ru': 'Миннеаполис',
                'zh-CN': '明尼阿波利斯'
            }
        },
        'continent': {
    
    
            'code': 'NA',
            'geoname_id': 6255149,
            'names': {
    
    
                'de': 'Nordamerika',
                'en': 'North America',
                'es': 'Norteamérica',
                'fr': 'Amérique du Nord',
                'ja': '北アメリカ',
                'pt-BR': 'América do Norte',
                'ru': 'Северная Америка',
                'zh-CN': '北美洲'
            }
        },
        'country': {
    
    
            'geoname_id': 6252001,
            'iso_code': 'US',
            'names': {
    
    
                'de': 'Vereinigte Staaten',
                'en': 'United States',
                'es': 'Estados Unidos',
                'fr': 'États Unis',
                'ja': 'アメリカ',
                'pt-BR': 'EUA',
                'ru': 'США',
                'zh-CN': '美国'
            }
        },
        'location': {
    
    
            'accuracy_radius': 10,
            'latitude': 44.9402,
            'longitude': -93.2188,
            'metro_code': 613,
            'time_zone': 'America/Chicago'
        },
        'postal': {
    
    
            'code': '55406'
        },
        'registered_country': {
    
    
            'geoname_id': 6252001,
            'iso_code': 'US',
            'names': {
    
    
                'de': 'Vereinigte Staaten',
                'en': 'United States',
                'es': 'Estados Unidos',
                'fr': 'États Unis',
                'ja': 'アメリカ',
                'pt-BR': 'EUA',
                'ru': 'США',
                'zh-CN': '美国'
            }
        },
        'subdivisions': [{
    
    
            'geoname_id': 5037779,
            'iso_code': 'MN',
            'names': {
    
    
                'en': 'Minnesota',
                'es': 'Minnesota',
                'fr': 'Minnesota',
                'ja': 'ミネソタ州',
                'pt-BR': 'Minesota',
                'ru': 'Миннесота',
                'zh-CN': '明尼苏达州'
            }
        }],
        'traits': {
    
    
            'ip_address': '128.101.101.101',
            'prefix_len': 21
        }
    },
    ['en'],
)

然后我们还可以利用返回的经纬度信息,去定位 IP 的相对地理位置:

扫描二维码关注公众号,回复: 15781081 查看本文章

在这里插入图片描述

如果遇到错误和异常,可以查看 官方客户端接口 文档。

更新 GeoIP2 数据库

由于 IP 信息的新增和修改申请每天都在进行,所以免费的 GeoLite2 离线数据库平均每月更新两次,为了保证 IP 查询的准确性,定期更新离线数据库是有必要的(虽然这并不能保证 IP 地址的信息 100% 准确,毕竟这中间有半个月左右的更新延迟)。

最简单但不长久的方式是 手动下载文件 来完成同步更新,所以建议使用 MaxMind 提供的 GeoIP 更新程序 进行自动更新,详情查看 更新 GeoIP 和 GeoLite 数据库 文档。

以 Windows 版本的 GeoIP 更新程序 为例,我们需要提前创建好 C:\ProgramData\MaxMind\GeoIPUpdate 目录,并把下载好的压缩包解压到这个目录下,并同时新建一个 GeoIP 目录:

在这里插入图片描述

然后打开 GeoIP.conf 文件,编辑一下自动更新相关的配置:

在这里插入图片描述

主要是三个配置:

  • AccountID

    • 在这里插入图片描述
  • LicenseKey

    • 在这里插入图片描述
  • EditionIDs GeoLite2-City GeoLite2-Country

    • 要更新的数据库版本 ID
    • 多个版本 ID 用空格分隔

编辑完成后保存 GeoIP.conf 文件,然后我们就可以运行 geoipupdate.exe 文件,它会执行一段时间,执行完成后,在 GeoIP 目录下,会出现它帮我们下载好的最新版本的数据库文件:

在这里插入图片描述

在 Windows 版本下,需要手动执行,而在 Linux 或 Unix 版本上则可以实现自动化更新过程,例如:每周运行两次,每次更新都会通过电子邮件将结果发送给您。具体的实现方式可以查看 运行 GeoIP 更新 文档。

猜你喜欢

转载自blog.csdn.net/hekaiyou/article/details/129578857