File size: 5,846 Bytes
1d21670
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
import streamlit as st
import requests
from bs4 import BeautifulSoup
import pandas as pd
import plotly.express as px

# 定義爬取數據的函數
def fetch_data(hospital_url, table_id, hospital_name):
    response = requests.get(hospital_url)
    soup = BeautifulSoup(response.text, 'html.parser')
    table = soup.find('table', {'id': table_id})
    if not table:
        return pd.DataFrame()  # 若表格未找到,返回空的DataFrame
    
    rows = table.find_all('tr')
    data = []
    
    if hospital_name == "成大醫院":
        columns = [th.text.strip() for th in rows[0].find_all("th")]
        columns = ['病床種類' if col == '病床類別' else col for col in columns]
        data_rows = rows[1:]
        for row in data_rows:
            row_data = [td.text.strip() for td in row.find_all("td")]
            if all(row_data):
                data.append(row_data)
    else:
        columns = ['病床種類', '病床數', '住院人數', '空床數', '佔床率']
        for row in rows[1:]:
            cols = row.find_all('td')
            if len(cols) == 5:
                row_data = [col.get_text(strip=True) for col in cols]
                if all(row_data):
                    data.append(row_data)
    
    df = pd.DataFrame(data, columns=columns)
    
    if '病床數' not in df.columns and '開放床數' in df.columns:
        df = df.rename(columns={'開放床數': '病床數'})
    
    return df

# Streamlit UI
st.title("醫院床位分配表爬取工具")

# 下拉式選單選擇醫院
hospital_options = {
    "台南醫院": {
        "url": "https://www.tmh.org.tw/tmh2016/ImpBD.aspx?Kind=2",
        "table_id": "ctl00_ContentPlaceHolder1_GV_Bed"
    },
    "奇美醫院": {
        "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=",
        "table_id": "DG1"
    },
    "成大醫院": {
        "url": "https://web.hosp.ncku.edu.tw/nckm/Bedstatus/BedStatus.aspx",
        "table_id": "GV_EmgInsure"
    }
}

selected_hospitals = st.multiselect("選擇醫院", list(hospital_options.keys()))

# 手動輸入收件人的電子郵件地址
to_addr_list = []
email_input = st.text_input("請輸入收件人的電子郵件地址,使用逗號分隔多個地址")

if email_input:
    to_addr_list = [email.strip() for email in email_input.split(",")]

# 當用戶按下按鈕時,開始爬取數據
if st.button("爬取資料並發送郵件"):
    st.write("正在爬取資料...")
    all_data = pd.DataFrame()

    for hospital_name in selected_hospitals:
        hospital_data = hospital_options[hospital_name]
        df = fetch_data(hospital_data["url"], hospital_data["table_id"], hospital_name)
        if df.empty:
            st.warning(f"{hospital_name} 的數據爬取結果為空,請檢查是否存在問題。")
        else:
            df['醫院'] = hospital_name
            all_data = pd.concat([all_data, df], ignore_index=True)

    if not all_data.empty:
        st.write("爬取完成,合併的數據如下:")
        st.dataframe(all_data)

        # 繪製圖表
        st.write("正在繪製圖表...")
        bed_column = '病床數'
        all_data[bed_column] = pd.to_numeric(all_data[bed_column], errors='coerce')
        bed_counts = all_data.groupby(['醫院', '病床種類'])[bed_column].sum().reset_index()

        # 圓餅圖
        fig_pie = px.pie(bed_counts, values=bed_column, names='病床種類', title='各類型病床分佈',
                         hover_data=['醫院'], labels={bed_column: '病床數'})
        st.plotly_chart(fig_pie)

        # 保存圓餅圖為文件
        fig_pie.write_image("pie_chart.png")

        # 柱狀圖
        fig_bar = px.bar(bed_counts, x='醫院', y=bed_column, color='病床種類', title='醫院病床分佈',
                         labels={bed_column: '病床數'}, barmode='group')
        st.plotly_chart(fig_bar)

        # 保存柱狀圖為文件
        fig_bar.write_image("bar_chart.png")

        # 格式化數據為電子郵件內容
        email_body = "以下為最新醫院床位分配數據:\n\n"
        email_body += all_data.to_string(index=False)

        # 構建郵件
        msg = MIMEMultipart()
        msg['Subject'] = '會員通知'
        msg['From'] = '[email protected]'
        msg['To'] = ', '.join(to_addr_list)
        
        # 添加文本內容
        msg.attach(MIMEText(email_body, 'plain', 'utf-8'))

        # 添加圖表圖片
        for image_path in ['pie_chart.png', 'bar_chart.png']:
            with open(image_path, 'rb') as img_file:
                img = MIMEImage(img_file.read())
                img.add_header('Content-Disposition', f'attachment; filename="{image_path}"')
                msg.attach(img)

        # 發送郵件給所有輸入的收件人
        if to_addr_list:
            st.write("正在發送郵件...")
            smtp_server = 'smtp.gmail.com'
            smtp_port = 587
            from_addr = '[email protected]'
            pwd = 'hedm elps tksg'
            
            mySMTP = smtplib.SMTP(smtp_server, smtp_port)
            mySMTP.ehlo()
            mySMTP.starttls()
            mySMTP.login(from_addr, pwd)
            
            try:
                mySMTP.sendmail(from_addr, to_addr_list, msg.as_string())
                st.success("成功發送郵件")
            except Exception as e:
                st.error(f"發送郵件失敗: {e}")
            
            mySMTP.quit()
        else:
            st.warning("請輸入至少一個有效的電子郵件地址。")

    else:
        st.error("沒有成功爬取任何數據。")