(文章)

跨部會活動的資料整合:調查表合併、場域去重與編號設計

從規劃到開發完成不到 2 個月。同一份 15 欄表頭收表,腳本合併場域並統一編號,匯入前逐列驗證,前台取用同一份資料。

磨人開發團隊・2026-10-20

目錄

2026 全臺戶外教育季是 22 週的跨部會網頁活動,從規劃、設計到開發完成不到 2 個月。教育部攜手文化部、內政部國家公園署、農業部林業及自然保育署、環境部、經濟部、客家委員會、交通部觀光署、海洋委員會與原住民族委員會共同推出,另有民間團體參與。各單位以同一份 15 欄的調查表提供課程,共 11 張工作表。開發團隊用 Python 腳本把這些工作表整理成場域、課程、角色與問答四張表,再由 Node.js 匯入腳本逐列驗證後寫進資料庫。整理完成的資料有 187 個場域、476 堂課程與 1,056 題問答,互動地圖、課程列表、角色卡片與公告取用同一組編號。

整體的建置範圍見活動平台與後台,獎勵與帳務見有獎活動平台的帳務、防刷與預算控管。

圖 1調查表經整理與逐列驗證後匯入,前台與對外文件取用同一份資料

10 個部會與民間團體

  • 11 張工作表同一份 15 欄表頭
15 欄調查表

開發團隊

  • Python 整理腳本欄位對照、場域合併、日期解析、編號排序
  • 總表四張工作表場域、課程、角色、問答
  • Node.js 匯入腳本第一輪驗證,第二輪寫入
場域編號、課程編號與整理後的欄位

活動網站與對外文件

  • 互動地圖與課程列表依範圍、縣市、月份、星期、主題與部會查詢
  • 角色卡片依總表批次輸出
  • 公告與分享內文沿用同一組名稱與數字

只在總表改一次場域名稱、課程時間等內容改在源頭,重跑腳本後,地圖、課程列表與卡片取用更新後的資料。

範圍:活動期間用到的場域、課程、角色、問答與公告資料

調查表的合併與欄位對照

調查表的 15 欄含課程名稱、辦理地點、地圖地址、類型、簡介、活動時間、收費、報名窗口、主管機關、辦理單位與推薦亮點。腳本以 pandas 逐張讀取,只取前 15 欄,欄名去除換行後以關鍵字(例如 google、簡介、推薦亮點)對成固定的內部欄名,記下每列來自哪一張工作表,再合併成一個資料表,範例列與重複的表頭列同時移除。

原欄位總表欄位整理規則
課程名稱課程名稱、課程編號去除換行與空白,以名稱對上配對表取得課程編號
辦理地點、地圖地址場域名稱、地址、Google Map 連結統一寫法後建立場域,見下一節;連結由地址組成查詢網址
類型課程分類二十多種填寫選項對照成 8 類,生態環境最多,有 186 堂
活動時間起始日、結束日、每週開放星期、時間備註依規則解析,見活動時間一節
報名窗口報名方式含網址標為報名連結,只有信箱標為聯繫信箱,含電話標為聯繫電話
簡介、類型標籤以關鍵字對照表比對名稱、簡介與類型,沒有命中時以分類作標籤

合併後拆成場域與課程兩張表:場域表一列一個場域,課程表一列一堂課,匯入時課程以場域編號對上所屬場域。這是Wickham,2014整理的結構,每個變數一欄、每筆觀察一列、每種觀察單位一張表。地址、區域與歸屬單位只寫在場域表,場域有多堂課時,地址也只有一份。

成員把一張張卡片歸進大櫃子的抽屜

場域的比對與合併

辦理地點先做正規化:去掉括號內的備註;全形逗號轉半形,連續空白併成一個;「臺」統一寫成「台」以便比對,地址在匯入時再統一為「臺」。正規化後的名稱是場域的鍵,名稱相同視為同一個場域,地址取第一筆有值的。

場域去重屬於重複紀錄偵測。Elmagarmid 等,2007指出,同一個實體在資料庫中常有兩種以上的表示方式,重複的紀錄之間沒有共同的鍵。調查表沒有共同的場域編號,編號由比對規則建立:一張 31 筆的合併對照表,把同棟或同園區的樓層、廳室、步道與不同寫法併入主場域;一張 18 筆的多地點對照表,把列出多個地點的課程歸入主場域,備註寫成「場地:含…」。

桌機螢幕錄影:由全臺縮放至單一場域,滑過場域顯示名稱。
圖 2每筆課程的辦理地點依三種規則歸入場域
  1. 讀取辦理地點來自各單位的調查表
  2. 正規化去括號備註、全形轉半形、臺統一為台
  • 同棟或同園區的樓層、廳室、步道
    併入主場域子地點寫進課程備註,格式「場地:…」
  • 一堂課列出多個地點
    歸入主場域備註寫明另含哪些地點
  • 不同物理位置
    各自保留為場域

地址另做標準化:取出括號中含縣市與門牌的正式地址,移除地圖網址,國字門牌改為阿拉伯數字(例如五號改為 5 號),Google Map 連結由整理後的地址組成。區域分北、中、南、東、離島五區,取自課程配對表;沒有對應時依地址判斷,比對順序是離島、北部、中部、南部、東部的縣市名稱。

每個場域另有 GPS 驗證範圍欄。座標先查人工座標表,其餘以地址(查不到時改用場域名稱)呼叫 Nominatim 地理編碼,請求間隔 1.1 秒,結果須落在緯度 21 至 27、經度 118 至 123 之內,再依場域類型換算成矩形範圍,187 個場域全部帶有驗證範圍。到場驗證以場域座標計算與使用者的距離。

歸屬單位(主管機關)由場域出現在哪一張調查表工作表判定:每張工作表對應一個正式單位名稱,場域名稱依手動指定、完全相符、包含關係、前四個字的順序比對,出現在兩張以上時由人工依課程數與相關程度決定。寫入後腳本驗證其餘欄位沒有被動到,歸屬彙總表的場域數與場域表一致。

下表是整理後的歸屬彙總。同樣算一個場域,可能是一間觀光工廠,也可能是一座國家公園,驗證範圍因此依場域類型換算。

主管機關場域類型數量
經濟部觀光工廠、產業園區56
交通部觀光署風景區、旅遊服務中心37
內政部國家公園署國家公園、自然保護區30
文化部古蹟、博物館、文化園區24
環境部環境教育設施場所17
農業部林業及自然保育署森林遊樂區、自然教育中心10
教育部科學館所、園區、社區6
海洋委員會海洋教育場域3
客家委員會客家文化園區2
原住民族委員會原住民族文化園區1
民間團體食魚體驗館1
合計11 張工作表187

活動時間的解析

活動時間在調查表是一格文字,腳本依下表的寫法判讀,星期與日期範圍各自解析,日期一律限制在 4 月 1 日至 8 月 31 日之間。

調查表的寫法解析結果
星期,例如每週六、日,或平日、假日寫入每週開放星期,1 至 7 代表週一至週日;平日為 1 至 5,假日為 6 與 7
月份區間,例如 4-8 月起日為首月 1 日,迄日為末月最後一日,括號內說明寫入時間備註
單一月份該月 1 日至月底
月/日的具體日期取最早與最晚的日期為起訖,多日活動的原文寫入時間備註
含預約、申請或團體的描述整個活動期間開放,原文寫入時間備註
其餘文字有 4 至 8 月的月份就取該範圍,否則整個活動期間開放,原文前 50 字寫入時間備註

起訖日與星期在匯入時分別存成日期與 JSON 陣列。前台的月份篩選以起訖日區間是否與所選月份重疊判斷,星期篩選以陣列是否包含所選星期判斷,都在伺服器查詢時完成。

編號與排序

課程編號由區域碼、水陸碼與序號組成,例如 N-W-01 表示北部、水域的第 1 號。區域碼 N、C、S、E、I 依序是北、中、南、東與離島;水陸碼 W 與 L 是水域與陸域,由課程名稱、簡介、類型與地點中的水域關鍵字判斷,命中任一個為 W,其餘為 L。排序固定為區域、水陸、序號,最後是進化等級 Lv1 至 Lv3,排序腳本把每列轉成四個數字的排序鍵,排完逐列檢查沒有倒退。

課程表、配對表、角色表與問答表都以這個編號對應:匯入角色時依課程編號找到課程與場域,匯入問答時依編號找到角色。問答題同樣掛在角色編號之下。編號各段與角色圖的對應,見大型活動的角色系統怎麼設計。

角色圖鑑:圖鑑頁說明三個階段,下方的卡片標出角色名稱與等級。
角色圖鑑:圖鑑頁說明三個階段,下方的卡片標出角色名稱與等級。

角色表記的是場域編號,卡片上的場域名稱在輸出時才由場域表取得,場域改名只需改一處。W3C 的網路資料最佳實務建議資料集內的項目以持久的 URI 作為識別碼,才能和其餘資料集中關於同一個地方、人或事件的資料相連。這裡用的是活動內部編號,沒有網址形式,原則相同:同一堂課、同一個場域,在每張表裡用同一個識別碼對應。

重點課程與週曆

調查表最後一欄讓各單位標出推薦亮點,這一欄是重點課程的選取依據。腳本先依各區域的課程數比例分配名額,每區至少一個,再從該區候選課程中逐一選出得分最高者:推薦亮點先加分,再依場域、類型與來源單位的分布調整分數,使重點課程分散在不同的場域、主題與單位。

選出的課程標記寫回配對表,對應角色的稀有度一律設為最高。排程另存為週曆,每列記錄課程、來源單位、角色編號、開放日期、結束日期與開放週次。後端以日期區間加課程編號清單保存週曆,前台請求本週重點課程時,伺服器依臺灣時區的當日找出所在區間,回傳該週課程與對應角色。每週節奏與抽獎的配合見22 週活動的參與節奏。

公告與分享內文

活動橫跨 22 週,公告在開跑前先排成一份總覽,共約 37 則,每則寫好發布日期與管道,需依實際數據替換的欄位用紅色標出。

類別則數發布時機
活動前公告1開跑前預告
里程碑公告6開跑、首批重點課程開放、暑假特別企劃、排名中期、最終倒數、活動結束
每週抽獎結果21第 2 週至第 22 週,每週五晚間 9 點前發布
月抽加碼預告5四月至八月各一則,結果併入每週抽獎結果
領獎與行政4領獎流程、排名審核、總排名結果、未領獎催領
活動結束版的排行榜:戰力榜與能量榜,依名次區間列出獎品,與領獎、排名審核等行政公告對應。
活動結束版的排行榜:戰力榜與能量榜,依名次區間列出獎品,與領獎、排名審核等行政公告對應。

各單位協助轉載的內文也先寫好:基底是固定結構的活動說明,依序為活動資訊、活動亮點、獎品、參加步驟與聯絡資訊,再依官網、電子報、社群貼文等管道改寫成不同版本。每個部會另有一則專屬貼文,開頭寫該部會的場域數與類型,例如內政部國家公園署是 30 個國家公園與自然保護區場域,農業部林業及自然保育署是 10 個森林遊樂區與自然教育中心場域,數字與歸屬彙總表一致。對外一律寫 180 多個場域、470 多堂課,各單位轉載時出現的就是同一組數字。

匯入前的逐列驗證

總表分為場域、課程、角色、問答四張工作表,依這個順序由 Node.js 腳本匯入,後一張以前一張的編號對應。每支匯入腳本分兩輪:第一輪逐列驗證並蒐集全部錯誤,任何一列不合格就整批中止並列出列號與原因;全部通過才進入第二輪逐列寫入,因此驗證失敗時資料庫不會有任何一列被寫入。

圖 3匯入分兩輪,任何一列驗證失敗就整批不寫入
  1. 讀取工作表依欄位順序轉成記錄
  2. 第一輪:逐列驗證蒐集全部錯誤,不在第一個錯誤就停止
  • 全部通過
    第二輪:逐列寫入同時填入建立時間與狀態欄
  • 任一列不合格
    整批中止列出列號與原因,資料庫維持原狀
工作表第一輪的檢查與處理
場域編號、名稱、地址、地圖連結、區域、歸屬單位與驗證範圍必填;區域須為五區之一;編號不重複;地址須解析出縣市與行政區
課程編號、所屬場域編號、名稱、分類與說明必填;場域編號須已存在;編號不重複;日期轉為 YYYY-MM-DD;星期與標籤轉為 JSON 陣列
角色課程編號、名稱與三段對話必填;稀有度與各階段數值須為 0 以上的整數;依課程編號關聯課程與場域
問答角色編號須已存在;等級只能是 1 或 2;答案只能是 A、B、C;同一角色與等級不重複

資料異動與前台的查詢方式

腳本都可以重跑:讀原始工作表,寫出總表,並逐筆檢查課程的場域存在於場域表、起訖日落在 4 月 1 日至 8 月 31 日、每堂課都有編號與標籤,列出不通過的項目。批次異動改在總表並重跑腳本,個別欄位則在後台逐筆編輯,每次編輯都記錄操作者與變更內容。

地圖依畫面範圍的四個角座標查詢場域,同時帶回場域內的課程與角色。篩選條件有縣市(含鄉鎮市區)、月份、星期、主題與部會,關鍵字搜尋涵蓋場域名、課程名、簡介、標籤與歸屬單位。課程是否在開放期間由伺服器依臺灣時區的當日判斷,尚未開始的標示為即將開放。

手機螢幕錄影:縮放與拖曳互動地圖。

角色卡片由 Playwright 啟動的無頭瀏覽器依總表逐張輸出,檔名由角色編號與等級組成,課程資料更新後重新輸出。活動結束後畫面自動換成結束版,地圖與圖鑑仍開放瀏覽。這類可重複產出的整理與檢查如何成為公部門專案的驗收證據,見公部門專案的交付與維運證據。

活動結束版首頁。互動地圖、角色圖鑑與最終排名仍開放瀏覽。
活動結束版首頁。互動地圖、角色圖鑑與最終排名仍開放瀏覽。

不適合的情況

  • 只有單一單位、課程在幾十筆以內:試算表加人工核對即可。
  • 內容必須逐字照原樣呈現,例如法規條文或公告原文:整理規則會統一寫法,這類內容不適用。
  • 活動沒有地圖,也不做到場驗證:場域合併與座標整理可以大幅簡化,表頭與編號仍然需要。

開始前要準備什麼

需要備好的有五項:參與單位名單與窗口、要統一的表頭欄位、活動期間與各單位想推的重點課程、地圖是否需要到場驗證、對外文案的數字口徑。備齊之後,可以討論跨單位活動的資料與平台規劃。

(聯絡)

Start a project.

三個步驟,取得可判斷的做法與預算區間。

  1. 01預約第一場會議:選擇時段,不需要完整規格。
  2. 02線上諮詢 15 至 30 分鐘:取得做法方向、預算區間與時程草案。
  3. 03檢視素材後,約 3 至 5 個工作天提供報價單暨交付規格明細表。
信箱
hello@polish-design.com.tw
通訊地址
(104) 台北市中山區植福路191-1號3F

預約第一場會議

週一至週五 16:00–18:00線上 30 分鐘

先選時段,再用 Google 帳號或信箱確認,預約完成可加入行事曆。

選擇時段

或先送出資料

還沒想好時段,可以先留下專案內容,專人以信箱回覆。送出後也能接著預約。

補充資料(選填):服務項目、目前階段、現有連結、得知管道

資料僅用於本次專案評估。

ISO/IEC 27001:2022 證書

(Certificate)

ISO/IEC 27001:2022

驗證機構
ARES International Certification
驗證範圍
互動沉浸式 3D 系統之開發流程,及網路與基礎設施之維運與管理。

到驗證機構網站查證