先跟各位說聲抱歉,昨天那篇實在太混了Q
我之後會將完整的 Rich Menus 內容都統整到昨天那篇裡
今天我們會開始我們的專案 - 口罩查詢系統
這個專案的開發時間會比較長,我將內容大致分成幾個部分
在這次的專案當中,我會大量使用到 try-except
以及 function 加強程式碼的可讀性以及容錯率
程式碼大多是參考過去我開發的專案內容進行修改
我們的專案簡單來說是使用者傳送位置訊息,我們會回覆該地點半徑1公里內的藥局資訊
而我們的訊息會是以 Flex Message 傳送
為了要計算距離,我們還需要藥局的座標資料
所以我們需要先處理好各家藥局的座標資料
這部分有人有統整好的資料集
接下來是要收到藥局口罩的剩餘數量
這部分會使用政府提供的口罩資料
最後是回傳的內容,我們會要設計 Flex Message 的版型
其中需要有藥局的資料,最下方需要有一個按鈕,回傳該藥局的位置資料
資料的部分,我們會把資料以及副程式都分開放,架構如下
congfig.yml
是存放 Channel Access Token
和 Channel Secret
的檔案
規劃大致就到這邊,接下來就要開始實作囉
這邊參考了 Kiang 大大整理的資料,我們先將檔案下載下來
這裡提供兩種下載方式
view raw
的字樣,對它點右鍵後選擇 另存連結為...
.csv
wget https://github.com/kiang/pharmacies/blob/master/data.csv
如果你們也遇到亂碼問題,這裡提供兩個解決方式
- 如果你是使用 windows 系統,可以改以記事本開啟
再來點擊另存為...
,編碼方式改為UTF-8
![]()
- 以 Excel 開啟,在上方的
資料
,找到在取得外部資料
的從文字檔
選擇剛剛下載的檔案
將原始檔案格式
改成UTF-8
分隔符號勾選逗點
成功~![]()
觀察一下資料之後會發現到裏面包含了很多種資料,但是我們只需要其中幾個
所以接下來我們要對這些資料做處理,只留下我們需要的資料
另外,我們要將它改成 JSON 的格式,方便之後存取資料
我們先在資料夾放好剛剛轉成 UTF-8 格式的 csv 檔,取名為 data
最後要將結果輸出到 positions.json
我希望輸出的格式如下:
{
"醫事機構代碼":{
"name" : "藥局名稱"
"phone" : "藥局電話"
"address" : "藥局地址"
"經度" : "藥局經度"
"緯度" : "藥局緯度"
},
...
}
程式碼如下
import csv,json
with open('data.csv','r',newline='') as f:
data = csv.reader(f)
output = open('positions.json','w')
arr = {}
for i in data:
arr[i[0]] = {}
arr[i[0]]['name']=i[1]
arr[i[0]]['phone']=i[3]
arr[i[0]]['address']=i[4]
arr[i[0]]['lng']=i[12]
arr[i[0]]['lat']=i[13]
output.write(json.dumps(arr,indent=4,ensure_ascii=False))
output.close()
口罩資料我們會使用政府提供的口罩資料集
這裡我們要製作兩個檔案
第一個是口罩資料集
另一個是將口罩資料以及藥局座標彙整起來的檔案
口罩資料是會不定時更新的資料集,為了確保獲取的資料是當前最新資料
我們會寫一個 python 去做更新
而更新也不是每次都要做,我設定每 30 分鐘一個區間,如果此次更新時間比上次多 30 分鐘以上,那就必須要更新資料了
update.py
import datetime,csv,json,requests,os
from logger import logger
from add_pos import add_pos
data_folder = str(os.getcwd()) + '/data/'
def update():
position_out = open(data_folder + 'csv/positions.csv','r',newline='')
nowtime = datetime.datetime.now()
pasttime = datetime.datetime.strptime(list(csv.reader(position_out))[0][6],'%Y/%m/%d %H:%M:%S')
minutes = datetime.timedelta(minutes=30)
if(nowtime-pasttime >= minutes):
# download maskdata.csv
logger.info('========== downloading ==========')
url = 'https://data.nhi.gov.tw/resource/mask/maskdata.csv'
request_data = requests.get(url).content.decode('utf-8')
# update maskdata.csv
try:
with open(data_folder + 'csv/maskdata.csv','w') as maskdata:
logger.info('open maskdata.csv => Success')
maskdata.write(request_data)
logger.info('========== Download Success ==========')
except:
logger.warning('open maskdata.csv => Failed')
logger.warning('========== Download Failed ==========')
return False
# update positions.csv
res = add_pos()
if(res == True):
logger.info('create positions.csv => Success')
return True
else:
logger.warning('create positions.csv => Failed')
return False
時間處理的部分使用了 datetime
這個套件處理
logger 的部分目前還不會細講,功能是為了要方便 debug
它會產出 log.log
檔案,將我們所紀錄的內容都寫在裡面
特別注意到,我們在找資料位置會為了要在任何環境下都能順利操作,所以會以
os.getcwd()
再加上相對路徑的方式處理
另外,也可以發現到在開啟檔案我都會另外寫 log 紀錄
日後如果是檔案出問題就可以第一時間找到囉~
接下來要將下載的資料以及前面產出的 positions.json
資料結合成一份 csv
add_pos.py
import csv,json,os
from logger import logger
data_folder = str(os.getcwd()) + '/data/'
def add_pos():
# read maskdata
try:
maskdata = open(data_folder + 'csv/maskdata.csv','r',newline='')
logger.info('open maskdata.csv => Success')
except:
logger.warning('open maskdata.csv => Failed')
return False
# read dict table
try:
pos_data = open(data_folder + 'json/positions.json','r',newline='')
logger.info('open positions.json => Success')
except:
logger.warning('open positions.json => Failed')
return False
# update positions
try:
out = open(data_folder + 'csv/positions.csv','w')
logger.info('open positions.csv => Success')
except:
logger.warning('open positions.csv => Failed')
return False
sheets = csv.reader(maskdata)
pos = json.load(pos_data)
writer = csv.writer(out)
for sheet in sheets:
arr = sheet
try:
lat = pos[sheet[0]]['lat']
lng = pos[sheet[0]]['lng']
except KeyError:
logger.warning('[add_pos] KeyError in line ' + str(sheet[0]))
continue
arr.append(lat)
arr.append(lng)
writer.writerow(arr)
return True
到目前為止,關於資料處理的部分大致就完成了
在下一篇我們會繼續將後續的部分完成
這次的實作內容如果完整自行實做起來可能會需要花到一整天的時間
在其中其實會遇到很多中文轉碼的問題
還有在 JSON, CSV 檔案會出現很多疑惑
我也翻了很多資料ww
希望大家能玩得開心拉~
HackMD 口罩供需資料平台
Kiang pharmacy資料
健康保險資料開放服務
CSDN python3 讀取csv問題
Koios1143 Chat Bot
口罩查詢系統 Github