from flask import Flask, request, render_template_string
import requests
app = Flask(__name__)
INDEX_HTML = """
入力フォーム
⇂名前を入力
"""
MAP_HTML = """
現在地マップ
"""
##########################################
# 汎用リクエスト関数: CORS/エラー対策
##########################################
CORS_PROXY = "https://cors.isomorphic-git.org/"
def safe_request_json(url, timeout=2, use_proxy_on_fail=True):
"""
安全に GET JSON を取得する。
失敗時は CORS プロキシで再試行する。
"""
try:
res = requests.get(url, timeout=timeout)
if res.status_code == 200:
return res.json()
else:
raise Exception(f"HTTP {res.status_code}")
except Exception:
if use_proxy_on_fail:
try:
proxy_url = CORS_PROXY + url
res = requests.get(proxy_url, timeout=timeout)
if res.status_code == 200:
return res.json()
except Exception:
pass
return None
##########################################
# 既存 API(エラーハンドリング強化 + CORS fallback)
##########################################
def get_geo_ipapi(ip):
url = f"http://ip-api.com/json/{ip}?lang=ja"
res = safe_request_json(url)
if res and res.get("status") == "success":
return {
"prefecture": res.get("regionName", ""),
"city": res.get("city", ""),
"lat": res.get("lat"),
"lon": res.get("lon")
}
return fallback()
def get_geo_ipwho(ip):
url = f"https://api.ipwho.org/ip/{ip}?format=json"
res = safe_request_json(url)
if res and res.get("success") is True:
data = res.get("data", {})
return {
"prefecture": data.get("region", ""),
"city": data.get("city", ""),
"lat": data.get("latitude"),
"lon": data.get("longitude"),
"capital": data.get("capital", "")
}
return fallback(capital="")
##########################################
# 新規追加 API(エラーハンドリング統一)
##########################################
def get_geo_reallyfreegeoip(ip):
url = f"https://reallyfreegeoip.org/json/{ip}"
res = safe_request_json(url)
if res:
return {
"prefecture": res.get("region_name", ""),
"city": res.get("city", ""),
"lat": res.get("latitude"),
"lon": res.get("longitude")
}
return fallback()
def get_geo_ipapico(ip):
url = f"https://ipapi.co/{ip}/json/"
res = safe_request_json(url)
if res:
return {
"prefecture": res.get("region_name", res.get("region", "")),
"city": res.get("city", ""),
"lat": res.get("latitude"),
"lon": res.get("longitude")
}
return fallback()
def get_geo_iplocalize(ip):
url = f"https://iplocalize.com/api/v1/lookup/{ip}"
res = safe_request_json(url)
if res:
return {
"prefecture": res.get("region", ""),
"city": res.get("city", ""),
"lat": res.get("latitude"),
"lon": res.get("longitude")
}
return fallback()
##########################################
# Fallback 共通
##########################################
def fallback(capital=None):
base = {
"prefecture": "",
"city": "",
"lat": 35.681236,
"lon": 139.767125
}
if capital is not None:
base["capital"] = capital
return base
##########################################
# Flask Routes
##########################################
@app.route("/", methods=["GET"])
def index():
return render_template_string(INDEX_HTML)
@app.route("/next", methods=["POST"])
def next_page():
name = request.form.get("name", "").strip()
mode = request.form.get("send_mode")
xff = request.headers.get("X-Forwarded-For")
if xff:
ip = xff.split(",")[0].strip() # 先頭のクライアント IP を使う
else:
ip = request.remote_addr
print(ip)
# 各 API を使用
api1 = get_geo_ipapi(ip)
api2 = get_geo_ipwho(ip)
api3 = get_geo_reallyfreegeoip(ip)
api5 = get_geo_ipapico(ip)
api6 = get_geo_iplocalize(ip)
# マスク処理
def mask(mode, prefecture, city):
if mode == "all":
return prefecture, city
elif mode == "pref_only":
return prefecture, ""
else:
return "", ""
apis = [api1, api2, api3, api5, api6]
names = ["ip-api", "IPWho", "ReallyFreeGeoIP", "ipapi.co", "iplocalize"]
for api, name_api in zip(apis, names):
pref, city = mask(mode, api.get("prefecture", ""), api.get("city", ""))
print(f"[{name_api}] 名前:{name} {pref} {city}")
# 地図表示は ip-api を優先
return render_template_string(
MAP_HTML,
lat=api1["lat"],
lon=api1["lon"],
prefecture=api1["prefecture"],
city=api1["city"]
)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=7860)