72 lines
2.4 KiB
Python
72 lines
2.4 KiB
Python
|
#!/usr/bin/python
|
|||
|
# -*- coding: utf-8 -*-
|
|||
|
# @version : 1.0
|
|||
|
# @Create Time : 2022/11/3 17:23
|
|||
|
# @File : ip_manage.py
|
|||
|
# @IDE : PyCharm
|
|||
|
# @desc : 获取IP地址归属地
|
|||
|
|
|||
|
"""
|
|||
|
文档:https://user.ip138.com/ip/doc
|
|||
|
IP查询第三方服务,有1000次的免费次数
|
|||
|
|
|||
|
JSONP请求示例(IPv4)
|
|||
|
https://api.ip138.com/ip/?ip=58.16.180.3&datatype=jsonp&token=cc87f3c77747bccbaaee35006da1ebb65e0bad57
|
|||
|
|
|||
|
aiohttp 异步请求文档:https://docs.aiohttp.org/en/stable/client_quickstart.html
|
|||
|
"""
|
|||
|
from aiohttp import TCPConnector
|
|||
|
|
|||
|
from application.settings import IP_PARSE_TOKEN, IP_PARSE_ENABLE
|
|||
|
import aiohttp
|
|||
|
from core.logger import logger
|
|||
|
from pydantic import BaseModel
|
|||
|
from typing import Optional
|
|||
|
|
|||
|
|
|||
|
class IPLocationOut(BaseModel):
|
|||
|
ip: str | None = None
|
|||
|
address: str | None = None
|
|||
|
country: str | None = None
|
|||
|
province: str | None = None
|
|||
|
city: str | None = None
|
|||
|
county: str | None = None
|
|||
|
operator: str | None = None
|
|||
|
postal_code: str | None = None
|
|||
|
area_code: str | None = None
|
|||
|
|
|||
|
|
|||
|
class IPManage:
|
|||
|
|
|||
|
def __init__(self, ip: str):
|
|||
|
self.ip = ip
|
|||
|
self.url = f"https://api.ip138.com/ip/?ip={ip}&datatype=jsonp&token={IP_PARSE_TOKEN}"
|
|||
|
|
|||
|
async def parse(self):
|
|||
|
"""
|
|||
|
IP 数据解析
|
|||
|
|
|||
|
接口返回:{'ret': 'ok', 'ip': '114.222.121.253','data': ['中国', '江苏', '南京', '江宁区', '电信', '211100', '025']}
|
|||
|
"""
|
|||
|
out = IPLocationOut()
|
|||
|
out.ip = self.ip
|
|||
|
if not IP_PARSE_ENABLE:
|
|||
|
logger.warning("未开启IP地址数据解析,无法获取到IP所属地,请在application/config/production.py:IP_PARSE_ENABLE中开启!")
|
|||
|
return out
|
|||
|
async with aiohttp.ClientSession(connector=TCPConnector(ssl=False)) as session:
|
|||
|
async with session.get(self.url) as resp:
|
|||
|
body = await resp.json()
|
|||
|
if body.get("ret") != 'ok':
|
|||
|
logger.error(f"获取IP所属地失败:{body}")
|
|||
|
return out
|
|||
|
data = body.get("data")
|
|||
|
out.address = f"{''.join(data[i] for i in range(0, 4))} {data[4]}"
|
|||
|
out.country = data[0]
|
|||
|
out.province = data[1]
|
|||
|
out.city = data[2]
|
|||
|
out.county = data[3]
|
|||
|
out.operator = data[4]
|
|||
|
out.postal_code = data[5]
|
|||
|
out.area_code = data[6]
|
|||
|
return out
|