起因
因為最近後背靠近腰部的部分總是癢癢的,於是掛號關渡醫院晚診看皮膚科,掛到了37號 該晚不晚該早不早
想說先去吃個飯,再去醫院,但又怕吃太久導致過號,又要等看過兩三個人才能看醫生
於是想說做一個定時去爬看診進度的推播,來追蹤提醒自己現在看到幾號了
使用套件
新增一個檔案
requirements.txt
內容為
requests==2.32.3
beautifulsoup4==4.12.3
然後開啟cmd
pip install -r requirements.txt
python 驗證
from datetime import datetime, timedelta
import requests
from bs4 import BeautifulSoup
# 定義爬取資料的函式
def fetch_doctor_status():
url = "https://www.gandau.gov.tw/IdxGp3/webreg/%E9%96%80%E8%A8%BA%E6%99%82%E5%88%BB%E8%A1%A8/QrySeeStat.asp?DocN=08" # 替換為實際 API 的 URL
response = requests.get(url)
if response.status_code == 200:
response.encoding = 'utf-8'
print(f"response:{response.text}")
soup = BeautifulSoup(response.text, "html.parser")
print(f"soup: {soup}")
# 找到 "李政源" 的燈號資料
rows = soup.find_all("tr", bgcolor="#E2FFA6")
for row in rows:
cells = row.find_all("td")
if "李政源" in cells[1].text:
status = cells[2].text.strip() # 燈號狀態
print(f"李政源醫生目前看到的號碼: {status}")
return status
else:
print("無法取得資料,請檢查 API 狀態")
return None
if __name__ == "__main__":
records = fetch_doctor_status()
print(f"records:{records}")
result
李政源醫生目前看到的號碼: 0
airflow 串接
from airflow import DAG
from airflow.operators.python import PythonOperator
from datetime import datetime, timedelta
import requests
from bs4 import BeautifulSoup
from airflow.timetables.trigger import CronTriggerTimetable
# 定義 Discord Webhook 的函式
def send_to_discord(message):
webhook_url = "{{放入你自己的 discord webhook url }}"
payload = {"content": message}
response = requests.post(webhook_url, json=payload)
if response.status_code == 204: # Discord Webhook 成功回應
print("訊息成功發送到 Discord")
else:
print(f"無法發送訊息到 Discord,HTTP 狀態碼: {response.status_code}, 回應: {response.text}")
# 定義爬取資料的函式
def fetch_doctor_status():
url = "https://www.gandau.gov.tw/IdxGp3/webreg/%E9%96%80%E8%A8%BA%E6%99%82%E5%88%BB%E8%A1%A8/QrySeeStat.asp?DocN=08" # 替換為實際 API 的 URL
response = requests.get(url)
response.encoding = 'utf-8'
if response.status_code == 200:
soup = BeautifulSoup(response.text, "html.parser")
# 找到 "李政源" 的燈號資料
rows = soup.find_all("tr", bgcolor="#E2FFA6")
for row in rows:
cells = row.find_all("td")
if "李政源" in cells[1].text:
status = cells[2].text.strip() # 燈號狀態
message = f"李政源醫生目前看到的號碼: {status}"
print(message)
send_to_discord(message)
print(f"李政源醫生目前看到的號碼: {status}")
return status
else:
print("無法取得資料,請檢查 API 狀態")
return None
# 定義 Airflow DAG
default_args = {
'owner': 'airflow',
'depends_on_past': False,
'email_on_failure': False,
'email_on_retry': False,
'retries': 1,
'retry_delay': timedelta(minutes=5),
}
with DAG(
'fetch_doctor_status',
default_args=default_args,
description='Fetch doctor status every minute',
schedule=CronTriggerTimetable(
cron="*/1 17-20 * * *", #
timezone="Asia/Taipei", # 指定時區為台北(UTC+8)
),
start_date=datetime(2025, 1, 22),
end_date=datetime(2025, 1, 22, 20, 30), # 設置結束日期和時間
catchup=False,
tags=['web scraping', 'doctor status'],
) as dag:
task_fetch_status = PythonOperator(
task_id='fetch_doctor_status',
python_callable=fetch_doctor_status,
)
歷程
因為 1800 醫生才開始營業 於是選定 1800-2000 來做 推送
但有問題是 2010 還是一直在收到推送
才發現 原來這樣的設定是指 1800-2059 ~
discord 也不是每一則都會發推播 如果每兩分鐘抓一次的推送 和上一次一樣 他可能就不會推播了
編碼問題
一開始 api 回來都亂碼
查了才知道
要加
response.encoding = 'utf-8'
才會正常
思考
邊吃飯邊想 就算我在吃飯 過號了我還是來不及
假設我是 30 號 今天看診共60號
但如果前面 15號 叫號碼時都 no show 且 是跟我一樣時間到達醫院補報到呢?
不是還是來不及 或是還是要等