오류 수정

This commit is contained in:
2025-12-22 17:41:31 +09:00
parent 91cd2ad7b2
commit 58cff598a7
3 changed files with 165 additions and 22 deletions

View File

@ -2,6 +2,7 @@ import os
import requests import requests
import json import json
import re import re
import importlib.util
from flask import Flask, request, jsonify, send_from_directory, make_response from flask import Flask, request, jsonify, send_from_directory, make_response
import sqlite3 import sqlite3
from datetime import datetime, timedelta from datetime import datetime, timedelta
@ -71,6 +72,126 @@ def get_captured_rainfall(date):
logger.error(f"캡처 강수량 조회 실패: {e}") logger.error(f"캡처 강수량 조회 실패: {e}")
return [], 0.0, None return [], 0.0, None
def generate_weather_data(date):
"""
날씨 데이터가 없을 때 Selenium으로 데이터 추출하여 SQLite에만 저장
(캡처 이미지 저장, FTP 업로드, 게시글 등록은 하지 않음)
Args:
date: 'YYYYMMDD' 형식
Returns:
bool: 성공 여부
"""
try:
logger.info(f"날씨 데이터 추출 시작 ({date})...")
# weather_capture 모듈에서 필요한 함수들을 동적으로 임포트
import importlib.util
spec = importlib.util.spec_from_file_location(
"weather_capture",
"/app/weather_capture.py"
)
weather_capture = importlib.util.module_from_spec(spec)
spec.loader.exec_module(weather_capture)
# Selenium으로 강우량 데이터 추출
from selenium_manager import SeleniumManager
selenium_mgr = SeleniumManager()
driver = selenium_mgr.get_driver()
try:
driver.get(weather_capture.WEATHER_URL)
rainfall_data = weather_capture.extract_rainfall_from_page(driver)
if rainfall_data:
# SQLite에만 저장 (이미지 저장, FTP 업로드는 하지 않음)
success = save_rainfall_to_sqlite(rainfall_data, date)
logger.info(f"날씨 데이터 추출 완료 ({date}): {success}")
return success
else:
logger.warning(f"강수량 데이터 추출 실패 ({date})")
return False
finally:
selenium_mgr.close_driver()
except Exception as e:
logger.error(f"날씨 데이터 추출 중 오류: {type(e).__name__}: {e}")
return False
def save_rainfall_to_sqlite(rainfall_data, date):
"""
추출한 강수량 데이터를 SQLite DB에만 저장
(이미지 저장, FTP 업로드, 게시글 등록 없음)
Args:
rainfall_data: {시간(int): 강수량(float)} 딕셔너리
date: 'YYYYMMDD' 형식
Returns:
bool: 성공 여부
"""
if not rainfall_data:
logger.warning("저장할 강수량 데이터가 없음")
return False
try:
os.makedirs(os.path.dirname(DB_PATH) or '/data', exist_ok=True)
conn = sqlite3.connect(DB_PATH)
curs = conn.cursor()
# 테이블 생성
curs.execute('''
CREATE TABLE IF NOT EXISTS rainfall_capture (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT NOT NULL,
hour INTEGER NOT NULL,
rainfall REAL NOT NULL,
UNIQUE(date, hour)
)
''')
curs.execute('''
CREATE TABLE IF NOT EXISTS rainfall_summary (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT NOT NULL UNIQUE,
total_rainfall REAL NOT NULL,
capture_time TEXT NOT NULL
)
''')
# 기존 데이터 삭제
curs.execute('DELETE FROM rainfall_capture WHERE date = ?', (date,))
curs.execute('DELETE FROM rainfall_summary WHERE date = ?', (date,))
# 시간별 강수량 저장
total_rainfall = 0.0
for hour in sorted(rainfall_data.keys()):
rainfall = rainfall_data[hour]
curs.execute(
'INSERT INTO rainfall_capture (date, hour, rainfall) VALUES (?, ?, ?)',
(date, hour, rainfall)
)
total_rainfall += rainfall
# 합계 저장
capture_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
curs.execute(
'INSERT INTO rainfall_summary (date, total_rainfall, capture_time) VALUES (?, ?, ?)',
(date, total_rainfall, capture_time)
)
conn.commit()
conn.close()
logger.info(f"SQLite 저장 완료: {date} 총 강수량 {total_rainfall:.1f}mm")
return True
except Exception as e:
logger.error(f"SQLite 저장 실패: {type(e).__name__}: {e}")
return False
def get_forecast_rainfall(date): def get_forecast_rainfall(date):
""" """
기상청 API를 통한 강수량 예보 조회 기상청 API를 통한 강수량 예보 조회
@ -96,27 +217,47 @@ def get_forecast_rainfall(date):
'nx': '57', 'nx': '57',
'ny': '130' 'ny': '130'
} }
,
'data_status': 'ok' | 'generating' | 'unavailable'
}
"""
today = datetime.now().strftime('%Y%m%d')
is_forecast = date_str > today
data_status = 'ok'
if is_forecast:
# 미래 날짜: API 예보
hourly, total = get_forecast_rainfall(date_str)
note = "⚠️ 이는 기상청 08:00 발표 예보입니다. 실제 이벤트 적용 기준은 당일 09:00 캡처 데이터입니다."
else:
# 당일 이상: 캡처 데이터
hourly, total, timestamp = get_captured_rainfall(date_str)
response = requests.get(url, params=params, timeout=10) # 데이터가 없을 경우 생성 시도
data = response.json() if not hourly:
logger.warning(f"날씨 캡처 데이터 없음 ({date_str}), 데이터 생성 시도...")
if data['response']['header']['resultCode'] != '00': if generate_weather_data(date_str):
return [], 0.0 # 다시 조회
hourly, total, timestamp = get_captured_rainfall(date_str)
rainfall_by_hour = {} if hourly:
for item in data['response']['body']['items']['item']: data_status = 'generating'
if item['category'] == 'RN1': # 1시간 강수량 note = "💡 방금 날씨 데이터를 생성했습니다."
hour = int(item['fcstTime'][:2]) else:
if 10 <= hour <= 21: # 10시~21시(오후 9시) data_status = 'unavailable'
rainfall_by_hour[hour] = parse_rainfall_value(item['fcstValue']) note = "⚠️ 날씨 데이터를 생성했으나 조회할 수 없습니다. 나중에 다시 시도해주세요."
else:
hourly_list = [(h, rainfall_by_hour.get(h, 0.0)) for h in range(10, 22)] data_status = 'unavailable'
total = sum(rain for _, rain in hourly_list) note = "⚠️ 날씨 데이터를 생성할 수 없습니다. 09:00에 자동으로 생성되며, 나중에 다시 시도해주세요."
else:
return hourly_list, total note = None
except Exception as e:
logger.error(f"API 강수량 예보 조회 실패: {e}") return {
return [], 0.0 'date': date_str,
'is_forecast': is_forecast,
'hourly_data': hourly,
'total': total,
'note': note,
'data_status': data_status.0
def get_rainfall_data(date_str): def get_rainfall_data(date_str):
""" """

View File

@ -378,7 +378,8 @@ def main():
file_list = [MAIN['file1'], MAIN['file2']] file_list = [MAIN['file1'], MAIN['file2']]
# 게시글 작성, wr_id = write_board( # 게시글 작성
wr_id = write_board(
board=MAIN['board'], board=MAIN['board'],
subject=MAIN['subject'], subject=MAIN['subject'],
content=MAIN['content'], content=MAIN['content'],
@ -388,7 +389,6 @@ def main():
file_list=file_list, file_list=file_list,
msg_sender=msg_sender, msg_sender=msg_sender,
url=MAIN.get('url') url=MAIN.get('url')
msg_sender=msg_sender
) )
if success: if success:

View File

@ -11,6 +11,8 @@ echo "[$(date '+%Y-%m-%d %H:%M:%S')] ========================================"
# Flask 웹서버를 백그라운드에서 시작 # Flask 웹서버를 백그라운드에서 시작
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Flask 웹서버 시작 (포트 5000)..." echo "[$(date '+%Y-%m-%d %H:%M:%S')] Flask 웹서버 시작 (포트 5000)..."
cd /app cd /app
export FLASK_APP=api_server.py
export PYTHONUNBUFFERED=1
/usr/bin/python -m flask run --host=0.0.0.0 --port=5000 >> /logs/flask.log 2>&1 & /usr/bin/python -m flask run --host=0.0.0.0 --port=5000 >> /logs/flask.log 2>&1 &
FLASK_PID=$! FLASK_PID=$!
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Flask PID: $FLASK_PID" echo "[$(date '+%Y-%m-%d %H:%M:%S')] Flask PID: $FLASK_PID"