楊本顥筆記・知識・作品

首頁 / 作品 / pchome-momo

個人專案 · 從課堂範例延伸重寫 01 / TL;DR

跨平台商品比價

找出 PChome 與 momo 上的同款商品,把不同名稱整理成可比較的品項,再查看價差與價格歷史。

Python · FlaskMySQLRapidFuzzDockerGitHub Actions
GitHub 原始碼 ↗ 看架構流程 ↓操作影片位置 ↓
跨平台商品比價的主題示意插畫
專案主題示意圖 · 非實際操作畫面

起點與改寫範圍

早期雙站爬取來自課堂範例。這個版本重新整理資料層、配對流程、價差介面與驗證方式,把重點放回「是不是同一件商品」。

操作影片

跟著畫面走一遍

輸入關鍵字、查看跨平台配對,再比較價差與歷史價格。

操作影片準備中

錄製完成後會放在這裡。

02 / WHY

兩堆商品資料,還不是一張比價表

早期結果把兩邊商品畫成散點圖,但點重疊在一起,仍然很難回答某一件商品在哪裡便宜。畫出資料之後,真正的比價問題還沒解決。

因此重寫時,我把同款商品的辨識放在核心。目標是讓想比較價格的人先確認品項,再看價差,不必自己在兩份長清單中來回找。

品項要相同
品牌、型號與規格要能對得上。
差異要可讀
以可排序的價差表取代難以辨識的散點。
價格有時間
保存觀測歷史,避免只看單次抓取的價格。
03 / ARCHITECTURE & CHOICES

架構與技術選型

從輸入到結果

由上往下沿藍色箭頭閱讀,右側是各階段的工作。小螢幕可在圖內左右滑動。

跨平台商品比價架構流程關鍵字與抓取工作 → 欄位正規化 → MySQL 商品與價格 → 配對與結果保存 → Flask 比價介面01關鍵字與抓取工作分別收集兩個平台的商品02欄位正規化整理價格、網址、品牌及型號03MySQL 商品與價格正規化結果先寫入商品及價格歷史04配對與結果保存分桶、評分、分組後保存配對05Flask 比價介面查看可排序價差及歷史資料
這是比價資料的主要流向。正規化是抓取與配對共用的邊界;配對品質會直接影響最後價差是否有意義。

HTTP 優先,瀏覽器作後備

資料能直接取得時走 HTTP,必要時才使用 Selenium,降低瀏覽器啟動與維護成本。

取捨:兩條擷取路徑都要面對網站改版;容器預設不包含 Chrome,後備路徑需另備環境。

分桶後評分,再合併群組

先用品牌與型號縮小候選,再比較名稱與規格,以 union-find 建立商品群組。

取捨:群組具有傳遞性,一筆錯配可能牽連其他品項,因此規格衝突不能只靠名稱相似度補救。

真實 MySQL 的獨立整合驗證

單元測試、MySQL 整合測試與 Docker 冒煙測試分開,讓無資料庫環境也能快速檢查核心邏輯。

取捨:CI 設定較多,但可以避免資料庫測試全被跳過仍呈現成功的情況。

04 / DEEP DIVE

兩個實作差異與內容

A從文字相似,走到同款商品

標題相似可能只是同系列,容量或組合數不同就不是公平的價格比較。分桶減少不必要配對,評分與衝突判斷才決定是否連在一起。

做法差異 · A比名稱相似度,很容易把不同規格當同款。

本專案採用 · B先整理品牌型號,再處理候選評分與分組。

核心邏輯示意 · Python 風格偽程式碼,含說明註解;非原始碼節錄
# 示意:先縮小候選,再決定是否合併
for bucket in group_by_brand_and_model(products):
    for left, right in candidate_pairs(bucket):
        if has_spec_conflict(left, right):
            continue  # 規格衝突不能只靠標題相似度抵銷
        if pair_score(left, right) >= threshold:
            groups.union(left.id, right.id)

這段是配對流程的精簡示意。union-find 表達群組關係;實際成效仍要用人工核對的正負樣本量測,不能只由演算法名稱推論準確度。

BCI 成功,也要確認該跑的測試有跑

無資料庫時跳過整合測試是合理的;但已經提供 MySQL 的 CI 工作若仍跳過,就可能只是環境設定失效。兩個情境必須分開處理。

做法差異 · A只看測試程序有沒有回傳成功。

本專案採用 · B整合環境額外確認資料庫測試沒有被跳過。

核心邏輯示意 · Python 風格偽程式碼,含說明註解;非原始碼節錄
# 示意:MySQL 整合工作必須真的執行資料庫案例
report = run_database_integration_tests()
if report.failed:
    fail_build()
# skip 在單元測試工作可接受,在此處代表環境有問題
if report.database_tests_skipped:
    fail_build("資料庫整合測試未執行")

原始 CI 以測試紀錄檢查跳過狀態;這裡用偽程式碼呈現規則。測試通過與測試根本沒執行,是兩個不同結論。

05 / TROUBLESHOOTING

遇到的問題

真實商品資料暴露錯配

發現:不同規格、不同組合或相近型號容易被名稱相似度混在一起。

排查與處理:回看實際誤配,將衝突條件補回配對邏輯與回歸案例。下一步仍需要固定標註集,才能量化改善。

多個 worker 查不到同一份工作進度

發現:背景工作佇列保存在行程記憶體,提交與輪詢若落在不同 worker,就看不到相同狀態。

排查與處理:目前固定單 worker,讓部署符合現有架構;若需要擴充,應先把工作佇列移到共用儲存。

06 / IMPACT & TAKEAWAYS

成果

以下為 2026 年 9 月整理的歷史開發紀錄;數據依各自的樣本與量測情境解讀,並非即時統計。

374 個案例

歷史測試收集紀錄

2026-08-12 pytest 快取記錄,含參數化展開;不是 374 個獨立函式,也不是本次重跑結果。

3 道 CI 工作

不同層次的驗證

單元、真實 MySQL 整合、Docker 冒煙各自檢查不同問題。這描述驗證設計,不表示目前遠端 CI 狀態。

尚待量測

同款配對的準確度

已針對真實誤配修正規則,但沒有足夠依據宣稱固定準確率。誤配會造成虛假價差;漏配則會錯失比較機會。

回顧

這個重寫讓我先問「使用者到底要比較什麼」,再決定怎麼呈現資料。下一次會更早建立人工配對樣本,讓規則調整有穩定的驗收依據。

07 / ROADMAP

未來展望

以下是依目前限制整理的後續方向,尚未完成,也尚未排定時程。

待規劃 · 01

建立同款與非同款的標註集

依品牌、容量、套裝與型號整理容易混淆的商品對,保留正例和負例。

怎麼確認有改善:同時觀察 precision 與 recall:前者關係到是否顯示錯誤價差,後者關係到漏掉多少可比較商品。

待規劃 · 02

把配對理由顯示出來

讓介面呈現品牌型號依據與規格衝突,對模糊配對提供待核對標示。

怎麼確認有改善:使用者能回到來源確認,不必把系統給出的每一組配對都視為確定事實。

待規劃 · 03

按需求擴充背景工作

若同時使用量增加,先將工作狀態與佇列移出行程記憶體,再評估多 worker。

怎麼確認有改善:驗證重啟後進度可追蹤、工作不重複執行,並區分網頁回應與抓取工作的資源。