纯真CZDB新格式IP库实战:与GeoLite2对比及Python读取指南

发布时间:2026/9/15 21:17:43
纯真CZDB新格式IP库实战:与GeoLite2对比及Python读取指南 前段时间我重构一个内部日志分析服务需要把每一条访问记录都打上地理位置和网络归属。最开始图省事直接用了 GeoLite2 免费版毕竟在全球 IP 覆盖上它确实是有口碑的。但真正跑起来以后问题就一个接一个来了国内一些 IP 的运营商字段经常对不上内网地址直接没法识别IPv6 段偶尔还有空缺。后来朋友提了一句纯真出新格式 CZDB 了社区版还免费我就顺手实测了一轮。这一测不要紧发现这个国产 IP 库在不少维度上出乎意料地能打于是有了这篇文章。这篇不打算写成官方文档的复述而是以一个实际使用者的角度把 CZDB 的文件结构、读取流程、数据对比、生产落地这些事完整讲一遍。如果你是做数据分析、日志解析、风控策略或者用户位置展示的手头正在纠结 IP 库选型那这篇应该能帮你省下不少调研时间。对免费 IP 库、Python 如何读取这类高频问题我也会在实操部分给出可直接抄的答案。1. 为什么我会把目光从 GeoLite2 移到纯真 CZDB1.1 旧方案在真实场景里暴露出的短板先说背景。我当时的需求其实很典型每天几千万条访问日志要按 IP 判断访问者来自哪个城市、用的哪家运营商偶尔还需要判断是不是机房 IP方便在报表里把爬虫流量和真实用户流量分开看。GeoLite2 免费版的核心能力是国家-省份-城市三级地理定位外加一个独立的 GeoLite2 ASN 库用来查自治域。这套组合在国际场景非常好用但放到国内业务里就有几个尴尬的地方。运营商识别基本是空白。免费版不提供 ISP 字段而国内做用户分析时电信/联通/移动这种维度又很常用。我们只能靠 ASN 去猜比如 AS4134 是电信、AS4837 是联通、AS9808 是移动但猜出来的结果并不总是准确尤其是那些同时被多家运营商路由的 IP。内网与保留地址没有归属信息。访问日志里经常混入 10.x、192.168.x 这类私网地址。GeoLite2 对它们直接返回空或者落在某个奇怪的地区报表里就会多出一批未知。IPv6 的覆盖不够细。免费版对大网段的 IPv6 定位到国家没问题但到城市一级经常失败或者是粗粒度到省级就停了。对我们这种想按城市聚合数据的系统来说这等于少了一个可用的维度。1.2 纯真社区版 CZDB 是什么纯真IP库在国内应该没人陌生很多老项目用的还是它的传统 .dat 格式特点就两个离线、免费社区版数据按季度更新。但这个格式有个历史包袱查询性能一般解析库也多为第三方维护质量参差不齐。CZDB 是纯真推出的新一代数据库格式全称大致是 CZ Database。社区版以离线压缩包形式提供包含 IPv4 和 IPv6 两个库文件命名类似 czdb_v4.db、czdb_v6.db。和旧 .dat 最大的区别是它有明确的头部元数据、索引区和文本区分离支持内存映射直接查询定位速度比传统逐条扫描快很多。另外社区版本身就带内网/保留地址这种分类条目国内运营商数据也齐全这对国内业务来说几乎是量身定制的。1.3 我给自己定下的三个验证目标动手之前我给自己列了三个问题后文所有的实测都是围绕这三个问题展开的CZDB 这种新格式是否真的容易解析文档少不少还是说必须依赖官方 SDK社区版的数据质量能不能扛住真实查询尤其是境内 IP 的城市和运营商识别能不能替代 GeoLite2它适合放生产环境吗内存占用、查询性能、更新流程是否可控接下来的内容就是对这三个问题的逐项拆解。2. CZDB 文件格式拆解一段不靠数据库的离线查找2.1 整体文件结构CZDB 不是传统数据库它更像一本自带索引的词典。文件里没有表没有 SQL没有任何服务端进程。你要做的只是把文件读进内存然后按索引去查文本结果。从文件布局上说它大致分成三块头部元数据区、索引区、文本数据区。头部元数据区保存了文件版本、创建时间、IP 类型IPv4 还是 IPv6、索引区偏移量、索引区长度、文本区偏移量、文本区长度以及用于校验的 MD5 信息。官方 SDK 读取文件的第一步就是解析这块头部拿到后面所有区域的精确坐标。索引区是IP 网段到文本偏移量的映射。每一条索引记录通常包含起始 IP、结束 IP以及该网段对应文本在文本区的偏移量。因为 IP 地址可以被转成整数所以这个索引天然支持二分查找。文本数据区存放的就是地区|运营商这类可读字符串多条数据之间用分隔符切开以字节形式存在文件尾部。查询时一旦在索引区定位到网段就能拿到偏移量再回文本区把字符串读出来。我个人的理解是CZDB 把一本厚书做成了带有页码索引的版本。你要查一个 IP只翻一次目录然后直接跳到你需要的页码而不需要打开书一页一页找。2.2 从头部到索引读取的完整路径官方文档里对 CZDB 的介绍比较精简好在头部结构不算复杂。我以 Python 为例用流式方式读取头部最核心的几个字段。import struct from pathlib import Path data Path(czdb_v4.db).read_bytes() # 假设前 4 字节是签名第 5 字节开始是版本等元信息 signature data[:4] version struct.unpack(I, data[4:8])[0] # 索引区偏移量和长度在头部中段具体偏移依据 SDK 定义 index_offset struct.unpack(Q, data[20:28])[0] index_length struct.unpack(Q, data[28:36])[0] text_offset struct.unpack(Q, data[36:44])[0] text_length struct.unpack(Q, data[44:52])[0]这里只是一个简化的示意实际读取时字段位置、字节序要以官方 SDK 的解析逻辑为准。但从流程上讲所有语言的读取方式都是一样的先解析头部拿到索引区和文本区坐标再做查询。查询时的大致路径是把 IP 地址转成整数。IPv4 转成 32 位无符号整数IPv6 转成两个 64 位整数或交由哈希函数处理。在索引区用二分查找找到第一个起始 IP 小于等于目标 IP、结束 IP 大于等于目标 IP 的记录。取出这条记录中的文本偏移量。到文本区按偏移量读取字节然后按编码解析成字符串。由于索引区是连续内存块读取过程几乎不涉及磁盘随机 IO性能相当稳定。2.3 CZDB 为什么性能更好这里要说一个旧 .dat 格式的痛点。老格式查询时常常需要从头扫描网段列表或者依赖第三方解析库在内存里做逐条匹配。如果列表本身没有排好序查询复杂度可能退化到 O(n)数据量一大性能就非常难看。CZDB 自带有序索引和二分查找单次查询复杂度是 O(log n)。在百万级网段规模下这个差距是肉眼可见的。配合内存映射mmap文件不需要整体读进内存操作系统会按页按需加载启动时基本感觉不到加载耗时查询时缺页中断也不算频繁。对这种读多写少、一次加载长期驻留的场景内存映射几乎是完美方案。顺便说一句CZDB 还有针对 IPv6 的版本。IPv6 地址空间大网段数量也更多所以 IPv6 库文件通常比 IPv4 大不少。设计上依然沿用同样的索引 文本偏移结构只是 IP 的整数表示更长。注意CZDB 文件是离线快照它不是实时数据。任何 IP 库都无法做到 100% 实时准确因为 IP 段归属会随网络调度变化。这也是为什么重要场景最好两套库交叉验证。3. 三分钟跑通Python 读取 CZDB 的完整实操3.1 准备阶段从哪里拿库和 SDK纯真官方提供了 C、C、Java、Go、Python 的 SDK社区也有不少语言绑定。我用的是 Python 版本pip 直接可以安装官方或者社区封装的包名字可能是czdb或类似名称以实际仓库为准。库文件的获取也很简单纯真官网或 GitHub 的 releases 页面下载社区版压缩包解压后通常包含两个核心文件一个 IPv4 库、一个 IPv6 库。社区版免费但要注意许可证条款。纯真 CZDB 社区版采用的是知识共享许可协议非商业用途可以免费使用拿去盈利前一定要看具体的许可说明。3.2 最小可运行示例下面这段代码是我在项目里的实际用法。为了让读者能直接看懂我做了简化import czdb # 初始化查询对象传入 IPv4 库文件路径 db czdb.CZDB() db.load(czdb_v4.db) ip_list [223.5.5.5, 114.114.114.114, 8.8.8.8, 192.168.1.1] for ip in ip_list: result db.lookup(ip) print(f{ip} - {result})输出结果大致是这种风格不同版本库文件的内容会有差异以下为示意223.5.5.5 - 浙江省杭州市 阿里云 114.114.114.114 - 江苏省南京市 电信 8.8.8.8 - 美国 加利福尼亚州 圣克拉拉 192.168.1.1 - 内网IP对 Python 新手来说上面这段代码已经够用了。但真实项目里我不会逐个 IP 去循环调用因为 Python 的 GIL 对大并发查询不友好后面第 5 章会讲生产化的做法。3.3 查询结果字段怎么解读CZDB 社区版返回的文本字段一般包含地理区域和网络归属两个维度。常见格式是大洲/国家/省份/城市 运营商这样一条字符串具体粒度取决于库文件的版本。内置的内网IP保留IP分类对日志分析特别有用。查询内网地址时返回的不是空而是一个明确的分类标签。这样在数据清洗阶段就能直接把内网流量过滤掉不用再维护一份私网网段表去比对。我在对比测试中发现GeoLite2 免费版对这个场景直接返回空字符串处理起来要额外写规则。IPv6 库同理只是内部处理逻辑更复杂。官方 SDK 会判断输入的 IP 类型如果是 IPv6 地址就去加载 IPv6 库查询逻辑一致。3.4 性能实测加载时间和单次查询耗时我的测试机器是一台 4 核 8G 的云主机Python 3.10SSD 磁盘。加载 IPv4 库文件到内存并完成索引初始化耗时约 0.2 秒IPv6 库文件更大约 0.5 秒。单次查询在毫秒级以下平均在 0.1 到 0.3 毫秒之间放到 Go 或 C 里还会更快。用 Python 直接写个简单压测脚本可以这样测import time import random def gen_random_ip(): return ..join(str(random.randint(0, 255)) for _ in range(4)) start time.time() for _ in range(100000): db.lookup(gen_random_ip()) cost time.time() - start qps 100000 / cost print(fQPS: {qps:.0f}, 单次平均耗时: {cost / 100000 * 1000:.3f} ms)注意这里把随机 IP 生成也计入耗时了实际纯查询耗时更低。如果追求极限性能预生成 IP 列表、跳过 IP 解析环节单线程 QPS 可以到几万甚至更高。提示Python 环境里做性能压测最好先用timeit或perf_counter不要用time.time()统计短耗时精度不够。上面的脚本只是为了演示整体量级不是基准测试的严谨写法。4. 正面硬刚CZDB 与 GeoLite2 的数据质量对比4.1 同一个 IP两套库给出的答案光看格式解析还不够IP 库好不好用最终要看查出来的数据准不准。我拿了一批国内常见公共 IP 和几个特定网段做对比结果很有代表性。拿公共 DNS 地址 223.5.5.5 来说GeoLite2 免费版定位结果中国浙江省杭州市ASN 查询显示属于阿里云。CZDB 社区版定位结果浙江省杭州市 阿里云。这次双方一致。但换到 114.114.114.114GeoLite2中国江苏省南京市ASN 显示属于南京信风网络。CZDB中国江苏省南京市 电信。从精确度看两者在城市级别一致但 CZDB 直接给出了运营商电信而 GeoLite2 免费版没有 ISP 字段只能根据 ASN 去反推。对于不懂 ASN 映射的团队CZDB 显然是更省事的。再看内网地址 192.168.1.1GeoLite2空结果。CZDB内网IP。这看起来是小功能但日志清洗场景真的太需要了。日志系统里内网地址占比不小如果能直接打上内网标签后续聚合统计就少了一堆脏数据。4.2 抽样测试境内 IP 谁更细为了能有个量化结论我做了个简单抽样从线上日志里随机抽了 1000 个境内 IP。再从境外访问 IP 里抽了 500 个。分别用两套库查询比对城市命中率和运营商识别能力。结果大概是这样对比项CZDB 社区版GeoLite2 免费版境内城市级别命中率约 95% 以上约 85% 左右运营商字段有电信/联通/移动等直接展示免费版无 ISP 字段区县级别数据部分城市能细分到区县基本到城市为止境外国家命中率覆盖可用但部分小国数据偏粗覆盖率高且稳定内网/保留地址有专门分类返回空IPv6 城市级精度境内部分可到城市部分粗粒度到省/州这个结果并不意外。GeoLite2 本来就是全球视角在境外 IP 覆盖上沉淀多年纯真是国内起家境内数据的细粒度自然有优势。对以国内业务为主的团队CZDB 在城市和运营商这两个维度上明显更顺手。4.3 境外 IP还是 GeoLite2 的天下我要客观说一句纯真 CZDB 在境外数据的丰富度上比不过 GeoLite2。比如查询一些欧洲小国的 IPCZDB 社区版可能只给到国家一级而 GeoLite2 通常能定位到城市。如果业务面向全球用户或者需要精确到境外城市做区域分析GeoLite2 依然是更稳的选择。所以在我的实际项目里最后的方案不是二选一而是分工境内流量走 CZDB境外流量走 GeoLite2。两者的分发逻辑不复杂先用一个精简的国家判断规则把 IP 分流再分别查询。这个思路我会在第 5 章展开说。4.4 体积与更新成本对比文件体积方面纯真 IPv4 库社区版通常是几十到一百多 MB 级别IPv6 库稍大GeoLite2 免费版按城市、ASN 分成多个文件合计体积也不小。两者都是离线文件更新方式都是下载新压缩包然后替换。GeoLite2 的官方建议是一个月更新一次纯真社区版则是按季度发布新版。季度更新对大多数场景够用毕竟一个 IP 段从一个运营商迁移到另一个运营商的频率并不高。许可证方面要啰嗦一句GeoLite2 免费版有 Atlassian 风格的限制条款实际是 MaxMind 的 EULA虽然允许大多数商业用途但有一些附加条件纯真社区版是 CC BY-NC-SA非商业用途免费商业用途需要购买授权。两者都不存在免费即随便用的情况生产环境引入前最好让法务或负责人过一眼条款。5. 生产落地与避坑手册那些文档里没写的事5.1 我在集成过程中踩过的坑坑 1把 CZDB 当 .dat 去读。旧 .dat 格式有很多现成解析库但 CZDB 是新的文件结构老库读不了读出来是一堆乱码字段。解决方案很简单用官方配套 SDK别去改老代码。坑 2IPv6 库和 IPv4 库混用。官方 SDK 会根据 IP 类型自动选择库文件但如果你用自定义解析逻辑一定要先判断 IP 版本再决定加载哪个文件。混用会导致查询结果为空或者直接报错。坑 3文件路径中的中文名问题。我在 Windows 下测试时把库文件放在带中文的目录里Python SDK 读取报错。后来改成英文路径才正常。Linux 服务器上倒是没有遇到过但为了保险建议统一用英文路径。坑 4文本编码问题。CZDB 返回的字符串一般是 UTF-8 或 GBK 编码具体看库文件编译时的设置。如果打印出来是乱码先检查编码再检查字段偏移不要急着怀疑库文件损坏。坑 5并发读取与文件句柄。CZDB 的 SDK 大多数是只读设计初始化后常驻内存多线程查询时一般没有写冲突。但如果你在 Web 服务里每来一个请求就 new 一个查询对象文件句柄会迅速耗尽。正确做法是全局初始化一次查询时复用同一个实例。5.2 如何搭一个高性能的 IP 查询服务生产中我一般不用 Python 直接对外提供高并发查询接口而是把它封装成一个内网 RPC 服务后端用 Go 或 CPython 只做管理脚本和离线分析调用。架构大概是这样服务启动时加载 CZDB 文件到内存建立好索引映射。接收查询请求参数是 IP 字符串或二进制 IP 地址。在内存中完成二分查找返回 JSON 格式的结果。定期检查库文件版本发现新版本后热更新不用重启进程。这样设计的好处是IP 库只加载一次后续所有请求都在内存中完成性能非常稳定。对绝大多数业务来说单机 QPS 几千到上万都够用了。更新流程里有一个小细节不要把新库文件直接覆盖旧文件。正确做法是先下载到临时文件校验 MD5 无误后再移动替换避免服务读到一半文件、拿到损坏数据。这个习惯跟数据库备份是一个道理。5.3 CZDB 与 GeoLite2 混合使用的分流策略前面提到过我最后是两套库同时用的。分流逻辑并不复杂核心是境内走 CZDB境外走 GeoLite2。实现上可以先在 CZDB 里查这个 IP如果结果中包含中国字样就取 CZDB 的省份、城市、运营商字段如果显示为境外国家就再调 GeoLite2 查更细的境外城市数据。示例伪代码如下res czdb.lookup(ip) if res and 中国 in res: return parse_czdb(res) else: geo geoip.lookup(ip) return parse_geolite2(geo)这种混合策略带来的效果是境内数据精度、运营商识别都由 CZDB 负责境外覆盖由 GeoLite2 兜底两边各自的短板都被补齐了。代价是要多维护一套库和两套解析逻辑但对于看重准确率的业务这点成本完全值得。5.4 别忘了 IP 库的时效性最后说一个容易被忽略的点IP 库的时效性。IP 地址段的归属不是一成不变的运营商之间会有网络资源转移IDC 机房也可能更换所有者。所以无论用哪个库都要建立定期更新的意识。我给自己定的节奏是每个季度初检查一次纯真社区版的新包每月拉一次 GeoLite2 更新。更新后跑一遍抽样对比确认数据没抽风再上线。这个流程自动化以后基本不需要人工干预。结语我的选择与一点小建议经过这一轮实测我最终把 CZDB 社区版作为境内 IP 查询的主库GeoLite2 作为境外补充。原因很简单CZDB 在运营商识别和内网地址分类上帮我省了大量清洗时间性能上也足够撑住现有流量而 GeoLite2 依旧是境外数据里最可靠的免费选择之一。要说完美两边都谈不上。CZDB 社区版的商用边界要盯紧GeoLite2 的免费版在境内数据上又确实偏粗。最理想的状态还是像我这样双库并行让各自的强项发挥作用。如果你只是做简单的省份统计那单独用 CZDB 就够了如果你的用户遍布全球再考虑引入 GeoLite2 做兜底。对了最后分享一个我在落地时的小技巧把 IP 库文件的加载逻辑设计成可插拔的对外只暴露一个lookup(ip)接口。这样无论是换库文件、还是切换底层实现上层业务代码都不用动。今天用的是 CZDB GeoLite2明天如果出现更合适的库我只需要替换实现而不是重写整个服务。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询