Name | ctlib-geoip JSON |
Version |
0.1.1
JSON |
| download |
home_page | None |
Summary | A GeoIP SDK supporting both sync and async operations |
upload_time | 2025-08-20 10:39:49 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.8 |
license | MIT |
keywords |
codetech
ctlib
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# ctlib-geoip
一个支持同步和异步操作的GeoIP SDK,基于httpx构建,提供高效的IP地理位置查询服务。
## 特性
- 🚀 支持同步和异步操作
- 💾 内置LRU缓存
- 🔄 智能重试机制,支持指数退避
- 📊 支持多种数据源(ipinfo.io, ip-api.com, ip.sb, iplocate.io)
- 🎯 类型安全,完整的类型提示和泛型支持
- 📝 详细的日志记录
- 🌐 灵活的URL模板系统,支持复杂API端点
- 🔧 清晰的参数语义:Unset表示使用默认值,None表示不发送参数
- 🌍 内置地理位置树管理,支持高效的地理位置匹配和访问控制
## 安装
```bash
pip install ctlib-geoip
```
## 快速开始
### 同步使用
```python
from ctlib_geoip import GeoIPClient
# 创建客户端
client = GeoIPClient(url="https://geoip.example.com/api/{ip}")
# 查询IP地址
result = client.lookup("8.8.8.8")
if result:
print(f"IP: {result.ip}")
print(f"国家: {result.country}")
print(f"地区: {result.region}")
print(f"城市: {result.city}")
print(f"数据源: {result.source}")
print(f"更新时间: {result.updated_at}")
```
### 异步使用
```python
import asyncio
from ctlib_geoip import AsyncGeoIPClient
async def main():
# 创建异步客户端
client = AsyncGeoIPClient(url="https://geoip.example.com/api/{ip}")
# 异步查询IP地址
result = await client.lookup("1.1.1.1")
if result:
print(f"IP: {result.ip}")
print(f"国家: {result.country}")
print(f"地区: {result.region}")
print(f"城市: {result.city}")
# 运行异步函数
asyncio.run(main())
```
### 自定义参数
```python
from ctlib_geoip import GeoIPClient
client = GeoIPClient(
url="https://geoip.example.com/api/{ip}",
source="ipinfo.io",
ttl=86400, # 24小时
max_retries=5,
max_wait_time=15,
headers={"User-Agent": "MyApp/1.0"}
)
# 使用默认参数
result1 = client.lookup("8.8.8.8")
# 覆盖特定参数
result2 = client.lookup("8.8.8.8", source="ip-api.com")
result3 = client.lookup("8.8.8.8", ttl=3600)
# 不携带source参数(后端不处理source)
result4 = client.lookup("8.8.8.8", source=None)
```
## API参考
### GeoIPClient
同步客户端类。
#### 参数
- `url: str` - GeoIP服务URL模板,支持 `{ip}` 占位符,如 `https://geoip.example.com/api/{ip}`
- `source: Union[DataSource, str, None] = None` - 数据源,None表示不指定数据源
- `ttl: int = 2592000` - 数据有效期(秒,默认30天)
- `cache_len: int = 256` - 缓存最大条数
- `max_retries: int = 3` - 最大重试次数
- `max_wait_time: int = 10` - 最长等待时间(秒)
- `headers: Dict[str, str] = None` - HTTP请求头
#### 方法
- `lookup(ip: Union[str, IPv4Address], source: SourceType = Unset, ttl: TTLType = Unset, **extra) -> Optional[GeoIP]`
### AsyncGeoIPClient
异步客户端类,参数和方法与同步客户端相同,但所有操作都是异步的。
### GeoIP
数据模型类。
#### 字段
- `ip: str` - IP地址
- `country: str` - 国家代码
- `region: str` - 地区
- `city: str` - 城市
- `updated_at: datetime` - 数据更新时间
- `source: str` - 数据来源
### GeoInfo
地理位置信息模型类。
#### 字段
- `name: Optional[str]` - 地理位置名称
- `country: str` - 国家代码
- `region: Optional[str]` - 地区名称
- `city: Optional[str]` - 城市名称
- `detail: Optional[str]` - 详细描述
- `geo_id: Optional[int]` - 地理位置ID
- `geo_code: Optional[str]` - 地理位置代码(格式:国家-地区-城市)
#### 类方法
- `from_geo_id(geo_id: int)` - 根据地理位置ID查找
- `from_geo_code(geo_code: str)` - 根据地理位置代码查找
- `from_name(name: str)` - 根据名称查找
### GeoTree
地理位置树管理类,用于高效的地理位置匹配和访问控制。
#### 功能特性
- **三层嵌套结构**: 国家(Country) → 地区(Region) → 城市(City)
- **高效查询**: 使用字典结构,查询时间复杂度O(1)
- **灵活匹配**: 支持不同级别的模糊匹配
- **访问控制**: 适用于基于地理位置的权限控制
#### 主要方法
- `add(geo: GeoInfo)` - 添加地理位置信息到树中
- `contains(geoip: GeoIP) -> bool` - 判断GeoIP是否在树中
#### 使用示例
```python
from ctlib_geoip import GeoTree, GeoInfo
# 创建地理位置树
geo_tree = GeoTree([
GeoInfo(country="HK", region="Central and Western"),
GeoInfo(country="CN", region="Guangdong", city="Shenzhen")
])
# 检查GeoIP是否在允许的地理位置范围内
geoip = GeoIP(ip="8.8.8.8", country="HK", region="Central and Western", city="Central")
is_allowed = geo_tree.contains(geoip) # True
```
### Unset
特殊标记类,用于表示使用客户端创建时的默认参数。
### 参数语义说明
- **`Unset`**: 使用客户端创建时设置的默认值
- **`None`**: 不向后端发送该参数
- **具体值**: 使用指定的值覆盖默认值
### URL模板系统
支持灵活的URL模板,例如:
```python
# 基本模板
url = "https://geoip.example.com/{ip}"
# 带查询参数的模板
url = "https://geoip.example.com/api/{ip}?key=value"
# 复杂模板
url = "https://geoip.example.com/v1/geoip/{ip}?format=json&lang=zh"
```
系统会自动处理 `{ip}` 占位符和查询参数的管理。
## 数据源
支持的数据源:
- `ipinfo.io` - IPInfo服务
- `ip-api.com` - IP-API服务
- `ip.sb` - IP.SB服务
- `iplocate.io` - IPLocate服务
也支持自定义数据源。
## 地理位置数据
SDK内置了丰富的地理位置数据,支持以下地区:
- **中国 (CN)**: 包含420个地理位置记录,涵盖所有省份和主要城市
- **香港 (HK)**: 包含20个地区记录,涵盖所有行政区
- **台湾 (TW)**: 包含32个地理位置记录
- **澳门 (MO)**: 包含10个地理位置记录
地理位置数据使用标准化的格式:
- **geo_code格式**: `国家-地区-城市`,如 `HK-NCW---`(香港-中西区)
- **支持查询方式**: 按ID、代码、名称等多种方式查找地理位置信息
## 缓存策略
- 使用LRU缓存
- 缓存结构:`{ip: {source: GeoIP}}`,支持同一IP的多个数据源结果
- TTL过期检查在业务层进行,缓存管理器专注于存储管理
- 智能缓存策略:优先返回指定数据源的结果,其次返回最新结果
## 重试机制
- 支持指数退避重试
- 从1秒开始等待,最大等待时间可配置
- 重试次数可配置
## 日志
使用Python标准logging模块:
- DEBUG级别:记录查询操作
- ERROR级别:记录错误信息
## 高级功能
### 地理位置访问控制
使用GeoTree实现基于地理位置的访问控制:
```python
from ctlib_geoip import GeoTree, GeoInfo, GeoIP
# 定义禁止访问的地理位置
blocked_regions = GeoTree([
GeoInfo(country="US", region="Texas"), # 禁止美国德克萨斯州
GeoInfo(country="US", region="Florida"), # 禁止美国佛罗里达州
GeoInfo(country="HK", region="Yau Tsim Mong"), # 禁止香港油尖旺区
])
def check_access(geoip: GeoIP) -> bool:
"""检查IP地址是否被禁止访问"""
return not blocked_regions.contains(geoip)
# 使用示例
geoip = GeoIP(ip="1.2.3.4", country="US", region="Texas", city="Houston")
if check_access(geoip):
print("允许访问")
else:
print("拒绝访问 - 该地区被禁止访问")
```
### 地理位置数据分析
利用内置的地理位置数据进行区域分析:
```python
from ctlib_geoip import GeoInfo
# 查找特定地理位置信息
shenzhen = GeoInfo.from_name("Shenzhen")
print(f"深圳: {shenzhen.detail}")
# 根据地理位置代码查找
hk_central = GeoInfo.from_geo_code("HK-HCW---")
print(f"香港中西区: {hk_central.name}")
```
## 许可证
MIT License
Raw data
{
"_id": null,
"home_page": null,
"name": "ctlib-geoip",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "codetech, ctlib",
"author": null,
"author_email": "jimin <jimin@codetech.top>",
"download_url": "https://files.pythonhosted.org/packages/f4/ee/ec960ef756589d11f946ebc7601bb3dc2b3fb8a5d8ba1c97be027669fda7/ctlib_geoip-0.1.1.tar.gz",
"platform": null,
"description": "# ctlib-geoip\n\n\u4e00\u4e2a\u652f\u6301\u540c\u6b65\u548c\u5f02\u6b65\u64cd\u4f5c\u7684GeoIP SDK\uff0c\u57fa\u4e8ehttpx\u6784\u5efa\uff0c\u63d0\u4f9b\u9ad8\u6548\u7684IP\u5730\u7406\u4f4d\u7f6e\u67e5\u8be2\u670d\u52a1\u3002\n\n## \u7279\u6027\n\n- \ud83d\ude80 \u652f\u6301\u540c\u6b65\u548c\u5f02\u6b65\u64cd\u4f5c\n- \ud83d\udcbe \u5185\u7f6eLRU\u7f13\u5b58\n- \ud83d\udd04 \u667a\u80fd\u91cd\u8bd5\u673a\u5236\uff0c\u652f\u6301\u6307\u6570\u9000\u907f\n- \ud83d\udcca \u652f\u6301\u591a\u79cd\u6570\u636e\u6e90\uff08ipinfo.io, ip-api.com, ip.sb, iplocate.io\uff09\n- \ud83c\udfaf \u7c7b\u578b\u5b89\u5168\uff0c\u5b8c\u6574\u7684\u7c7b\u578b\u63d0\u793a\u548c\u6cdb\u578b\u652f\u6301\n- \ud83d\udcdd \u8be6\u7ec6\u7684\u65e5\u5fd7\u8bb0\u5f55\n- \ud83c\udf10 \u7075\u6d3b\u7684URL\u6a21\u677f\u7cfb\u7edf\uff0c\u652f\u6301\u590d\u6742API\u7aef\u70b9\n- \ud83d\udd27 \u6e05\u6670\u7684\u53c2\u6570\u8bed\u4e49\uff1aUnset\u8868\u793a\u4f7f\u7528\u9ed8\u8ba4\u503c\uff0cNone\u8868\u793a\u4e0d\u53d1\u9001\u53c2\u6570\n- \ud83c\udf0d \u5185\u7f6e\u5730\u7406\u4f4d\u7f6e\u6811\u7ba1\u7406\uff0c\u652f\u6301\u9ad8\u6548\u7684\u5730\u7406\u4f4d\u7f6e\u5339\u914d\u548c\u8bbf\u95ee\u63a7\u5236\n\n## \u5b89\u88c5\n\n```bash\npip install ctlib-geoip\n```\n\n## \u5feb\u901f\u5f00\u59cb\n\n### \u540c\u6b65\u4f7f\u7528\n\n```python\nfrom ctlib_geoip import GeoIPClient\n\n# \u521b\u5efa\u5ba2\u6237\u7aef\nclient = GeoIPClient(url=\"https://geoip.example.com/api/{ip}\")\n\n# \u67e5\u8be2IP\u5730\u5740\nresult = client.lookup(\"8.8.8.8\")\nif result:\n print(f\"IP: {result.ip}\")\n print(f\"\u56fd\u5bb6: {result.country}\")\n print(f\"\u5730\u533a: {result.region}\")\n print(f\"\u57ce\u5e02: {result.city}\")\n print(f\"\u6570\u636e\u6e90: {result.source}\")\n print(f\"\u66f4\u65b0\u65f6\u95f4: {result.updated_at}\")\n```\n\n### \u5f02\u6b65\u4f7f\u7528\n\n```python\nimport asyncio\nfrom ctlib_geoip import AsyncGeoIPClient\n\n\nasync def main():\n # \u521b\u5efa\u5f02\u6b65\u5ba2\u6237\u7aef\n client = AsyncGeoIPClient(url=\"https://geoip.example.com/api/{ip}\")\n\n # \u5f02\u6b65\u67e5\u8be2IP\u5730\u5740\n result = await client.lookup(\"1.1.1.1\")\n if result:\n print(f\"IP: {result.ip}\")\n print(f\"\u56fd\u5bb6: {result.country}\")\n print(f\"\u5730\u533a: {result.region}\")\n print(f\"\u57ce\u5e02: {result.city}\")\n\n\n# \u8fd0\u884c\u5f02\u6b65\u51fd\u6570\nasyncio.run(main())\n```\n\n### \u81ea\u5b9a\u4e49\u53c2\u6570\n\n```python\nfrom ctlib_geoip import GeoIPClient\n\nclient = GeoIPClient(\n url=\"https://geoip.example.com/api/{ip}\",\n source=\"ipinfo.io\",\n ttl=86400, # 24\u5c0f\u65f6\n max_retries=5,\n max_wait_time=15,\n headers={\"User-Agent\": \"MyApp/1.0\"}\n)\n\n# \u4f7f\u7528\u9ed8\u8ba4\u53c2\u6570\nresult1 = client.lookup(\"8.8.8.8\")\n\n# \u8986\u76d6\u7279\u5b9a\u53c2\u6570\nresult2 = client.lookup(\"8.8.8.8\", source=\"ip-api.com\")\nresult3 = client.lookup(\"8.8.8.8\", ttl=3600)\n\n# \u4e0d\u643a\u5e26source\u53c2\u6570\uff08\u540e\u7aef\u4e0d\u5904\u7406source\uff09\nresult4 = client.lookup(\"8.8.8.8\", source=None)\n```\n\n## API\u53c2\u8003\n\n### GeoIPClient\n\n\u540c\u6b65\u5ba2\u6237\u7aef\u7c7b\u3002\n\n#### \u53c2\u6570\n\n- `url: str` - GeoIP\u670d\u52a1URL\u6a21\u677f\uff0c\u652f\u6301 `{ip}` \u5360\u4f4d\u7b26\uff0c\u5982 `https://geoip.example.com/api/{ip}`\n- `source: Union[DataSource, str, None] = None` - \u6570\u636e\u6e90\uff0cNone\u8868\u793a\u4e0d\u6307\u5b9a\u6570\u636e\u6e90\n- `ttl: int = 2592000` - \u6570\u636e\u6709\u6548\u671f\uff08\u79d2\uff0c\u9ed8\u8ba430\u5929\uff09\n- `cache_len: int = 256` - \u7f13\u5b58\u6700\u5927\u6761\u6570\n- `max_retries: int = 3` - \u6700\u5927\u91cd\u8bd5\u6b21\u6570\n- `max_wait_time: int = 10` - \u6700\u957f\u7b49\u5f85\u65f6\u95f4\uff08\u79d2\uff09\n- `headers: Dict[str, str] = None` - HTTP\u8bf7\u6c42\u5934\n\n#### \u65b9\u6cd5\n\n- `lookup(ip: Union[str, IPv4Address], source: SourceType = Unset, ttl: TTLType = Unset, **extra) -> Optional[GeoIP]`\n\n### AsyncGeoIPClient\n\n\u5f02\u6b65\u5ba2\u6237\u7aef\u7c7b\uff0c\u53c2\u6570\u548c\u65b9\u6cd5\u4e0e\u540c\u6b65\u5ba2\u6237\u7aef\u76f8\u540c\uff0c\u4f46\u6240\u6709\u64cd\u4f5c\u90fd\u662f\u5f02\u6b65\u7684\u3002\n\n### GeoIP\n\n\u6570\u636e\u6a21\u578b\u7c7b\u3002\n\n#### \u5b57\u6bb5\n\n- `ip: str` - IP\u5730\u5740\n- `country: str` - \u56fd\u5bb6\u4ee3\u7801\n- `region: str` - \u5730\u533a\n- `city: str` - \u57ce\u5e02\n- `updated_at: datetime` - \u6570\u636e\u66f4\u65b0\u65f6\u95f4\n- `source: str` - \u6570\u636e\u6765\u6e90\n\n### GeoInfo\n\n\u5730\u7406\u4f4d\u7f6e\u4fe1\u606f\u6a21\u578b\u7c7b\u3002\n\n#### \u5b57\u6bb5\n\n- `name: Optional[str]` - \u5730\u7406\u4f4d\u7f6e\u540d\u79f0\n- `country: str` - \u56fd\u5bb6\u4ee3\u7801\n- `region: Optional[str]` - \u5730\u533a\u540d\u79f0\n- `city: Optional[str]` - \u57ce\u5e02\u540d\u79f0\n- `detail: Optional[str]` - \u8be6\u7ec6\u63cf\u8ff0\n- `geo_id: Optional[int]` - \u5730\u7406\u4f4d\u7f6eID\n- `geo_code: Optional[str]` - \u5730\u7406\u4f4d\u7f6e\u4ee3\u7801\uff08\u683c\u5f0f\uff1a\u56fd\u5bb6-\u5730\u533a-\u57ce\u5e02\uff09\n\n#### \u7c7b\u65b9\u6cd5\n\n- `from_geo_id(geo_id: int)` - \u6839\u636e\u5730\u7406\u4f4d\u7f6eID\u67e5\u627e\n- `from_geo_code(geo_code: str)` - \u6839\u636e\u5730\u7406\u4f4d\u7f6e\u4ee3\u7801\u67e5\u627e\n- `from_name(name: str)` - \u6839\u636e\u540d\u79f0\u67e5\u627e\n\n### GeoTree\n\n\u5730\u7406\u4f4d\u7f6e\u6811\u7ba1\u7406\u7c7b\uff0c\u7528\u4e8e\u9ad8\u6548\u7684\u5730\u7406\u4f4d\u7f6e\u5339\u914d\u548c\u8bbf\u95ee\u63a7\u5236\u3002\n\n#### \u529f\u80fd\u7279\u6027\n\n- **\u4e09\u5c42\u5d4c\u5957\u7ed3\u6784**: \u56fd\u5bb6(Country) \u2192 \u5730\u533a(Region) \u2192 \u57ce\u5e02(City)\n- **\u9ad8\u6548\u67e5\u8be2**: \u4f7f\u7528\u5b57\u5178\u7ed3\u6784\uff0c\u67e5\u8be2\u65f6\u95f4\u590d\u6742\u5ea6O(1)\n- **\u7075\u6d3b\u5339\u914d**: \u652f\u6301\u4e0d\u540c\u7ea7\u522b\u7684\u6a21\u7cca\u5339\u914d\n- **\u8bbf\u95ee\u63a7\u5236**: \u9002\u7528\u4e8e\u57fa\u4e8e\u5730\u7406\u4f4d\u7f6e\u7684\u6743\u9650\u63a7\u5236\n\n#### \u4e3b\u8981\u65b9\u6cd5\n\n- `add(geo: GeoInfo)` - \u6dfb\u52a0\u5730\u7406\u4f4d\u7f6e\u4fe1\u606f\u5230\u6811\u4e2d\n- `contains(geoip: GeoIP) -> bool` - \u5224\u65adGeoIP\u662f\u5426\u5728\u6811\u4e2d\n\n#### \u4f7f\u7528\u793a\u4f8b\n\n```python\nfrom ctlib_geoip import GeoTree, GeoInfo\n\n# \u521b\u5efa\u5730\u7406\u4f4d\u7f6e\u6811\ngeo_tree = GeoTree([\n GeoInfo(country=\"HK\", region=\"Central and Western\"),\n GeoInfo(country=\"CN\", region=\"Guangdong\", city=\"Shenzhen\")\n])\n\n# \u68c0\u67e5GeoIP\u662f\u5426\u5728\u5141\u8bb8\u7684\u5730\u7406\u4f4d\u7f6e\u8303\u56f4\u5185\ngeoip = GeoIP(ip=\"8.8.8.8\", country=\"HK\", region=\"Central and Western\", city=\"Central\")\nis_allowed = geo_tree.contains(geoip) # True\n```\n\n### Unset\n\n\u7279\u6b8a\u6807\u8bb0\u7c7b\uff0c\u7528\u4e8e\u8868\u793a\u4f7f\u7528\u5ba2\u6237\u7aef\u521b\u5efa\u65f6\u7684\u9ed8\u8ba4\u53c2\u6570\u3002\n\n### \u53c2\u6570\u8bed\u4e49\u8bf4\u660e\n\n- **`Unset`**: \u4f7f\u7528\u5ba2\u6237\u7aef\u521b\u5efa\u65f6\u8bbe\u7f6e\u7684\u9ed8\u8ba4\u503c\n- **`None`**: \u4e0d\u5411\u540e\u7aef\u53d1\u9001\u8be5\u53c2\u6570\n- **\u5177\u4f53\u503c**: \u4f7f\u7528\u6307\u5b9a\u7684\u503c\u8986\u76d6\u9ed8\u8ba4\u503c\n\n### URL\u6a21\u677f\u7cfb\u7edf\n\n\u652f\u6301\u7075\u6d3b\u7684URL\u6a21\u677f\uff0c\u4f8b\u5982\uff1a\n\n```python\n# \u57fa\u672c\u6a21\u677f\nurl = \"https://geoip.example.com/{ip}\"\n\n# \u5e26\u67e5\u8be2\u53c2\u6570\u7684\u6a21\u677f\nurl = \"https://geoip.example.com/api/{ip}?key=value\"\n\n# \u590d\u6742\u6a21\u677f\nurl = \"https://geoip.example.com/v1/geoip/{ip}?format=json&lang=zh\"\n```\n\n\u7cfb\u7edf\u4f1a\u81ea\u52a8\u5904\u7406 `{ip}` \u5360\u4f4d\u7b26\u548c\u67e5\u8be2\u53c2\u6570\u7684\u7ba1\u7406\u3002\n\n## \u6570\u636e\u6e90\n\n\u652f\u6301\u7684\u6570\u636e\u6e90\uff1a\n\n- `ipinfo.io` - IPInfo\u670d\u52a1\n- `ip-api.com` - IP-API\u670d\u52a1\n- `ip.sb` - IP.SB\u670d\u52a1\n- `iplocate.io` - IPLocate\u670d\u52a1\n\n\u4e5f\u652f\u6301\u81ea\u5b9a\u4e49\u6570\u636e\u6e90\u3002\n\n## \u5730\u7406\u4f4d\u7f6e\u6570\u636e\n\nSDK\u5185\u7f6e\u4e86\u4e30\u5bcc\u7684\u5730\u7406\u4f4d\u7f6e\u6570\u636e\uff0c\u652f\u6301\u4ee5\u4e0b\u5730\u533a\uff1a\n\n- **\u4e2d\u56fd (CN)**: \u5305\u542b420\u4e2a\u5730\u7406\u4f4d\u7f6e\u8bb0\u5f55\uff0c\u6db5\u76d6\u6240\u6709\u7701\u4efd\u548c\u4e3b\u8981\u57ce\u5e02\n- **\u9999\u6e2f (HK)**: \u5305\u542b20\u4e2a\u5730\u533a\u8bb0\u5f55\uff0c\u6db5\u76d6\u6240\u6709\u884c\u653f\u533a\n- **\u53f0\u6e7e (TW)**: \u5305\u542b32\u4e2a\u5730\u7406\u4f4d\u7f6e\u8bb0\u5f55\n- **\u6fb3\u95e8 (MO)**: \u5305\u542b10\u4e2a\u5730\u7406\u4f4d\u7f6e\u8bb0\u5f55\n\n\u5730\u7406\u4f4d\u7f6e\u6570\u636e\u4f7f\u7528\u6807\u51c6\u5316\u7684\u683c\u5f0f\uff1a\n- **geo_code\u683c\u5f0f**: `\u56fd\u5bb6-\u5730\u533a-\u57ce\u5e02`\uff0c\u5982 `HK-NCW---`\uff08\u9999\u6e2f-\u4e2d\u897f\u533a\uff09\n- **\u652f\u6301\u67e5\u8be2\u65b9\u5f0f**: \u6309ID\u3001\u4ee3\u7801\u3001\u540d\u79f0\u7b49\u591a\u79cd\u65b9\u5f0f\u67e5\u627e\u5730\u7406\u4f4d\u7f6e\u4fe1\u606f\n\n## \u7f13\u5b58\u7b56\u7565\n\n- \u4f7f\u7528LRU\u7f13\u5b58\n- \u7f13\u5b58\u7ed3\u6784\uff1a`{ip: {source: GeoIP}}`\uff0c\u652f\u6301\u540c\u4e00IP\u7684\u591a\u4e2a\u6570\u636e\u6e90\u7ed3\u679c\n- TTL\u8fc7\u671f\u68c0\u67e5\u5728\u4e1a\u52a1\u5c42\u8fdb\u884c\uff0c\u7f13\u5b58\u7ba1\u7406\u5668\u4e13\u6ce8\u4e8e\u5b58\u50a8\u7ba1\u7406\n- \u667a\u80fd\u7f13\u5b58\u7b56\u7565\uff1a\u4f18\u5148\u8fd4\u56de\u6307\u5b9a\u6570\u636e\u6e90\u7684\u7ed3\u679c\uff0c\u5176\u6b21\u8fd4\u56de\u6700\u65b0\u7ed3\u679c\n\n## \u91cd\u8bd5\u673a\u5236\n\n- \u652f\u6301\u6307\u6570\u9000\u907f\u91cd\u8bd5\n- \u4ece1\u79d2\u5f00\u59cb\u7b49\u5f85\uff0c\u6700\u5927\u7b49\u5f85\u65f6\u95f4\u53ef\u914d\u7f6e\n- \u91cd\u8bd5\u6b21\u6570\u53ef\u914d\u7f6e\n\n## \u65e5\u5fd7\n\n\u4f7f\u7528Python\u6807\u51c6logging\u6a21\u5757\uff1a\n\n- DEBUG\u7ea7\u522b\uff1a\u8bb0\u5f55\u67e5\u8be2\u64cd\u4f5c\n- ERROR\u7ea7\u522b\uff1a\u8bb0\u5f55\u9519\u8bef\u4fe1\u606f\n\n## \u9ad8\u7ea7\u529f\u80fd\n\n### \u5730\u7406\u4f4d\u7f6e\u8bbf\u95ee\u63a7\u5236\n\n\u4f7f\u7528GeoTree\u5b9e\u73b0\u57fa\u4e8e\u5730\u7406\u4f4d\u7f6e\u7684\u8bbf\u95ee\u63a7\u5236\uff1a\n\n```python\nfrom ctlib_geoip import GeoTree, GeoInfo, GeoIP\n\n# \u5b9a\u4e49\u7981\u6b62\u8bbf\u95ee\u7684\u5730\u7406\u4f4d\u7f6e\nblocked_regions = GeoTree([\n GeoInfo(country=\"US\", region=\"Texas\"), # \u7981\u6b62\u7f8e\u56fd\u5fb7\u514b\u8428\u65af\u5dde\n GeoInfo(country=\"US\", region=\"Florida\"), # \u7981\u6b62\u7f8e\u56fd\u4f5b\u7f57\u91cc\u8fbe\u5dde\n GeoInfo(country=\"HK\", region=\"Yau Tsim Mong\"), # \u7981\u6b62\u9999\u6e2f\u6cb9\u5c16\u65fa\u533a\n])\n\ndef check_access(geoip: GeoIP) -> bool:\n \"\"\"\u68c0\u67e5IP\u5730\u5740\u662f\u5426\u88ab\u7981\u6b62\u8bbf\u95ee\"\"\"\n return not blocked_regions.contains(geoip)\n\n# \u4f7f\u7528\u793a\u4f8b\ngeoip = GeoIP(ip=\"1.2.3.4\", country=\"US\", region=\"Texas\", city=\"Houston\")\nif check_access(geoip):\n print(\"\u5141\u8bb8\u8bbf\u95ee\")\nelse:\n print(\"\u62d2\u7edd\u8bbf\u95ee - \u8be5\u5730\u533a\u88ab\u7981\u6b62\u8bbf\u95ee\")\n```\n\n### \u5730\u7406\u4f4d\u7f6e\u6570\u636e\u5206\u6790\n\n\u5229\u7528\u5185\u7f6e\u7684\u5730\u7406\u4f4d\u7f6e\u6570\u636e\u8fdb\u884c\u533a\u57df\u5206\u6790\uff1a\n\n```python\nfrom ctlib_geoip import GeoInfo\n\n# \u67e5\u627e\u7279\u5b9a\u5730\u7406\u4f4d\u7f6e\u4fe1\u606f\nshenzhen = GeoInfo.from_name(\"Shenzhen\")\nprint(f\"\u6df1\u5733: {shenzhen.detail}\")\n\n# \u6839\u636e\u5730\u7406\u4f4d\u7f6e\u4ee3\u7801\u67e5\u627e\nhk_central = GeoInfo.from_geo_code(\"HK-HCW---\")\nprint(f\"\u9999\u6e2f\u4e2d\u897f\u533a: {hk_central.name}\")\n```\n\n## \u8bb8\u53ef\u8bc1\n\nMIT License\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A GeoIP SDK supporting both sync and async operations",
"version": "0.1.1",
"project_urls": null,
"split_keywords": [
"codetech",
" ctlib"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "7e8cb6a2373a8ba9b954d2fca6521a9e942b77b93e156418e61615c953aa5df5",
"md5": "34aca7d690d4a091083316096c38c503",
"sha256": "115bb83e0334d6028cb56e3b5d961e76af1bcc3b8f2d412d4f158764aa412c21"
},
"downloads": -1,
"filename": "ctlib_geoip-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "34aca7d690d4a091083316096c38c503",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 27409,
"upload_time": "2025-08-20T10:39:48",
"upload_time_iso_8601": "2025-08-20T10:39:48.343339Z",
"url": "https://files.pythonhosted.org/packages/7e/8c/b6a2373a8ba9b954d2fca6521a9e942b77b93e156418e61615c953aa5df5/ctlib_geoip-0.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "f4eeec960ef756589d11f946ebc7601bb3dc2b3fb8a5d8ba1c97be027669fda7",
"md5": "31ccd26e873e9aaef8622393dc23592c",
"sha256": "803d3148564cde6d160c9241f5389398171faed7c7d97e92b266ecc9c9e5be58"
},
"downloads": -1,
"filename": "ctlib_geoip-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "31ccd26e873e9aaef8622393dc23592c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 23054,
"upload_time": "2025-08-20T10:39:49",
"upload_time_iso_8601": "2025-08-20T10:39:49.565168Z",
"url": "https://files.pythonhosted.org/packages/f4/ee/ec960ef756589d11f946ebc7601bb3dc2b3fb8a5d8ba1c97be027669fda7/ctlib_geoip-0.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-20 10:39:49",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "ctlib-geoip"
}