一个后端代码
-
这个代码有以下目的
-
利用一些平台为新用户提供的免费token额度,支持用户自发获取平台的免费token并共享到后端
-
后端实时更新可用token并且弃用额度耗尽token
-
减少API的调用量,设置对短时间内相同的请求调用之前的响应内容
-
总的来说,目的很单纯,就是白嫖
GPT完成了日志输出的补充
代码实现
from flask import Flask, jsonify, request
from datetime import datetime
import requests
import time
import logging
app = Flask(__name__)
API_URL = "https://api.caiyunapp.com/v2.6/{}/{}/realtime"
# 配置日志记录
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger()
# 从文件中读取API tokens
try:
with open("tokens.txt", 'r') as f:
tokens = [i.strip() for i in f.readlines()]
except Exception as e:
logger.error("Error reading tokens: %s", e)
tokens = []
# 历史天气获取数据,如果有请求对于同一个position在5min内提出相同的请求,那么直接返回历史数据
# 格式为 {position : {time:,info:}}
history = {}
# 天气条件的映射
weather_conditions = {
"CLEAR_NIGHT": "晴(夜间)",
"PARTLY_CLOUDY_DAY": "多云(白天)",
"PARTLY_CLOUDY_NIGHT": "多云(夜间)",
"CLOUDY": "阴",
"LIGHT_HAZE": "轻度雾霾",
"MODERATE_HAZE": "中度雾霾",
"HEAVY_HAZE": "重度雾霾",
"LIGHT_RAIN": "小雨",
"MODERATE_RAIN": "中雨",
"HEAVY_RAIN": "大雨",
"STORM_RAIN": "暴雨",
"FOG": "雾",
"LIGHT_SNOW": "小雪",
"MODERATE_SNOW": "中雪",
"HEAVY_SNOW": "大雪",
"STORM_SNOW": "暴雪",
"DUST": "浮尘",
"SAND": "沙尘",
"WIND": "大风"
}
def fetch_weather_data(token: str, position: str):
"""Fetch weather data from the API."""
try:
logger.debug("Fetching weather data for position: %s using token: %s", position, token)
response = requests.get(API_URL.format(token, position))
response.raise_for_status()
data = response.json()
if data.get("status") != "ok":
logger.warning("API returned status 'no' for position: %s", position)
return {"status": "no"}
realtime = data.get("result", {}).get("realtime", {})
temperature = realtime.get("temperature")
wind_speed = realtime.get("wind", {}).get("speed")
skycon = realtime.get("skycon")
weather_condition = determine_weather_condition(skycon)
logger.info("Weather data fetched successfully for %s: Temperature: %s, Wind Speed: %s, Condition: %s",
position, temperature, wind_speed, weather_condition)
return {
"status": 'ok',
"temperature": temperature,
"wind": wind_speed,
"condition": weather_condition
}
except requests.exceptions.RequestException as e:
logger.error("Request error for token %s: %s", token, e)
return {"error": str(e)}
except Exception as e:
logger.error("Error processing weather data: %s", e)
return {"error": "An error occurred while processing the weather data."}
def determine_weather_condition(skycon):
"""Determine the weather condition from the skycon."""
condition = weather_conditions.get(skycon, "未知天气")
logger.debug("Determined weather condition for skycon %s: %s", skycon, condition)
return condition
@app.route('/weather', methods=['GET'])
def get_weather():
position = request.args.get('position')
if not position:
logger.error("No position parameter provided in request.")
return jsonify({"error": "Position parameter is required."}), 400
timestamp = time.time()
if position in history and (timestamp - history[position]['time'] <= 300):
logger.info("Returning cached weather data for position: %s", position)
return jsonify(history[position]['info'])
if not tokens:
logger.error("No available tokens to make a request.")
return jsonify({"error": "No available tokens."}), 500
to_remove_token = []
for token in tokens:
logger.info("Using token: %s at %s", token, datetime.now())
info = fetch_weather_data(token, position)
if 'error' in info:
logger.warning("Failed with token %s: %s", token, info['error'])
with open("stale_token.txt", 'a') as f:
f.write(token + "\n")
to_remove_token.append(token)
continue
if info['status'] == "no":
logger.warning("API call unsuccessful for token: %s", token)
to_remove_token.append(token)
continue
logger.info("Successful response received.")
history[position] = {
"time": time.time(),
"info": info
}
return jsonify(info)
for token in to_remove_token:
tokens.remove(token)
logger.info("Removing stale token: %s", token)
logger.error("All tokens failed for position: %s", position)
return jsonify({"error": "All tokens failed."}), 500
if __name__ == '__main__':
app.run(debug=True)