drfy commited on
Commit
1c9ef0c
·
verified ·
1 Parent(s): 6960dd7

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +149 -58
main.py CHANGED
@@ -8,26 +8,36 @@ import sys
8
  import os
9
  from logging.handlers import RotatingFileHandler
10
 
 
11
  LOG_FILE = os.path.join('/code', 'ip_query.log')
12
 
 
13
  try:
 
14
  formatter = logging.Formatter('%(message)s')
 
 
15
  log_handler = RotatingFileHandler(
16
  LOG_FILE,
17
- maxBytes=10*1024*1024,
18
  backupCount=5,
19
  encoding='utf-8'
20
  )
21
  log_handler.setFormatter(formatter)
 
 
22
  logger = logging.getLogger('ip_query')
23
  logger.setLevel(logging.INFO)
24
  logger.addHandler(log_handler)
 
 
25
  startup_log = {
26
  "时间": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
27
  "事件": "系统启动",
28
  "状态": "成功"
29
  }
30
  logger.info(json.dumps(startup_log, ensure_ascii=False))
 
31
  except Exception as e:
32
  print(f"日志初始化失败: {e}")
33
  sys.exit(1)
@@ -35,42 +45,67 @@ except Exception as e:
35
  city_reader = maxminddb.open_database('GeoLite2-City.mmdb')
36
  asn_reader = maxminddb.open_database('GeoLite2-ASN.mmdb')
37
  cn_reader = maxminddb.open_database('GeoCN.mmdb')
38
- lang = ["zh-CN", "en"]
39
  asn_map = {
40
- 9812: "东方有线",
41
- 9389: "中国长城",
42
- 17962: "天威视讯",
43
- 17429: "歌华有线",
44
- 7497: "科技网",
45
- 24139: "华数",
46
- 9801: "中关村",
47
- 4538: "教育网",
48
- 24151: "CNNIC",
49
- 38019: "中国移动", 139080: "中国移动", 9808: "中国移动", 24400: "中国移动", 134810: "中国移动", 24547: "中国移动",
50
- 56040: "中国移动", 56041: "中国移动", 56042: "中国移动", 56044: "中国移动", 132525: "中国移动", 56046: "中国移动",
51
- 56047: "中国移动", 56048: "中国移动", 59257: "中国移动", 24444: "中国移动",
52
- 24445: "中国移动", 137872: "中国移动", 9231: "中国移动", 58453: "中国移动",
53
- 4134: "中国电信", 4812: "中国电信", 23724: "中国电信", 136188: "中国电信", 137693: "中国电信", 17638: "中国电信",
54
- 140553: "中国电信", 4847: "中国电信", 140061: "中国电信", 136195: "中国电信", 17799: "中国电信", 139018: "中国电信",
55
- 134764: "中国电信", 4837: "中国联通", 4808: "中国联通", 134542: "中国联通", 134543: "中国联通",
56
- 59019: "金山云",
57
- 135377: "优刻云",
58
- 45062: "网易云",
59
- 37963: "阿里云", 45102: "阿里云国际",
60
- 45090: "腾讯云", 132203: "腾讯云国际",
61
- 55967: "百度云", 38365: "百度云",
62
- 58519: "华为云", 55990: "华为云", 136907: "华为云",
63
- 4609: "澳門電訊",
64
- 13335: "Cloudflare",
65
- 55960: "亚马逊云", 14618: "亚马逊云", 16509: "亚马逊云",
66
- 15169: "谷歌云", 396982: "谷歌云", 36492: "谷歌云",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
68
 
69
  def get_as_info(number):
70
  r = asn_map.get(number)
71
  if r:
72
  return r
73
-
74
  def get_des(d):
75
  for i in lang:
76
  if i in d['names']:
@@ -84,14 +119,14 @@ def get_country(d):
84
  return r
85
 
86
  def province_match(s):
87
- arr = ['内蒙古', '黑龙江', '河北', '山西', '吉林', '辽宁', '江苏', '浙江', '安徽', '福建', '江西', '山东', '河南', '湖北', '湖南', '广东', '海南', '四川', '贵州', '云南', '陕西', '甘肃', '青海', '广西', '西藏', '宁夏', '新疆', '北京', '天津', '上海', '重庆']
88
  for i in arr:
89
  if i in s:
90
  return i
91
  return ''
92
 
93
  def de_duplicate(regions):
94
- regions = filter(bool, regions)
95
  ret = []
96
  [ret.append(i) for i in regions if i not in ret]
97
  return ret
@@ -100,12 +135,11 @@ def get_addr(ip, mask):
100
  network = ipaddress.ip_network(f"{ip}/{mask}", strict=False)
101
  first_ip = network.network_address
102
  return f"{first_ip}/{mask}"
103
-
104
  def get_maxmind(ip: str):
105
- ret = {"ip": ip}
106
  asn_info = asn_reader.get(ip)
107
  if asn_info:
108
- as_ = {"number": asn_info["autonomous_system_number"], "name": asn_info["autonomous_system_organization"]}
109
  info = get_as_info(as_["number"])
110
  if info:
111
  as_["info"] = info
@@ -115,45 +149,78 @@ def get_maxmind(ip: str):
115
  ret["addr"] = get_addr(ip, prefix)
116
  if not city_info:
117
  return ret
118
-
 
119
  if "location" in city_info:
120
  location = city_info["location"]
121
- ret["location"] = {
122
- "latitude": location.get("latitude"),
123
- "longitude": location.get("longitude")
124
- }
125
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  if "country" in city_info:
127
  country_code = city_info["country"]["iso_code"]
128
  country_name = get_country(city_info["country"])
129
- ret["country"] = {"code": country_code, "name": country_name}
130
-
131
  if "registered_country" in city_info:
132
  registered_country_code = city_info["registered_country"]["iso_code"]
133
- ret["registered_country"] = {"code": registered_country_code, "name": get_country(city_info["registered_country"])}
134
-
135
  regions = [get_des(i) for i in city_info.get('subdivisions', [])]
136
 
137
  if "city" in city_info:
138
  c = get_des(city_info["city"])
139
- if (not regions or c not in regions[-1]) and c not in country_name:
140
  regions.append(c)
141
-
142
  regions = de_duplicate(regions)
143
  if regions:
144
  ret["regions"] = regions
145
-
146
  return ret
147
 
148
- def get_cn(ip: str, info={}):
149
  ret, prefix = cn_reader.get_with_prefix_len(ip)
150
  if not ret:
151
  return
152
  info["addr"] = get_addr(ip, prefix)
153
- regions = de_duplicate([ret["province"], ret["city"], ret["districts"]])
154
  if regions:
155
  info["regions"] = regions
156
- info["regions_short"] = de_duplicate([province_match(ret["province"]), ret["city"].replace('市', ''), ret["districts"]])
157
  if "as" not in info:
158
  info["as"] = {}
159
  info["as"]["info"] = ret['isp']
@@ -164,7 +231,7 @@ def get_cn(ip: str, info={}):
164
  def get_ip_info(ip):
165
  info = get_maxmind(ip)
166
  if "country" in info and info["country"]["code"] == "CN" and ("registered_country" not in info or info["registered_country"]["code"] == "CN"):
167
- get_cn(ip, info)
168
  return info
169
 
170
  def query():
@@ -172,25 +239,33 @@ def query():
172
  try:
173
  ip = input('IP: \t').strip()
174
  info = get_ip_info(ip)
 
175
  print(f"网段:\t{info['addr']}")
 
 
176
  if "location" in info:
177
  print(f"经纬度:\t{info['location']['latitude']}, {info['location']['longitude']}")
 
178
  if "as" in info:
179
- print(f"ISP:\t", end=' ')
180
  if "info" in info["as"]:
181
- print(info["as"]["info"], end=' ')
182
  else:
183
- print(info["as"]["name"], end=' ')
184
  if "type" in info:
185
- print(f"({info['type']})", end=' ')
186
- print(f"ASN{info['as']['number']}", end=' ')
187
  print(info['as']["name"])
 
188
  if "registered_country" in info and ("country" not in info or info["country"]["code"] != info["registered_country"]["code"]):
189
  print(f"注册地:\t{info['registered_country']['name']}")
 
190
  if "country" in info:
191
  print(f"使用地:\t{info['country']['name']}")
 
192
  if "regions" in info:
193
  print(f"位置: \t{' '.join(info['regions'])}")
 
194
  except Exception as e:
195
  print(e)
196
  raise e
@@ -201,9 +276,14 @@ app = FastAPI()
201
 
202
  @app.get("/")
203
  async def api(request: Request, ip: str = None):
 
204
  client_ip = request.headers.get("x-forwarded-for") or request.headers.get("x-real-ip") or request.client.host
205
  query_ip = ip.strip() if ip else client_ip
 
 
206
  result = get_ip_info(query_ip)
 
 
207
  log_data = {
208
  "时间": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
209
  "访问IP": client_ip,
@@ -211,13 +291,21 @@ async def api(request: Request, ip: str = None):
211
  "请求头": dict(request.headers),
212
  "查询结果": result
213
  }
 
 
214
  logger.info(json.dumps(log_data, ensure_ascii=False))
 
215
  return result
216
 
217
  @app.get("/{ip}")
218
  async def path_api(request: Request, ip: str):
 
219
  client_ip = request.headers.get("x-forwarded-for") or request.headers.get("x-real-ip") or request.client.host
 
 
220
  result = get_ip_info(ip)
 
 
221
  log_data = {
222
  "时间": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
223
  "访问IP": client_ip,
@@ -225,10 +313,13 @@ async def path_api(request: Request, ip: str):
225
  "请求头": dict(request.headers),
226
  "查询结果": result
227
  }
 
 
228
  logger.info(json.dumps(log_data, ensure_ascii=False))
 
229
  return result
230
 
231
  if __name__ == '__main__':
232
  query()
233
  import uvicorn
234
- uvicorn.run(app, host="0.0.0.0", port=8080, server_header=False, proxy_headers=True)
 
8
  import os
9
  from logging.handlers import RotatingFileHandler
10
 
11
+ # 定义日志文件路径
12
  LOG_FILE = os.path.join('/code', 'ip_query.log')
13
 
14
+ # 配置日志
15
  try:
16
+ # 创建格式化器
17
  formatter = logging.Formatter('%(message)s')
18
+
19
+ # 配置处理器
20
  log_handler = RotatingFileHandler(
21
  LOG_FILE,
22
+ maxBytes=10*1024*1024, # 10MB
23
  backupCount=5,
24
  encoding='utf-8'
25
  )
26
  log_handler.setFormatter(formatter)
27
+
28
+ # 获取logger
29
  logger = logging.getLogger('ip_query')
30
  logger.setLevel(logging.INFO)
31
  logger.addHandler(log_handler)
32
+
33
+ # 记录启动日志
34
  startup_log = {
35
  "时间": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
36
  "事件": "系统启动",
37
  "状态": "成功"
38
  }
39
  logger.info(json.dumps(startup_log, ensure_ascii=False))
40
+
41
  except Exception as e:
42
  print(f"日志初始化失败: {e}")
43
  sys.exit(1)
 
45
  city_reader = maxminddb.open_database('GeoLite2-City.mmdb')
46
  asn_reader = maxminddb.open_database('GeoLite2-ASN.mmdb')
47
  cn_reader = maxminddb.open_database('GeoCN.mmdb')
48
+ lang = ["zh-CN","en"]
49
  asn_map = {
50
+ 9812:"东方有线",
51
+ 9389:"中国长城",
52
+ 17962:"天威视讯",
53
+ 17429:"歌华有线",
54
+ 7497:"科技网",
55
+ 24139:"华数",
56
+ 9801:"中关村",
57
+ 4538:"教育网",
58
+ 24151:"CNNIC",
59
+
60
+ 38019:"中国移动",139080:"中国移动",9808:"中国移动",24400:"中国移动",134810:"中国移动",24547:"中国移动",
61
+ 56040:"中国移动",56041:"中国移动",56042:"中国移动",56044:"中国移动",132525:"中国移动",56046:"中国移动",
62
+ 56047:"中国移动",56048:"中国移动",59257:"中国移动",24444:"中国移动",
63
+ 24445:"中国移动",137872:"中国移动",9231:"中国移动",58453:"中国移动",
64
+
65
+ 4134:"中国电信",4812:"中国电信",23724:"中国电信",136188:"中国电信",137693:"中国电信",17638:"中国电信",
66
+ 140553:"中国电信",4847:"中国电信",140061:"中国电信",136195:"中国电信",17799:"中国电信",139018:"中国电信",
67
+ 133776:"中国电信",58772:"中国电信",146966:"中国电信",63527:"中国电信",58539:"中国电信",58540:"中国电信",
68
+ 141998:"中国电信",138169:"中国电信",139203:"中国电信",58563:"中电信",137690:"中国电信",63838:"中国电信",
69
+ 137694:"中国电信",137698:"中国电信",136167:"中国电信",148969:"中国电信",134764:"中国电信",
70
+ 134770:"中国电信",148981:"中国电信",134774:"中国电信",136190:"中国电信",140647:"中国电信",
71
+ 132225:"中国电信",140485:"中国电信",4811:"中国电信",131285:"中国电信",137689:"中国电信",
72
+ 137692:"中国电信",140636:"中国电信",140638:"中国电信",140345:"中国电信",38283:"中国电信",
73
+ 140292:"中国电信",140903:"中国电信",17897:"中国电信",134762:"中国电信",139019:"中国电信",
74
+ 141739:"中国电信",141771:"中国电信",134419:"中国电信",140276:"中国电信",58542:"中国电信",
75
+ 140278:"中国电信",139767:"中国电信",137688:"中国电信",137691:"中国电信",4809:"中国电信",
76
+ 58466:"中国电信",137687:"中国电信",134756:"中国电信",134760:"中国电信",
77
+ 133774:"中国电信",133775:"中国电信",4816:"中国电信",134768:"中国电信",
78
+ 58461:"中国电信",58519:"��国电信",58520:"中国电信",131325:"中国电信",
79
+
80
+ 4837:"中国联通",4808:"中国联通",134542:"中国联通",134543:"中国联通",10099:"中国联通",
81
+ 140979:"中国联通",138421:"中国联通",17621:"中国联通",17622:"中国联通",17816:"中国联通",
82
+ 140726:"中国联通",17623:"中国联通",136958:"中国联通",9929:"中国联通",58519:"中国联通",
83
+ 140716:"中国联通",4847:"中国联通",136959:"中国联通",135061:"中国联通",139007:"中国联通",
84
+
85
+ 59019:"金山云",
86
+ 135377:"优刻云",
87
+ 45062:"网易云",
88
+ 137718:"火山引擎",
89
+ 37963:"阿里云",45102:"阿里云国际",
90
+ 45090:"腾讯云",132203:"腾讯云国际",
91
+ 55967:"百度云",38365:"百度云",
92
+ 58519:"华为云", 55990:"华为云",136907:"华为云",
93
+ 4609:"澳門電訊",
94
+ 134773:"珠江宽频",
95
+ 1659:"台湾教育网",
96
+ 8075:"微软云",
97
+ 17421:"中华电信",
98
+ 3462:"HiNet",
99
+ 13335:"Cloudflare",
100
+ 55960:"亚马逊云",14618:"亚马逊云",16509:"亚马逊云",
101
+ 15169:"谷歌云",396982:"谷歌云",36492:"谷歌云",
102
  }
103
 
104
  def get_as_info(number):
105
  r = asn_map.get(number)
106
  if r:
107
  return r
108
+
109
  def get_des(d):
110
  for i in lang:
111
  if i in d['names']:
 
119
  return r
120
 
121
  def province_match(s):
122
+ arr=['内蒙古','黑龙江','河北','山西','吉林','辽宁','江苏','浙江','安徽','福建','江西','山东','河南','湖北','湖南','广东','海南','四川','贵州','云南','陕西','甘肃','青海','广西','西藏','宁夏','新疆','北京','天津','上海','重庆']
123
  for i in arr:
124
  if i in s:
125
  return i
126
  return ''
127
 
128
  def de_duplicate(regions):
129
+ regions = filter(bool,regions)
130
  ret = []
131
  [ret.append(i) for i in regions if i not in ret]
132
  return ret
 
135
  network = ipaddress.ip_network(f"{ip}/{mask}", strict=False)
136
  first_ip = network.network_address
137
  return f"{first_ip}/{mask}"
 
138
  def get_maxmind(ip: str):
139
+ ret = {"ip":ip}
140
  asn_info = asn_reader.get(ip)
141
  if asn_info:
142
+ as_ = {"number":asn_info["autonomous_system_number"],"name":asn_info["autonomous_system_organization"]}
143
  info = get_as_info(as_["number"])
144
  if info:
145
  as_["info"] = info
 
149
  ret["addr"] = get_addr(ip, prefix)
150
  if not city_info:
151
  return ret
152
+
153
+ # 添加经纬度和时区信息
154
  if "location" in city_info:
155
  location = city_info["location"]
156
+ loc_data = {}
157
+ if "latitude" in location:
158
+ loc_data["latitude"] = location["latitude"]
159
+ if "longitude" in location:
160
+ loc_data["longitude"] = location["longitude"]
161
+ if "time_zone" in location:
162
+ loc_data["timezone"] = location["time_zone"]
163
+ if loc_data:
164
+ ret["location"] = loc_data
165
+
166
+ # 添加大洲信息
167
+ if "continent" in city_info and city_info["continent"]:
168
+ try:
169
+ ret["continent"] = {
170
+ "code": city_info["continent"].get("code"),
171
+ "name": get_des(city_info["continent"]) if "names" in city_info["continent"] else None
172
+ }
173
+ except Exception:
174
+ pass
175
+
176
+ # 添加邮政编码
177
+ if "postal" in city_info and city_info["postal"]:
178
+ postal_code = city_info["postal"].get("code")
179
+ if postal_code:
180
+ ret["postal"] = postal_code
181
+
182
+ # 添加网络特征
183
+ if "traits" in city_info and city_info["traits"]:
184
+ traits = city_info["traits"]
185
+ traits_data = {}
186
+ if "is_anonymous_proxy" in traits:
187
+ traits_data["is_anonymous_proxy"] = traits["is_anonymous_proxy"]
188
+ if "is_satellite_provider" in traits:
189
+ traits_data["is_satellite_provider"] = traits["is_satellite_provider"]
190
+ if traits_data:
191
+ ret["traits"] = traits_data
192
+
193
  if "country" in city_info:
194
  country_code = city_info["country"]["iso_code"]
195
  country_name = get_country(city_info["country"])
196
+ ret["country"] = {"code":country_code,"name":country_name}
197
+
198
  if "registered_country" in city_info:
199
  registered_country_code = city_info["registered_country"]["iso_code"]
200
+ ret["registered_country"] = {"code":registered_country_code,"name":get_country(city_info["registered_country"])}
201
+
202
  regions = [get_des(i) for i in city_info.get('subdivisions', [])]
203
 
204
  if "city" in city_info:
205
  c = get_des(city_info["city"])
206
+ if (not regions or c not in regions[-1])and c not in country_name:
207
  regions.append(c)
208
+
209
  regions = de_duplicate(regions)
210
  if regions:
211
  ret["regions"] = regions
212
+
213
  return ret
214
 
215
+ def get_cn(ip:str, info={}):
216
  ret, prefix = cn_reader.get_with_prefix_len(ip)
217
  if not ret:
218
  return
219
  info["addr"] = get_addr(ip, prefix)
220
+ regions = de_duplicate([ret["province"],ret["city"],ret["districts"]])
221
  if regions:
222
  info["regions"] = regions
223
+ info["regions_short"] = de_duplicate([province_match(ret["province"]),ret["city"].replace('市',''),ret["districts"]])
224
  if "as" not in info:
225
  info["as"] = {}
226
  info["as"]["info"] = ret['isp']
 
231
  def get_ip_info(ip):
232
  info = get_maxmind(ip)
233
  if "country" in info and info["country"]["code"] == "CN" and ("registered_country" not in info or info["registered_country"]["code"] == "CN"):
234
+ get_cn(ip,info)
235
  return info
236
 
237
  def query():
 
239
  try:
240
  ip = input('IP: \t').strip()
241
  info = get_ip_info(ip)
242
+
243
  print(f"网段:\t{info['addr']}")
244
+
245
+ # 添加经纬度显示
246
  if "location" in info:
247
  print(f"经纬度:\t{info['location']['latitude']}, {info['location']['longitude']}")
248
+
249
  if "as" in info:
250
+ print(f"ISP:\t",end=' ')
251
  if "info" in info["as"]:
252
+ print(info["as"]["info"],end=' ')
253
  else:
254
+ print(info["as"]["name"],end=' ')
255
  if "type" in info:
256
+ print(f"({info['type']})",end=' ')
257
+ print(f"ASN{info['as']['number']}",end=' ')
258
  print(info['as']["name"])
259
+
260
  if "registered_country" in info and ("country" not in info or info["country"]["code"] != info["registered_country"]["code"]):
261
  print(f"注册地:\t{info['registered_country']['name']}")
262
+
263
  if "country" in info:
264
  print(f"使用地:\t{info['country']['name']}")
265
+
266
  if "regions" in info:
267
  print(f"位置: \t{' '.join(info['regions'])}")
268
+
269
  except Exception as e:
270
  print(e)
271
  raise e
 
276
 
277
  @app.get("/")
278
  async def api(request: Request, ip: str = None):
279
+ # 获取请求信息
280
  client_ip = request.headers.get("x-forwarded-for") or request.headers.get("x-real-ip") or request.client.host
281
  query_ip = ip.strip() if ip else client_ip
282
+
283
+ # 获取IP信息
284
  result = get_ip_info(query_ip)
285
+
286
+ # 构建日志信息
287
  log_data = {
288
  "时间": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
289
  "访问IP": client_ip,
 
291
  "请求头": dict(request.headers),
292
  "查询结果": result
293
  }
294
+
295
+ # 使用logger.info而不是logging.info
296
  logger.info(json.dumps(log_data, ensure_ascii=False))
297
+
298
  return result
299
 
300
  @app.get("/{ip}")
301
  async def path_api(request: Request, ip: str):
302
+ # 获取请求信息
303
  client_ip = request.headers.get("x-forwarded-for") or request.headers.get("x-real-ip") or request.client.host
304
+
305
+ # 获取IP信息
306
  result = get_ip_info(ip)
307
+
308
+ # 构建日志信息
309
  log_data = {
310
  "时间": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
311
  "访问IP": client_ip,
 
313
  "请求头": dict(request.headers),
314
  "查询结果": result
315
  }
316
+
317
+ # 使用logger.info而不是logging.info
318
  logger.info(json.dumps(log_data, ensure_ascii=False))
319
+
320
  return result
321
 
322
  if __name__ == '__main__':
323
  query()
324
  import uvicorn
325
+ uvicorn.run(app, host="0.0.0.0", port=8080, server_header=False, proxy_headers=True)