JAMESPARK3's picture
Update app.py
586c602 verified
import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
import google.generativeai as genai
from datetime import datetime, timedelta
import time
import xml.etree.ElementTree as ET
import requests
import matplotlib.font_manager as fm
import os
# 폰트 μ„€μ •
plt.rcParams['font.family'] = 'DejaVu Sans'
plt.rcParams['axes.unicode_minus'] = False
# API ν‚€ μ„€μ •
GEMINI_API_KEY = os.environ.get('GEMINI_API_KEY')
WEATHER_API_KEY = os.environ.get('WEATHER_API_KEY')
# Gemini λͺ¨λΈ μ„€μ •
genai.configure(api_key=GEMINI_API_KEY)
model = genai.GenerativeModel('gemini-2.0-flash-exp')
def get_weather_data(base_date):
url = "https://apihub.kma.go.kr/api/typ02/openApi/VilageFcstInfoService_2.0/getVilageFcst"
params = {
'pageNo': '1',
'numOfRows': '1000',
'dataType': 'XML',
'base_date': base_date,
'base_time': '0500',
'nx': '59',
'ny': '125',
'authKey': WEATHER_API_KEY
}
response = requests.get(url, params=params)
response.raise_for_status()
return response.text
def parse_weather_data(xml_data):
root = ET.fromstring(xml_data)
all_data = []
for item in root.findall('.//item'):
all_data.append({
'base_date': item.find('baseDate').text,
'category': item.find('category').text,
'fcstTime': item.find('fcstTime').text,
'fcstValue': item.find('fcstValue').text,
'fcstDate': item.find('fcstDate').text
})
return pd.DataFrame(all_data)
def get_precipitation_times(pty_data):
if pty_data.empty:
return "μ—†μŒ"
# κ°•μˆ˜κ°€ μžˆλŠ” μ‹œκ°„λŒ€ μ°ΎκΈ°
precipitation_times = pty_data[pty_data['fcstValue'] != '0']
if precipitation_times.empty:
return "μ—†μŒ"
# μ—°μ†λœ μ‹œκ°„λŒ€ κ·Έλ£Ήν™”
times = precipitation_times['fcst_datetime'].dt.strftime('%Hμ‹œ')
return f"{times.iloc[0]}λΆ€ν„° {times.iloc[-1]}κΉŒμ§€"
def analyze_weather_trends(df, current_time):
tomorrow = (current_time + timedelta(days=1)).strftime("%Y%m%d")
# 였늘과 내일 λ‚ μ§œμ˜ 데이터 뢄리
today_data = df[df['fcstDate'] == current_time.strftime("%Y%m%d")]
tomorrow_data = df[df['fcstDate'] == tomorrow]
# 였늘 기온 데이터 처리
temp_data = today_data[today_data['category'] == 'TMP'].copy()
if not temp_data.empty:
temp_data['fcst_datetime'] = pd.to_datetime(temp_data['fcstDate'] + temp_data['fcstTime'], format='%Y%m%d%H00')
closest_time_data = temp_data.iloc[(temp_data['fcst_datetime'] - current_time).abs().argsort()[:1]]
current_temp = float(closest_time_data['fcstValue'].iloc[0])
else:
current_temp = 0
# 였늘 μ‹œκ°„λŒ€λ³„ 기온 계산
temp_data['hour'] = temp_data['fcstTime'].str[:2].astype(int)
morning_temps = temp_data[temp_data['hour'].between(6, 11)]['fcstValue'].astype(float)
afternoon_temps = temp_data[temp_data['hour'].between(12, 17)]['fcstValue'].astype(float)
evening_temps = temp_data[temp_data['hour'].between(18, 23)]['fcstValue'].astype(float)
# 였늘 ν•˜λŠ˜μƒνƒœ 데이터
sky_data = today_data[today_data['category'] == 'SKY'].copy()
if not sky_data.empty:
sky_data['fcst_datetime'] = pd.to_datetime(sky_data['fcstDate'] + sky_data['fcstTime'], format='%Y%m%d%H00')
morning_sky_data = sky_data[sky_data['fcst_datetime'].dt.hour.between(6, 11)].sort_values(by='fcst_datetime').iloc[0] if len(sky_data[sky_data['fcst_datetime'].dt.hour.between(6, 11)]) > 0 else None
afternoon_sky_data = sky_data[sky_data['fcst_datetime'].dt.hour.between(12, 17)].sort_values(by='fcst_datetime').iloc[0] if len(sky_data[sky_data['fcst_datetime'].dt.hour.between(12, 17)]) > 0 else None
evening_sky_data = sky_data[sky_data['fcst_datetime'].dt.hour.between(18, 23)].sort_values(by='fcst_datetime').iloc[0] if len(sky_data[sky_data['fcst_datetime'].dt.hour.between(18, 23)]) > 0 else None
morning_sky = morning_sky_data['fcstValue'] if morning_sky_data is not None else '1'
afternoon_sky = afternoon_sky_data['fcstValue'] if afternoon_sky_data is not None else '1'
evening_sky = evening_sky_data['fcstValue'] if evening_sky_data is not None else '1'
else:
morning_sky = afternoon_sky = evening_sky = '1'
# 였늘 κ°•μˆ˜ν˜•νƒœ 데이터
pty_data = today_data[today_data['category'] == 'PTY'].copy()
if not pty_data.empty:
pty_data['fcst_datetime'] = pd.to_datetime(pty_data['fcstDate'] + pty_data['fcstTime'], format='%Y%m%d%H00')
current_pty_data = pty_data.iloc[(pty_data['fcst_datetime'] - current_time).abs().argsort()[:1]]
current_pty = current_pty_data['fcstValue'].iloc[0] if not current_pty_data.empty else '0'
today_precip_times = get_precipitation_times(pty_data)
else:
current_pty = '0'
today_precip_times = "μ—†μŒ"
# 내일 데이터 뢄석
tomorrow_temp_data = tomorrow_data[tomorrow_data['category'] == 'TMP'].copy()
tomorrow_sky_data = tomorrow_data[tomorrow_data['category'] == 'SKY'].copy()
tomorrow_pty_data = tomorrow_data[tomorrow_data['category'] == 'PTY'].copy()
if not tomorrow_pty_data.empty:
tomorrow_pty_data['fcst_datetime'] = pd.to_datetime(tomorrow_pty_data['fcstDate'] + tomorrow_pty_data['fcstTime'], format='%Y%m%d%H00')
tomorrow_precip_times = get_precipitation_times(tomorrow_pty_data)
else:
tomorrow_precip_times = "μ—†μŒ"
# 내일 μ‹œκ°„λŒ€λ³„ 기온 계산
tomorrow_temp_data['hour'] = tomorrow_temp_data['fcstTime'].str[:2].astype(int)
tomorrow_morning_temps = tomorrow_temp_data[tomorrow_temp_data['hour'].between(6, 11)]['fcstValue'].astype(float)
tomorrow_afternoon_temps = tomorrow_temp_data[tomorrow_temp_data['hour'].between(12, 17)]['fcstValue'].astype(float)
tomorrow_evening_temps = tomorrow_temp_data[tomorrow_temp_data['hour'].between(18, 23)]['fcstValue'].astype(float)
# 내일 ν•˜λŠ˜μƒνƒœ
if not tomorrow_sky_data.empty:
tomorrow_sky_data['fcst_datetime'] = pd.to_datetime(tomorrow_sky_data['fcstDate'] + tomorrow_sky_data['fcstTime'], format='%Y%m%d%H00')
tomorrow_morning_sky = tomorrow_sky_data[tomorrow_sky_data['fcst_datetime'].dt.hour.between(6, 11)].iloc[0]['fcstValue'] if len(tomorrow_sky_data[tomorrow_sky_data['fcst_datetime'].dt.hour.between(6, 11)]) > 0 else '1'
tomorrow_afternoon_sky = tomorrow_sky_data[tomorrow_sky_data['fcst_datetime'].dt.hour.between(12, 17)].iloc[0]['fcstValue'] if len(tomorrow_sky_data[tomorrow_sky_data['fcst_datetime'].dt.hour.between(12, 17)]) > 0 else '1'
tomorrow_evening_sky = tomorrow_sky_data[tomorrow_sky_data['fcst_datetime'].dt.hour.between(18, 23)].iloc[0]['fcstValue'] if len(tomorrow_sky_data[tomorrow_sky_data['fcst_datetime'].dt.hour.between(18, 23)]) > 0 else '1'
else:
tomorrow_morning_sky = tomorrow_afternoon_sky = tomorrow_evening_sky = '1'
# 내일 κ°•μˆ˜μƒνƒœ
if not tomorrow_pty_data.empty:
tomorrow_morning_pty = tomorrow_pty_data[tomorrow_pty_data['fcst_datetime'].dt.hour.between(6, 11)].iloc[0]['fcstValue'] if len(tomorrow_pty_data[tomorrow_pty_data['fcst_datetime'].dt.hour.between(6, 11)]) > 0 else '0'
tomorrow_afternoon_pty = tomorrow_pty_data[tomorrow_pty_data['fcst_datetime'].dt.hour.between(12, 17)].iloc[0]['fcstValue'] if len(tomorrow_pty_data[tomorrow_pty_data['fcst_datetime'].dt.hour.between(12, 17)]) > 0 else '0'
tomorrow_evening_pty = tomorrow_pty_data[tomorrow_pty_data['fcst_datetime'].dt.hour.between(18, 23)].iloc[0]['fcstValue'] if len(tomorrow_pty_data[tomorrow_pty_data['fcst_datetime'].dt.hour.between(18, 23)]) > 0 else '0'
else:
tomorrow_morning_pty = tomorrow_afternoon_pty = tomorrow_evening_pty = '0'
# 날씨 μƒνƒœ λ§€ν•‘
sky_status = {'1': 'λ§‘μŒ', '2': 'κ΅¬λ¦„μ‘°κΈˆ', '3': 'κ΅¬λ¦„λ§ŽμŒ', '4': '흐림'}
pty_status = {'0': 'μ—†μŒ', '1': 'λΉ„', '2': 'λΉ„/눈', '3': '눈', '4': 'μ†Œλ‚˜κΈ°'}
prompt = f"""
ν˜„μž¬ μ‹œκ°: {current_time.strftime('%Yλ…„ %mμ›” %d일 %Hμ‹œ %MλΆ„')} κΈ°μ€€
[였늘 날씨 정보]
1. 기온 정보:
- ν˜„μž¬ 기온: {current_temp}도
- 졜고 기온: {max(temp_data['fcstValue'].astype(float))}도
- μ΅œμ € 기온: {min(temp_data['fcstValue'].astype(float))}도
- μ•„μΉ¨ 평균 기온: {morning_temps.mean():.1f}도
- μ˜€ν›„ 평균 기온: {afternoon_temps.mean():.1f}도
- 저녁 평균 기온: {evening_temps.mean():.1f}도
2. ν•˜λŠ˜μƒνƒœ:
- μ•„μΉ¨: {sky_status.get(morning_sky, 'μ•Œμˆ˜μ—†μŒ')}
- μ˜€ν›„: {sky_status.get(afternoon_sky, 'μ•Œμˆ˜μ—†μŒ')}
- 저녁: {sky_status.get(evening_sky, 'μ•Œμˆ˜μ—†μŒ')}
3. κ°•μˆ˜ μƒνƒœ: {pty_status.get(current_pty, 'μ•Œμˆ˜μ—†μŒ')}
κ°•μˆ˜ μ‹œκ°„: {today_precip_times}
[내일 날씨 정보]
1. 기온 정보:
- 졜고 기온: {max(tomorrow_temp_data['fcstValue'].astype(float))}도
- μ΅œμ € 기온: {min(tomorrow_temp_data['fcstValue'].astype(float))}도
- μ•„μΉ¨ 평균 기온: {tomorrow_morning_temps.mean():.1f}도
- μ˜€ν›„ 평균 기온: {tomorrow_afternoon_temps.mean():.1f}도
- 저녁 평균 기온: {tomorrow_evening_temps.mean():.1f}도
2. ν•˜λŠ˜μƒνƒœ:
- μ•„μΉ¨: {sky_status.get(tomorrow_morning_sky, 'μ•Œμˆ˜μ—†μŒ')}
- μ˜€ν›„: {sky_status.get(tomorrow_afternoon_sky, 'μ•Œμˆ˜μ—†μŒ')}
- 저녁: {sky_status.get(tomorrow_evening_sky, 'μ•Œμˆ˜μ—†μŒ')}
3. κ°•μˆ˜ μƒνƒœ:
- μ•„μΉ¨: {pty_status.get(tomorrow_morning_pty, 'μ•Œμˆ˜μ—†μŒ')}
- μ˜€ν›„: {pty_status.get(tomorrow_afternoon_pty, 'μ•Œμˆ˜μ—†μŒ')}
- 저녁: {pty_status.get(tomorrow_evening_pty, 'μ•Œμˆ˜μ—†μŒ')}
κ°•μˆ˜ μ‹œκ°„: {tomorrow_precip_times}
μœ„ 정보λ₯Ό λ°”νƒ•μœΌλ‘œ 였늘과 λ‚΄μΌμ˜ 날씨λ₯Ό 총 100자 μ •λ„λ‘œ μ „λ¬Έ κΈ°μƒμΊμŠ€ν„°μ²˜λŸΌ μžμ—°μŠ€λŸ½κ²Œ μ„€λͺ…ν•΄μ£Όμ„Έμš”.
"λ„€","μ„€λͺ…λ“œλ¦¬κ² μŠ΅λ‹ˆλ‹€."λ“±κ³Ό 같은 인사말은 μ œμ™Έν•˜κ³ , λ‚ μ”¨μ •λ³΄λ§Œ 였늘과 내일 날씨λ₯Ό μ΄μ–΄μ„œ μ„€λͺ…ν•΄μ£Όμ„Έμš”.
ν˜„μž¬μ‹œκ° κΈ°μ˜¨μ„ λ¨Όμ € μ•Œλ €μ£Όκ³ , 였늘과 내일 μ•„μΉ¨, μ˜€ν›„, μ €λ…μ˜ 졜고/μ΅œμ €μ˜¨λ„μ™€ 눈/λΉ„ μ—¬λΆ€λ₯Ό λ°˜λ“œμ‹œ ν¬ν•¨ν•˜κ³ ,
λˆˆμ΄λ‚˜ λΉ„κ°€ 였면 λͺ‡μ‹œλΆ€ν„° λͺ‡μ‹œκΉŒμ§€ μ˜€λŠ”μ§€ λ°˜λ“œμ‹œ μ•Œλ €μ£Όμ„Έμš”.
"""
response = model.generate_content(prompt)
return response.text
def get_current_temperature(temp_data, current_time):
# fcstTime을 datetime 객체둜 λ³€ν™˜
temp_data['fcst_datetime'] = pd.to_datetime(temp_data['fcstDate'] + temp_data['fcstTime'], format='%Y%m%d%H00')
# ν˜„μž¬ μ‹œκ°„κ³Ό κ°€μž₯ κ°€κΉŒμš΄ 예보 μ‹œκ°„ μ°ΎκΈ°
closest_time_data = temp_data.iloc[(temp_data['fcst_datetime'] - current_time).abs().argsort()[:1]]
return float(closest_time_data['fcstValue'])
def main():
# νŽ˜μ΄μ§€ μ—¬λ°± 쀄이기 μœ„ν•œ CSS μΆ”κ°€
st.markdown("""
<style>
.block-container {
padding-left: 1rem !important;
padding-right: 1rem !important;
max-width: 95% !important;
}
.css-1d391kg {
padding-left: 1rem;
padding-right: 1rem;
}
</style>
""", unsafe_allow_html=True)
while True:
try:
current_time = datetime.now() + timedelta(hours=8)
print(f"[DEBUG] Current time: {current_time}")
base_date = current_time.strftime("%Y%m%d")
print(f"[DEBUG] Base date: {base_date}")
# 05μ‹œ 이전이면 μ „λ‚  데이터 μ‚¬μš©
if current_time.hour < 5:
base_date = (current_time - timedelta(days=1)).strftime("%Y%m%d")
else:
base_date = current_time.strftime("%Y%m%d")
print(f"[DEBUG] Base date for API request: {base_date}")
xml_data = get_weather_data(base_date)
print(f"[DEBUG] XML data received: {len(xml_data)} bytes")
print(f"[DEBUG] XML content: {xml_data[:500]}") # 처음 500자만 좜λ ₯
# XML νŒŒμ‹± 전에 root μš”μ†Œ 확인
root = ET.fromstring(xml_data)
print(f"[DEBUG] XML root tag: {root.tag}")
print(f"[DEBUG] XML root children: {[child.tag for child in root]}")
df = parse_weather_data(xml_data)
print(f"[DEBUG] Parsed DataFrame shape: {df.shape}")
print(f"[DEBUG] DataFrame columns: {df.columns}")
# μ˜¨λ„ 데이터 처리
temp_data = df[df['category'] == 'TMP'].copy()
print(f"[DEBUG] Temperature data shape: {temp_data.shape}")
temp_data['datetime'] = pd.to_datetime(temp_data['fcstDate'] + temp_data['fcstTime'], format='%Y%m%d%H%M')
print(f"[DEBUG] Datetime range: {temp_data['datetime'].min()} to {temp_data['datetime'].max()}")
# ν˜„μž¬ 기온 계산
current_temp = get_current_temperature(temp_data, current_time)
print(f"[DEBUG] Current temperature: {current_temp}")
# 날씨 예보 생성
weather_forecast = analyze_weather_trends(df, current_time)
print(f"[DEBUG] Weather forecast generated: {len(weather_forecast)} characters")
# 내일 μ•„μΉ¨ 기온 계산
tomorrow_data = df[df['fcstDate'] == (current_time + timedelta(days=1)).strftime("%Y%m%d")]
tomorrow_temp_data = tomorrow_data[tomorrow_data['category'] == 'TMP'].copy()
tomorrow_temp_data['hour'] = tomorrow_temp_data['fcstTime'].str[:2].astype(int)
tomorrow_morning_temps = tomorrow_temp_data[tomorrow_temp_data['hour'].between(6, 11)]['fcstValue'].astype(float)
tomorrow_morning_temp = tomorrow_temp_data[tomorrow_temp_data['hour'] == 6]['fcstValue'].iloc[0] if not tomorrow_temp_data[tomorrow_temp_data['hour'] == 6].empty else 0
st.markdown(f"""<span style='font-size: 3.5em'><b>μ‹€μ‹œκ°„ 날씨 λŒ€μ‹œλ³΄λ“œ</b> <span style='font-size: 0.7em'>(ν˜„μž¬μ˜¨λ„: <b><span style='color: {'red' if current_temp >= 0 else 'blue'}'>{current_temp:.1f}</span></b>도, 내일 μ•„μΉ¨ 6μ‹œ μ˜¨λ„: <b><span style='color: {'red' if float(tomorrow_morning_temp) >= 0 else 'blue'}'>{float(tomorrow_morning_temp):.1f}</span></b>도)</span></span>""", unsafe_allow_html=True)
# κ·Έλž˜ν”„ 그리기
fig, ax = plt.subplots(figsize=(25, 10))
# 색상 νŒ”λ ˆνŠΈ μ„€μ •
colors = ['#FF0000', '#00AA00', '#0000FF', '#FFA500', '#800080'] # λΉ¨κ°•, 초둝, νŒŒλž‘, μ£Όν™©, 보라
for idx, date in enumerate(temp_data['fcstDate'].unique()):
date_data = temp_data[temp_data['fcstDate'] == date]
temps = date_data['fcstValue'].astype(float)
times = date_data['datetime']
color = colors[idx % len(colors)]
# κΈ°λ³Έ μ˜¨λ„ μ„  κ·Έλž˜ν”„ - μ„  μŠ€νƒ€μΌ κ°œμ„ 
line = ax.plot(times, temps,
marker='o',
label=f'{date[:4]}-{date[4:6]}-{date[6:]}',
markersize=12, # 마컀 크기 증가
linewidth=5, # μ„  κ΅΅κΈ° 증가
color=color,
markeredgewidth=2.5,
markerfacecolor=color,
markeredgecolor='white',
linestyle='-',
alpha=0.8) # μ•½κ°„μ˜ 투λͺ…도 μΆ”κ°€
# 졜고/μ΅œμ € μ˜¨λ„ μ°ΎκΈ°
max_temp = temps.max()
min_temp = temps.min()
max_temp_time = times[temps.idxmax()]
min_temp_time = times[temps.idxmin()]
# 졜고 μ˜¨λ„ ν‘œμ‹œ - 더 λˆˆμ— λ„κ²Œ μˆ˜μ •
ax.annotate(f'Max: {max_temp}Β°C',
xy=(max_temp_time, max_temp),
xytext=(10, 15),
textcoords='offset points',
ha='left',
va='bottom',
bbox=dict(boxstyle='round,pad=0.5',
fc='yellow',
alpha=0.7,
edgecolor=color),
fontsize=27,
fontweight='bold',
color=color)
# μ΅œμ € μ˜¨λ„ ν‘œμ‹œ - 더 λˆˆμ— λ„κ²Œ μˆ˜μ •
ax.annotate(f'Min: {min_temp}Β°C',
xy=(min_temp_time, min_temp),
xytext=(10, -15),
textcoords='offset points',
ha='left',
va='top',
bbox=dict(boxstyle='round,pad=0.5',
fc='lightblue',
alpha=0.7,
edgecolor=color),
fontsize=27,
fontweight='bold',
color=color)
# κ·Έλž˜ν”„ μŠ€νƒ€μΌ κ°œμ„ 
ax.set_title('', fontsize=18, pad=20, fontweight='bold')
ax.set_xlabel('λ‚ μ§œ 및 μ‹œκ°„', fontsize=16, fontweight='bold')
ax.set_ylabel('기온 (°C)', fontsize=16, fontweight='bold')
ax.tick_params(axis='both', labelsize=14)
ax.grid(True, linestyle='--', alpha=0.4)
# λ°€ μ‹œκ°„λŒ€ 음영 처리
dates = temp_data['fcstDate'].unique()
for date in dates:
evening = pd.to_datetime(f"{date[:4]}-{date[4:6]}-{date[6:]} 18:00:00")
next_morning = evening + timedelta(hours=12)
ax.axvspan(evening, next_morning,
alpha=0.2,
color='gray',
label='_nolegend_')
# λ‚ μ§œ λ³€κ²½μ„  μΆ”κ°€
dates = temp_data['fcstDate'].unique()
for date in dates[1:]:
midnight = pd.to_datetime(f"{date[:4]}-{date[4:6]}-{date[6:]} 00:00:00")
ax.axvline(x=midnight,
color='black',
linestyle=':',
linewidth=2,
alpha=0.5,
label='_nolegend_')
ax.annotate(f'{date[4:6]}/{date[6:]}',
xy=(midnight, ax.get_ylim()[1]),
xytext=(0, 10),
textcoords='offset points',
ha='center',
fontsize=25,
fontweight='bold',
color='black')
ax.set_facecolor('#f8f9fa')
min_time = temp_data['datetime'].min()
max_time = temp_data['datetime'].max()
# ν˜„μž¬ μ‹œκ° μ„Έλ‘œμ„  μΆ”κ°€
current_datetime = pd.to_datetime(current_time)
if min_time <= current_datetime <= max_time:
ax.axvline(x=current_datetime, color='red', linestyle='--', linewidth=3, alpha=0.7)
ax.annotate('Now',
xy=(current_datetime, ax.get_ylim()[1]),
xytext=(0, 10),
textcoords='offset points',
ha='center',
va='bottom',
bbox=dict(boxstyle='round,pad=0.5',
fc='white',
ec='red',
alpha=0.8),
fontsize=25,
fontweight='bold',
color='red')
ax.set_xlim(min_time, max_time)
# λ²”λ‘€ μŠ€νƒ€μΌ μ„€μ • κ°œμ„ 
legend = ax.legend(fontsize=25,
frameon=True,
facecolor='white',
edgecolor='gray',
loc='upper right',
bbox_to_anchor=(1.13, 1.0))
for text in legend.get_texts():
text.set_fontweight('bold')
plt.xticks(rotation=45)
plt.tight_layout()
st.pyplot(fig, use_container_width=True)
plt.close()
# 날씨 예보 ν…μŠ€νŠΈλ₯Ό 슀크둀 νš¨κ³Όμ™€ ν•¨κ»˜ ν‘œμ‹œ
st.markdown(
'<style>'
'.scroll-container {'
' width: 100%;'
' overflow: hidden;'
' padding: 10px 0;'
'}'
'.scroll-text {'
' display: inline-block;'
' white-space: nowrap;'
' animation: scroll-left 40s linear infinite;'
' padding-left: 100%;'
'}'
'@keyframes scroll-left {'
' 0% { transform: translateX(0); }'
' 100% { transform: translateX(-100%); }' # -200%μ—μ„œ -100%둜 λ³€κ²½
'}'
'</style>'
'<div class="scroll-container">'
f' <div class="scroll-text">'
f' <span style="font-size: 1.8em; font-weight: bold; color: yellow;">{weather_forecast.replace(chr(10), " ")}</span>'
f' <span style="font-size: 1.8em; font-weight: bold; color: yellow; margin-left: 100px;">{weather_forecast.replace(chr(10), " ")}</span>' # λ™μΌν•œ ν…μŠ€νŠΈ ν•œλ²ˆ 더 μΆ”κ°€
' </div>'
'</div>',
unsafe_allow_html=True
)
time.sleep(300)
st.rerun()
except Exception as e:
st.error(f"였λ₯˜ λ°œμƒ: {str(e)}")
time.sleep(300)
if __name__ == "__main__":
main()