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 的相对地理位置:

2023-03-16-152007.png

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

更新 GeoIP2 数据库

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

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

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

2023-03-16-224948.png

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

2023-03-16-225912.png

主要是三个配置:

  • AccountID
    • 2023-03-16-222857.png
  • LicenseKey
    • 2023-03-16-223037.png
  • EditionIDs GeoLite2-City GeoLite2-Country
    • 要更新的数据库版本 ID
    • 多个版本 ID 用空格分隔

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

2023-03-16-231619.png

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容