Lunar-(13)날씨(실시간 재난문자, 전세계 지역 현재 날씨 검색, 기상관련 사이트 링크)
2024. 1. 8. 22:21
빛하루

화면 왼쪽에는 실시간 재난 문자 정보를 받아오는 기능,
화면 중앙에는 전세계의 지역명을 검색하면 해당 지역의 현재 날씨 정보를 받아와 아이콘으로 표시하는 기능,
화면 오른쪽에는 각종 기상관련 사이트로 이동할 수 있는 링크를 삽입해두었다.
※pages/weather.py 코드
# lunar.state.home 모듈에서 필요한 State 및 HomeState를 가져옵니다.
import reflex as rx
from lunar.state.base import State
from lunar.state.home import HomeState
from PIL import Image
# 컴포넌트를 가져옵니다.
from ..components import container
color = "rgb(107,99,246)"
# 탭 버튼을 생성하는 함수
def tab_button(imagepath, href):
"""A tab switcher button."""
return rx.link(
rx.image(
src=imagepath,
height='40px',
width='40px',
),
display="inline-flex",
align_items="center",
py=3,
px=2,
href=href, # 버튼 클릭 시 이동할 경로
)
def message(message):
return rx.box(
rx.button(
rx.vstack(
rx.box(
rx.text(
message['date'],
style={'white-space': 'normal'},
font_Size = '15px',
font_weight= 'bolder',
),
bg = '#dec445',
),
rx.text(),
rx.text(
message['area'],
style={'white-space': 'normal'},
font_Size = '13px',
font_weight='bold',
),
rx.divider(variant="dashed", border_color="black"),
rx.text(
message['text'],
style={'white-space': 'normal'},
font_size = '15px',
),
width = '100%',
),
height='auto',
width='90%',
),
rx.container(height='5px'),
align='start',
padding='5px', # 테두리와 내용 사이의 여백 지정
)
# 왼쪽에 표시되는 탭 스위처
def tabs():
"""The tab switcher displayed on the left."""
return rx.box(
rx.vstack(
rx.container(
rx.hstack(
rx.image(
src='/moon.png',
height='60px',
width='60px',
),
rx.text(
"Lunar",
style={
"fontSize": "40px",
"fontWeight": "bolder",
"fontFamily": "Calibri, Calibri",
"background": "-webkit-linear-gradient(-45deg, #e04a3f, #4e8be6)",
"-webkit-background-clip": "text",
"color": "transparent",
},
center_content=True,
), # 앱 이름
),
),
rx.vstack(
rx.hstack(
rx.container(width='5px'),
rx.vstack(
rx.container(height='10px'),
rx.vstack(
rx.button('Disaster',Font_size = '20px',on_click = HomeState.climate_message,bg = '#eb7373'),
),
rx.container(height='5px'),
rx.foreach(
HomeState.weather_message_result,
message,
),
rx.container(height='4px'),
align_items='start',
width ='100%',
),
),
align_items = 'start',
margin_left = '20px',
border = '3px solid #000000',
border_radius = '30px',
box_Shadow = '10px 10px 5px #d61c4e',
width = '90%',
),
align_items="start",
gap=4,
),
py=4,
overflow='auto',
)
# 오른쪽에 표시되는 사이드바
def sidebar(HomeState):
"""The sidebar displayed on the right."""
return rx.vstack(
rx.container(height='10px'),
rx.heading(
'Weather sites',
font_Size = '30px',
font_weight='bolder',
bg = 'blue.400',
),
rx.hstack(
rx.container(width='1px'),
rx.vstack(
rx.link(
rx.button("대한민국 기상청"),
href="https://www.weather.go.kr/w/index.do",
color="rgb(107,99,246)",
button=True,
),
rx.link(
rx.button("일본 기상청"),
href="https://www.data.jma.go.jp/multi/index.html?lang=kr",
color="rgb(107,99,246)",
button=True,
),
rx.link(
rx.button("미국 기상청"),
href="https://worldweather.wmo.int/kr/country.html?countryCode=93",
color="rgb(107,99,246)",
button=True,
),
rx.link(
rx.button("Windy"),
href="https://www.windy.com/?36.342,127.389,5",
color="rgb(107,99,246)",
button=True,
),
rx.link(
rx.button("AccuWeather"),
href="https://www.accuweather.com/",
color="rgb(107,99,246)",
button=True,
),
align_items='start',
width ='100%',
),
border = '2px solid #000000',
border_radius = '30px',
box_Shadow = '10px 10px 5px #307849',
width='80%',
),
align_items="start",
gap=4,
height='100%',
width = '100%',
py=4,
overflow='auto',
)
# 피드의 헤더
def feed_header(HomeState):
"""The header of the feed."""
return rx.hstack(
rx.image(src='/find1.png',height='35px',width='35px'),
rx.input(on_change=HomeState.set_weather_search, placeholder="Search place..!"),
rx.button('search', on_click = HomeState.climate_websearch),
justify="space-between",
p=4,
border_bottom="3px solid #000000",
)
# 피드 영역
def feed(HomeState):
"""The feed."""
return rx.box(
feed_header(HomeState),
rx.container(height='10px'),
rx.vstack(
rx.cond(
HomeState.weather_search_show,
rx.vstack(
rx.hstack(
rx.heading(
HomeState.weather_search,
as_='mark',
font_Size = '50px',
),
margin_left = '5%',
),
rx.hstack(
rx.vstack(
rx.text(
f"현재 기온 : {HomeState.status_temperature}'C",
font_Size = '25px',
font_weight='bold',
),
rx.text(
f'현재 날씨 : {HomeState.status_climate}',
font_Size = '25px',
font_weight='bolder',
),
rx.text(
f"체감 온도 : {HomeState.status_feel_temperature}'C",
font_Size = '25px',
font_weight='bolder',
),
rx.text(
f"최저 온도 : {HomeState.today_min_temperature}'C",
font_Size = '25px',
font_weight='bolder',
color = 'blue',
),
rx.text(
f"최고 온도 : {HomeState.today_max_temperature}'C",
font_Size = '25px',
font_weight='bolder',
color = 'red',
),
rx.text(
f'현재 습도 : {HomeState.status_humidity}%',
font_Size = '25px',
font_weight='bolder',
),
rx.text(
f'현재 기압 : {HomeState.status_atmospheric_pressure}hpa',
font_Size = '25px',
font_weight='bolder',
),
rx.text(
f'풍속 : {HomeState.status_wind_speed}m/s',
font_Size = '25px',
font_weight='bolder',
),
align_items='start',
margin_left = '5%',
),
rx.container(width='5%'),
rx.vstack(
rx.image(
src = HomeState.image,
height='400px',
width = 'auto',
)
)
),
width = '90%',
margin_left = '5%',
align_items='start',
border = '2px solid #000000',
border_radius = '30px',
box_Shadow = '10px 10px 10px #575050',
),
rx.vstack(
rx.heading(
'Enter the area where you want to search for weather.',
font_Size = '40px',
font_weight='border',
),
align_items='start',
width = '100%',
)
)
),
rx.container(height='20px'),
overflow='auto',
)
# 홈 페이지
def weather():
State.check_login
return rx.vstack(
rx.grid(
tabs(),
feed(HomeState),
sidebar(HomeState),
grid_template_columns="2fr 5fr 2fr",
width='97%',
h="90vh",
gap=4,
),
rx.grid(
rx.vstack(
rx.container(height='5px'),
rx.button(
rx.icon(tag="moon"),
on_click=rx.toggle_color_mode,
width = '80%',
_hover={"bg": "orange.400"},
),
width = '100%',
),
rx.vstack(
rx.hstack(
tab_button('/Home.png','/'),
tab_button('/profile.png','/profile'),
tab_button('/map.png','/map'),
tab_button('/chat.png','/chat'),
tab_button('/Aichat.png','/aichat'),
tab_button('/diary.png','/diary'),
tab_button('/video.png','/video'),
tab_button('/game.png','/game'),
tab_button('/music.png','/music'),
tab_button('/weather.png','/weather'),
tab_button('/setting.png','/setting'),
margin_right='5px',
border="1px solid #000000",
border_radius="full",
box_Shadow = '10px 10px 5px #3083f0',
),
width = '100%',
),
rx.vstack(
rx.container(height='5px'),
rx.button(
"Sign out",
on_click=State.logout,
bg="#212963",
color="white",
_hover={"bg": "blue.600"},
width = '80%',
),
width = '100%',
),
width='97%',
grid_template_columns="2fr 5fr 2fr",
),
)
※ state/home.py의 기상관련 함수를 담당하는 코드
# 재난문자 웹 크롤링
def climate_message(self):
url = "https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=0&ie=utf8&query=%EC%9E%AC%EB%82%9C%EB%AC%B8%EC%9E%90"
response = requests.get(url)
html = response.text
soup = bs(html, 'html.parser')
areas = soup.select(".area")
disaster_texts = soup.select(".disaster_text")
dates = soup.select(".date")
self.weather_message_result = []
# 결과 출력
for area, disaster_text, date in zip(areas, disaster_texts, dates):
data = {'area' : area.get_text(strip=True), 'date' : date.get_text(strip=True), 'text':disaster_text.get_text(strip = True) }
self.weather_message_result.append(data)
# 날씨 웹 크롤링
def climate_websearch(self):
key=''
with open('weatherapikey.json','r')as f:
key = json.load(f)
weather_api_key = key['key']
url = f"http://api.openweathermap.org/data/2.5/weather?q={self.weather_search}&appid={weather_api_key}&lang=kr&units=metric"
result = requests.get(url)
data = json.loads(result.text)
self.status_climate = data['weather'][0]['description']
self.status_temperature = data['main']['temp']
self.status_feel_temperature = data['main']['feels_like']
self.today_min_temperature = data['main']['temp_min']
self.today_max_temperature = data['main']['temp_max']
self.status_humidity = data['main']['humidity']
self.status_atmospheric_pressure = data['main']['pressure']
self.status_wind_direction = data['wind']['deg']
self.status_wind_speed = data['wind']['speed']
self.status_climate_icon_url= f"https://openweathermap.org/img/wn/{data['weather'][0]['icon']}@2x.png"
self.image = Image.open((requests.get(self.status_climate_icon_url, stream=True).raw))
self.weather_search_show=True'Projects' 카테고리의 다른 글
| Lunar-(15)전체코드 중간정리2(함수 부분) (0) | 2024.01.08 |
|---|---|
| Lunar-(14)전체코드 중간 정리1(프론트엔드 부분) (3) | 2024.01.08 |
| Lunar-(12)멜론 차트 top100 가져오기, 가수 크롤링 검색결과 (1) | 2024.01.03 |
| Lunar-(11)현재 수정중인 작업, 기능추가예정작업 (0) | 2024.01.01 |
| Lunar-(10)비디오 기능추가(구글 웹 크롤링-Selenium) (0) | 2023.12.24 |