技術演講現場
在公開技術分享場合向現場會眾介紹雙北景點推薦系統之全鏈路設計架構與演算法
全鏈路系統架構
資料爬取、MySQL 雲端儲存、NLP 推薦引擎至 LINE Webhook 之完整架構流程
LINE 機器人操作流程
三階段行政區篩選、Carousel 輪播卡片推薦,以及地圖導航與文字雲回傳
景點評論文字雲
Jieba 斷詞過濾後生成的景點特色關鍵字文字雲視覺化(以景美集應廟為例)
Webhook 串接架構
使用者訊息觸發 Callback,透過 Webhook 與 Flask 雲端主機進行通訊
專案說明:本專案曾於 2022 年底的公開分享中發表,內容是從網路爬蟲、中文自然語言處理(NLP)、加權評分到 LINE 聊天機器人的完整實作。首圖為當天在講台上講解系統架構的照片;原始程式碼公開於 GitHub。

01 · Background

專案背景與演講實況

假日想出門走走,或者抵達某個景點後想知道「下一站能去哪」,往往面臨資訊過載的痛點。網路上的推薦部落格多半充斥業配或主觀喜好,而 Google Maps 上的評論動輒數百上千則,逐一瀏覽費時費力,更難以快速歸納出該景點的真實口碑與核心特色。

為了解決這個問題,我設計並實作了「雙北旅遊景點推薦系統」:整合自動化評論爬蟲、Jieba 中文斷詞、正負向情緒字典與加權評分演算法,並透過 LINE 官方帳號提供互動式階層查詢與景點關鍵字文字雲。本專案曾於公開技術分享場合進行專題演講,現場拆解從資料工程、演算法設計到雲端服務部署的完整開發鏈路。

技術演講現場:於講台上向會眾拆解爬蟲、NLP 情緒分析與推薦演算法架構
技術演講現場:向會眾講解雙北景點推薦系統架構(資料蒐集、情緒分析、加權推薦與 LINE Bot 串接)

02 · Architecture

全鏈路系統架構

整體系統分為五大核心模組,涵蓋離線資料處理流水線與即時線上回應架構:

雙北景點推薦系統全鏈路系統架構圖
雙北景點推薦系統全鏈路架構:資料爬取、MySQL 儲存、NLP 推薦引擎、Flask 後端與 LINE Bot 串接
1. 資料蒐集與清洗

以雙北景點資料庫為基礎,透過 Google Maps 評論爬蟲定期抓取各景點最新評論,進行標籤過濾與 Emoji 轉文字預處理。

2. 關聯式資料庫

採用雲端 MySQL(ClearDB)儲存景點主檔、評論文本、星等評分、計算後的綜合推薦分數與文字雲圖片連結。

3. NLP 與加權推薦

使用 Jieba 進行中文斷詞,結合自建情緒字典計算情緒得分,並導入 IMDb 加權評分公式抗噪,融合成最終推薦權重。

4. 後端服務與部署

以 Python Flask 開發 Webhook 伺服器,驗證 LINE 數位簽名,並部署於 PaaS 雲端主機(Adaptable.io)。

5. LINE 機器人體驗

提供縣市、區域次群組、行政區三層選單,回傳 Carousel 輪播卡片,附帶 Google Maps 導航連結與動態評論文字雲。

03 · Data & NLP

資料蒐集與自然語言處理

1. Google Maps 評論爬蟲設計

資料源自雙北觀光景點清單。為了掌握景點近期的真實旅客口碑,爬蟲鎖定排序為「最新」的評論,透過 Token 翻頁機制(Next Page Token)批次抓取,每個景點上限設定為 1,700 則評論。在資料採集過程中,設計了隨機 User-Agent 輪替與 0.5~2 秒隨機延遲,降低被目標服務阻擋的風險。

2. 文字清洗與表情符號轉換

Google Maps 評論常包含大量系統介面標籤與非文字雜訊,若直接進行斷詞會嚴重干擾統計:

  • 翻譯標籤分離:過濾 (由 Google 提供翻譯) 與 (原始評論),確保優先保留使用者原始輸入的文字內容。
  • 介面元資料排除:清理「上次造訪時間」、「等待時間」、「建議預訂」、「⋯⋯更多」等系統結構化標記。
  • 表情符號轉換:導入 emoji.demojize,將常見的表情符號轉換為可供 NLP 處理的文字標籤(例如 :sparkles: 或 :thumbs_up:),保留旅客的情緒色彩。

3. Jieba 斷詞與特色文字雲

評論清理完成後,以 jieba 進行中文斷詞,再用 wordcloud 套件為每個景點產生關鍵字文字雲,把評論裡反覆出現的特色(建築、小吃、歷史典故等)濃縮成一張圖。文字雲上傳後以圖片連結存進資料庫,LINE Bot 回覆時直接帶出。

景點評論文字雲範例:景美集應廟之關鍵字分佈
景點評論文字雲產出範例(以景美集應廟為例):清晰萃取古色古香、廟宇、歷史、鮮奶饅頭、景美夜市等關鍵口碑

04 · Algorithm

推薦演算法與評分機制

如果單純依照「Google Maps 平均星等」進行排序,常會產生顯著偏差:一處只有 2 則 5 星評論的新開景點,排名會直接壓過累積 1,500 則評論且平均 4.7 星的成熟經典景點。這在推薦系統中屬於典型的「小樣本極端值偏誤」。

1. 星等加權評分(Weighted Rating, WR)

為了解決評分樣本不均的問題,星等部分採用 IMDb 式的加權評分公式:

WR = [ v / (v + m) ] × R + [ m / (v + m) ] × C
  • v:該景點的評論數。
  • m:進入排名所需的最低評論數門檻。
  • R:該景點的平均星等。
  • C:全體景點的平均星等。

評論數 v 少的時候,分數會被拉向全體平均 C;評論數遠超過門檻 m 之後,景點自己的平均星等 R 才會主導分數,少數極端評價就不容易把排名帶偏。

2. 情緒分析與綜合得分

星等之外,評論文字的語氣也反映遊客滿意度。情緒分析使用台大自然語言處理的正負向字典,對斷詞後的評論計分;最後把情緒分析分數與星等評價分數加權相加,得到排序用的綜合分數(資料庫欄位 result_avg):

Final Score = 情緒分析分數 × 1 + 星等評價分數 × 0.67

這樣排序同時看「大家給幾顆星」和「評論實際怎麼說」,LINE Bot 查詢時直接依這個分數排序。

05 · LINE Bot

LINE 機器人互動與成果展示

1. Webhook 雙向通訊架構

使用者在 LINE App 傳送文字指令時,LINE 平台會發出 HTTPS POST 請求至後端伺服器的 /callback 路由。Flask 後端首先藉由 X-Line-Signature 檢查請求的數位簽名是否合法,再由 WebhookHandler 將訊息派發給對應的處理函數,從 MySQL 查詢資料後透過 LINE Messaging API 封裝為範本訊息回傳。

LINE Bot Webhook 通訊架構說明
LINE Bot Webhook 通訊架構:使用者傳訊、LINE Platform 轉發、Flask 後端處理與 API 回覆

2. 三階層式探索選單與防僵化機制

雙北行政區數量龐大,若一次列出幾十個行政區會大幅增加使用者認知負擔。系統設計了三種不同粒度的探索路徑:

  1. 直選縣市推薦:使用者直接點擊「臺北市」或「新北市」,系統自該縣市排序前 5% 的最高分景點中隨機抽取 6 處,呈現雙北頂級推薦。
  2. 跨區生活圈次分組:將地理相鄰的行政區合併為群組(例如「士林、大同區」或「五股、泰山、新莊、蘆洲、三重區」),方便以區域生活圈為導向的探索。
  3. 精準行政區推薦:下鑽至特定行政區(如士林區),系統由該區綜合得分排名前 50% 的景點中篩選 3 筆呈現。

為了避免使用者每次點選同一個區域都看到一模一樣的景點,後端在取得 Top 景點集合後會進行隨機抽樣(Random Shuffle),既維持了高推薦品質,又具備探索新景點的驚喜感。

3. 互動展示與圖文回傳成果

使用者選定具體景點後,聊天機器人會立即回傳包含景點名稱、Google Maps 導航短網址,以及一目了然的評論特色文字雲圖片。旅客無須逐篇翻閱幾百則評論,即可在手機畫面上秒懂該景點好玩在哪、必看重點與注意事項。

LINE 機器人操作截圖:從行政區篩選、輪播卡片到文字雲即時回覆
LINE Bot 完整操作流程:生活圈選擇(左)、行政區景點輪播卡片(中)、景點連結與文字雲回傳(右)
LINE 機器人互動實錄 GIF
LINE 機器人實機操作動畫展示:點選「士林區」後推薦「林語堂故居」,即時獲取導航與文字雲

06 · Retrospective

系統限制與後續改進方向

  • 免費 PaaS 平台的冷啟動:免費雲端主機閒置一段時間後會休眠,使用者在休眠期間傳訊息,第一次回應會明顯變慢。後續可改用常駐主機,或定時喚醒服務。
  • 離線批次爬蟲的時效維護:目前的評分與文字雲為單次批次運算後寫入資料庫,尚缺乏自動化的定期增量排程機制。未來可結合每週排程爬取最新評價,使文字雲與情緒評分隨季節動態更新。
  • 多維度推薦特徵擴充:目前推薦主要依賴地理區域、星等與情緒分數。若能進一步結合停留時間標籤、室內/戶外屬性、即時天氣 API 與使用者個人化偏好標籤,推薦精準度將能更進一步提升。

本專案完整原始碼與 Colab 爬蟲腳本已整理公開於 GitHub:jelink27/Tourist-attraction-recommender-system。