Spaces:
Build error
Build error
| import streamlit as st | |
| import requests | |
| from bs4 import BeautifulSoup | |
| import pandas as pd | |
| import plotly.express as px | |
| import time | |
| def main(): | |
| st.set_page_config(page_title="奇美醫院病床占用率查詢", layout="wide") | |
| st.title("奇美醫院病床占用率查詢系統") | |
| st.write("此應用程式顯示奇美醫院的即時病床占用情況") | |
| # 添加刷新按鈕 | |
| if st.button("刷新數據"): | |
| st.cache_data.clear() | |
| # 獲取病床數據 | |
| df = get_hospital_bed_data() | |
| # 如果數據獲取失敗,提供示例數據 | |
| if df.empty: | |
| st.warning("⚠️ 無法連接到奇美醫院網站。顯示示例數據以供參考。") | |
| df = get_sample_data() | |
| # 顯示數據 | |
| col1, col2 = st.columns([2, 3]) | |
| with col1: | |
| st.subheader("病床占用數據表") | |
| st.dataframe(df, use_container_width=True) | |
| # 計算總數 | |
| total_beds = df['總床數'].sum() | |
| total_occupied = df['佔床數'].sum() | |
| total_available = df['空床數'].sum() | |
| overall_rate = f"{(total_occupied / total_beds * 100):.2f}%" if total_beds > 0 else "0%" | |
| st.subheader("總計") | |
| total_data = pd.DataFrame({ | |
| '項目': ['總病床數', '總佔床數', '總空床數', '整體佔床率'], | |
| '數值': [total_beds, total_occupied, total_available, overall_rate] | |
| }) | |
| st.dataframe(total_data, use_container_width=True, hide_index=True) | |
| with col2: | |
| st.subheader("病床占用率視覺化") | |
| # 創建占用率條形圖 | |
| fig = px.bar( | |
| df, | |
| x='病床類別', | |
| y='佔床數', | |
| text='佔床率', | |
| color='佔床率', | |
| color_continuous_scale='RdYlGn_r', # 紅(高)-黃-綠(低)色彩範圍 | |
| labels={'佔床數': '已占用病床數', '病床類別': '病床類型', '佔床率': '占用率'}, | |
| height=500 | |
| ) | |
| fig.update_layout(xaxis={'categoryorder': 'total descending'}) | |
| st.plotly_chart(fig, use_container_width=True) | |
| # 創建餅圖顯示空床/占床比例 | |
| pie_data = pd.DataFrame({ | |
| '狀態': ['已占用', '可用'], | |
| '數量': [total_occupied, total_available] | |
| }) | |
| pie_fig = px.pie( | |
| pie_data, | |
| values='數量', | |
| names='狀態', | |
| color='狀態', | |
| color_discrete_map={'已占用': 'red', '可用': 'green'}, | |
| hole=0.4 | |
| ) | |
| st.plotly_chart(pie_fig, use_container_width=True) | |
| # 資料快取5分鐘 | |
| def get_hospital_bed_data(): | |
| """獲取奇美醫院病床占用數據""" | |
| try: | |
| # URL of the page to scrape | |
| url = "https://www.chimei.org.tw/%E4%BD%94%E5%BA%8A%E7%8E%87%E6%9F%A5%E8%A9%A2/%E4%BD%94%E5%BA%8A%E7%8E%87%E6%9F%A5%E8%A9%A2.aspx?ihospital=10&ffloor=" | |
| # 設置請求頭,模擬瀏覽器訪問 | |
| headers = { | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', | |
| 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', | |
| 'Accept-Language': 'zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7', | |
| 'Connection': 'keep-alive', | |
| 'Upgrade-Insecure-Requests': '1', | |
| 'Referer': 'https://www.chimei.org.tw/' | |
| } | |
| # Send HTTP request with timeout and headers | |
| response = requests.get(url, headers=headers, timeout=10) | |
| response.encoding = 'utf-8' # Set encoding to handle Chinese characters | |
| # Create BeautifulSoup object | |
| soup = BeautifulSoup(response.text, 'html.parser') | |
| # Find the target table (DG1) | |
| target_table = soup.find('table', {'id': 'DG1'}) | |
| # Extract data from the table | |
| data = [] | |
| if target_table: | |
| rows = target_table.find_all('tr') | |
| # Skip the header row | |
| for row in rows[1:]: | |
| cols = row.find_all('td') | |
| if len(cols) == 5: # Ensure row has 5 columns | |
| bed_type = cols[0].text.strip() | |
| total_beds = int(cols[1].text.strip()) | |
| occupied_beds = int(cols[2].text.strip()) | |
| available_beds = int(cols[3].text.strip()) | |
| occupancy_rate = cols[4].text.strip() | |
| data.append({ | |
| '病床類別': bed_type, | |
| '總床數': total_beds, | |
| '佔床數': occupied_beds, | |
| '空床數': available_beds, | |
| '佔床率': occupancy_rate | |
| }) | |
| # Create pandas DataFrame | |
| df = pd.DataFrame(data) | |
| return df | |
| except Exception as e: | |
| st.error(f"獲取數據時發生錯誤: {e}") | |
| return pd.DataFrame() | |
| def get_sample_data(): | |
| """提供示例數據,當無法從網站獲取數據時使用""" | |
| data = [ | |
| {'病床類別': '一般病床', '總床數': 1200, '佔床數': 980, '空床數': 220, '佔床率': '81.67%'}, | |
| {'病床類別': '加護病床', '總床數': 120, '佔床數': 98, '空床數': 22, '佔床率': '81.67%'}, | |
| {'病床類別': '燒燙傷病床', '總床數': 30, '佔床數': 18, '空床數': 12, '佔床率': '60.00%'}, | |
| {'病床類別': '負壓隔離病床', '總床數': 24, '佔床數': 10, '空床數': 14, '佔床率': '41.67%'}, | |
| {'病床類別': '急診觀察病床', '總床數': 60, '佔床數': 45, '空床數': 15, '佔床率': '75.00%'}, | |
| {'病床類別': '精神科病床', '總床數': 80, '佔床數': 65, '空床數': 15, '佔床率': '81.25%'} | |
| ] | |
| return pd.DataFrame(data) | |
| if __name__ == "__main__": | |
| main() |