changedetection.io 完整教學 2026:3.4 萬星開源網頁變更監控,降價/補貨/公告自動通知(Docker 安裝、CSS/XPath/jq 選擇器、Browser Steps、Apprise 通知、價格追蹤與 REST API 一次學會)

changedetection.io 是 GitHub 上 34,000+ stars、Apache-2.0 授權的開源網頁變更監控工具(Python 撰寫,最新版 0.60.8,2021 年至今持續維護)。它幫你盯住任何網頁——商品降價、補貨、政府公告、職缺釋出、PDF 改版——只要內容變了就透過 Apprise 推播到 ntfy、Telegram、Discord、Email 或 Webhook。本文從 Docker Compose 安裝、第一個 watch、CSS/XPath/JSONPath/jq 選擇器、條件觸發、JavaScript 網站的 Browser Steps 與 Playwright 設定,一路到價格追蹤模式、REST API 自動化(含可直接複製的 Python 範例)、與 Distill.io/Visualping/自己寫 cron 的完整比較表,以及 7 個新手一定會踩的陷阱。

  • Dennis
  • 10 分鐘閱讀
changedetection.io 完整教學 2026:3.4 萬星開源網頁變更監控,降價/補貨/公告自動通知(Docker 安裝、CSS/XPath/jq 選擇器、Browser Steps、Apprise 通知、價格追蹤與 REST API 一次學會)

changedetection.io 是一套開源、可自架的網頁變更監控工具(GitHub 34,000+ stars、Apache-2.0、Python 撰寫):你只要貼上一個網址,它就會定期去比對頁面內容,只要發現差異,就透過 Apprise 推播到 ntfy、Telegram、Discord、Email 或 Webhook。 它最常被拿來做三件事:盯商品降價、盯補貨、盯各種「只會默默更新在官網上」的公告。

這篇文章會從零帶你自架一套,並且把「怎麼只在你真正在意的那一行文字改變時才通知你」這個關鍵技巧講清楚——因為「什麼都通知」等於什麼都沒通知。

為什麼需要它?Uptime Kuma 管「活著沒」,它管「變了沒」

如果你已經在用 Uptime Kuma 之類的工具,先分清楚兩件事:

工具類型它回答的問題例子
可用性監控(Uptime Kuma、Gatus)服務還活著嗎?網站回 503 了,趕快叫我
內容變更監控(changedetection.io)內容變了嗎?官網還活著,但價格從 8,990 變成 6,990

網頁最麻煩的變更,往往是「頁面完全正常、HTTP 200、只是某一小段文字不一樣」。這種事沒有工具幫你盯,就只能自己每天手動重刷。changedetection.io 就是來解決這件事的。

實際會用到它的情境:

  • 電商商品降價或補貨(白色 48 號有貨了叫我)
  • 政府機關/公會/學校公告異動(招標、法規、榜單、課程名額)
  • 公司職缺頁釋出新職位、BambooHR 之類的平台更新
  • B2B 競品定價頁改版、條款更新
  • PDF 文件改版(它有內建 PDF 文字變更偵測)
  • JSON API 回應內容變動(不是看 HTTP 狀態,是看 body 內容)

專案基本資料

項目內容
GitHubdgtlmoon/changedetection.io
Stars約 34,700(2026-10 統計)
授權Apache-2.0(商用自架沒問題)
語言Python
最新版本0.60.8(2026-09-28 發布)
Docker 映像dgtlmoon/changedetection.io 或 ghcr.io/dgtlmoon/changedetection.io
官方 SaaS約 US$8.99/月(不想自架時的選項)
資源需求很輕,1 vCPU/512MB RAM 就能跑(要開 Chrome 才需要更多)

5 分鐘安裝:Docker Compose

最省事的方式是 Docker Compose。先建一個資料夾,放一份 docker-compose.yml:

services:
  changedetection:
    image: ghcr.io/dgtlmoon/changedetection.io
    container_name: changedetection
    hostname: changedetection
    volumes:
      - changedetection-data:/datastore
    ports:
      - 127.0.0.1:5000:5000
    restart: unless-stopped
    environment:
      - TZ=Asia/Taipei
      - BASE_URL=https://change.example.com

volumes:
  changedetection-data:

啟動:

docker compose up -d
docker compose logs -f --tail=50

打開 http://127.0.0.1:5000 就會看到介面。注意這裡刻意綁在 127.0.0.1,原因是這個服務內含你所有監控清單,直接開到公網等於把情報公開。要從外部連進來,正確做法是走反向代理(Cloudflare Tunnel 完整教學 或 Caddy/Nginx),而不是改 0.0.0.0。

如果你不想寫 compose,一行也行:

docker run -d --restart always \
  -p "127.0.0.1:5000:5000" \
  -v datastore-volume:/datastore \
  --name changedetection.io \
  dgtlmoon/changedetection.io

讓它能抓 JavaScript 網站(強烈建議)

很多現代電商頁面的價格是 JS 執行後才塞進 DOM,純 HTTP fetcher 抓到的會是空殼。解法是加跑一個 Chrome:

services:
  changedetection:
    image: ghcr.io/dgtlmoon/changedetection.io
    volumes:
      - changedetection-data:/datastore
    ports:
      - 127.0.0.1:5000:5000
    restart: unless-stopped
    environment:
      - PLAYWRIGHT_DRIVER_URL=ws://browser-sockpuppet-chrome:3000
    depends_on:
      browser-sockpuppet-chrome:
        condition: service_started

  browser-sockpuppet-chrome:
    hostname: browser-sockpuppet-chrome
    image: dgtlmoon/sockpuppetbrowser:latest
    cap_add:
      - SYS_ADMIN
    restart: unless-stopped
    environment:
      - SCREEN_WIDTH=1920
      - SCREEN_HEIGHT=1024
      - SCREEN_DEPTH=16
      - MAX_CONCURRENT_CHROME_PROCESSES=10

volumes:
  changedetection-data:

設定好 PLAYWRIGHT_DRIVER_URL 後,每個 watch 就能在編輯頁切換 fetcher 成 Chrome,並解鎖 Visual Selector(用滑鼠點你要監控的那一塊)與 Browser Steps。記憶體會多吃一些,1GB RAM 以上比較保險。

建立第一個 watch

介面右上角「+ ADD WEBSITE TO WATCH」貼上網址即可。重點是這三個欄位:

  1. URL:要監控的頁面。
  2. Check interval:多久檢查一次(預設都有值,建議至少 15 分鐘起跳)。
  3. Filters & Triggers(下面會細講):決定「哪些內容算變更」。

存檔後按「Recheck」可以立刻驗證抓不抓得到。抓到了,它會存下一份快照,之後有差異才會通知你。

關鍵技術一:把「雜訊」濾掉的選擇器

沒有設選擇器,一個頁面上任何一點改動(廣告輪播、時間戳、推薦商品)都會通知你。 這是新手最常見的失敗原因。changedetection.io 支援:

語法寫法適合
CSS Selector#price、.product-price一般 HTML 頁面,最簡單
XPath//span[@class="price"]結構複雜、要往上找相對節點
JSONPathjson:$..priceJSON API 回應
jqjq:.items[] | select(.inStock)複雜 JSON 過濾與邏輯判斷
正規表達式re:test:、re:match:、re:replace:文字層級的抽取與清理

還有一組「清理用」的開關,跟選擇器搭著用最有效:

  • Subtractive selectors:先把頁首、頁尾、導覽列整塊刪掉再比對。
  • Ignore text:符合的字串(例如 版權所有 2026、隨機時間戳)直接忽略。
  • Trigger text:只有當頁面出現這些字時才算變更。
  • Text should not be present:出現就告警(適合監控「已售完」字樣消失)。
  • Extract text:用 regex 只留下你要的那一小段(例如只留價格數字)。

電商價格:優先抓 JSON-LD,比爬 DOM 穩

很多電商(含台灣的購物網站)會在頁面裡埋 application/ld+json 的結構化資料,裡面就有 price 與 availability。這比抓看得見的 <div> 可靠太多,因為前端改版常常只改 CSS class、不改結構化資料。用 JSON filter 直接寫:

json:$..price

就能把整份 JSON-LD 裡的 price 抽出來比對。若你要更複雜的條件(例如只在 availability 是 InStock 時才比價格),改用 jq: 版本。

關鍵技術二:只在「真的降價」時通知你

如果你的需求是價格,不要自己寫選擇器,直接用內建的 Re-stock & Price detection 處理器(restock_diff)。在編輯頁把處理器切成價格/補貨模式後,它會自動讀取頁面的價格 meta 資料,並給你這些選項:

  • Follow price changes:跳脫「有變就通知」,改追蹤價格趨勢。
  • Price change threshold:只有變動超過 X% 才通知(避免 1 元跳動轟炸你)。
  • In stock only:只在「補貨」那一刻通知。
  • 還能把歷史價格畫成趨勢圖,看它是不是真的在慢慢降。

搭配 Conditions(ALL / ANY 邏輯)可以做出很精準的規則,例如:

{
  "conditions": [
    { "field": "page_filtered_text", "operator": "contains_regex", "value": "6,?990" }
  ],
  "conditions_match_logic": "ANY"
}

關鍵技術三:登入後才看得到的頁面(Browser Steps)

有些內容要登入、要選規格、要按下「查詢」才會出現。Browser Steps 讓你在每次檢查前先跑一串瀏覽器動作:

  1. 開啟頁面
  2. 填入文字框(帳號/關鍵字/日期)
  3. 點擊按鈕(同意 cookie、加入購物車、送出查詢)
  4. 才執行變更比對

它需要 Playwright 已啟用(也就是上面那段 sockpuppetbrowser 的設定)。設定完 Browser Steps 之後,再回 Visual Selector 分頁用滑鼠點出真正要盯的元素,整個流程就穩了。

通知:透過 Apprise 串接 100+ 種服務

changedetection.io 的通知底層用的是 Apprise,所以你能填的是「通知 URL」。在每個 watch 的 Edit → Notifications 貼上,或直接在 Settings 設成全站預設:

服務通知 URL 格式
ntfy(自架或 ntfy.sh)ntfy://ntfy.sh/my-changes
ntfy(自架含帳密)ntfy://user:pass@ntfy.example.com/my-topic
Telegramtgram://<bot_token>/<chat_id>
Discorddiscord://<WebhookID>/<WebhookToken>/
Gotifygotify://hostname/token
Email(Gmail 應用程式密碼)mailto://user:app_password@gmail.com
一般 Webhook/自家 APIjson://your-server.com/hook

幾點實務建議:

  • 優先用 ntfy:自架一個 ntfy 容器,手機裝 App 訂閱 topic,完全免費又即時。搭配 Apprise 幾乎零設定。
  • 進階:只在特定條件才通知,用 trigger_text(出現「降價」才通知)。
  • 加上截圖:開啟 notification_screenshot,通知會附上變更當時的畫面,回頭查很方便。
  • 通知也可以模板化:標題與內容支援 Jinja2,能塞入 {{diff}}、{{watch_url}} 等變數。

用 AI 過濾雜訊(可接本機 Ollama)

0.6x 之後加入的 LLM 功能,解決的是「diff 太多行、看不出重點」的問題:

  • AI 變更意圖(llm_intent):用一句白話寫「只有價格低於 50 美元才通知我」「忽略導覽列與頁尾的變動」,AI 會拿每次 diff 去對照,不符的就自動靜音。
  • AI 變更摘要(llm_change_summary):通知不再是落落長的 diff,而是「價格從 NT$8,990 降到 NT$6,990」這種人話。

它支援 OpenAI、Gemini、Anthropic,也能透過 LiteLLM 指向任何 OpenAI 相容端點——包含你本機的 Ollama 或 vLLM,這樣完全不用把監控頁面內容送去第三方。要用本機模型有兩個小訣竅:把 Ollama 的 num_ctx 開到 8192 以上,並視情況調高 LLM_RESTOCK_MAX_CONTENT_CHARS(預設 15000),否則價格藏在頁面深處時會被截掉。

要完全關掉 AI 功能,設環境變數 LLM_FEATURES_DISABLED=true 即可。

用 REST API 自動化:批量建立 watch

手動加監控很累,尤其是你有 50 個商品要盯。changedetection.io 有完整的 REST API(API key 在 Settings → API):

curl -X GET "http://127.0.0.1:5000/api/v1/watch" \
  -H "x-api-key: YOUR_API_KEY"

用 Python 批量新增(可直接執行):

import requests

API = "http://127.0.0.1:5000/api/v1"
KEY = "YOUR_API_KEY"
headers = {"x-api-key": KEY, "Content-Type": "application/json"}

targets = [
    ("https://shop.example.com/item/123", "商品 A 價格"),
    ("https://shop.example.com/item/456", "商品 B 價格"),
]

for url, title in targets:
    payload = {
        "url": url,
        "title": title,
        "time_between_check": {"minutes": 30},
        "processor": "restock_diff",          # 價格/補貨模式
        "follow_price_changes": True,
        "price_change_threshold_percent": 3,   # 變動 3% 以上才通知
        "notification_urls": ["ntfy://ntfy.sh/my-changes"],
        "notification_screenshot": True,
        "track_ldjson_price_data": True,
    }
    r = requests.post(f"{API}/watch", headers=headers, json=payload)
    print(r.status_code, title, r.text[:80])

其他常用端點:GET /watch/{uuid}(查單一)、PUT /watch/{uuid}(改設定)、DELETE /watch/{uuid}(刪除)、GET /watch/{uuid}/history(歷史快照)、POST /import(批量匯入)、GET /systeminfo(系統狀態)。

如果你要「偵測到變更就觸發後續動作」,除了 json:// webhook,也可以搭配 n8n 完整教學 做一條自動化流程,例如變更 → 寫入 Google Sheet → 發 Slack。

與其他方案比較

方案自架成本選擇器/條件通知管道適合誰
changedetection.io✅免費(自架);官方 SaaS 約 $8.99/月CSS/XPath/JSONPath/jq/regex+條件+LLMApprise 100+ 種想完全掌控、要監控大量頁面
Distill.io❌(瀏覽器擴充+雲端)有免費額度,付費方案視覺選取Email/Slack/Webhook不想自架、頁面數量少
Visualping❌有免費額度,付費方案視覺選取Email/Slack非技術使用者
自己寫 cron + Playwright✅免費全部自己寫自己接工程師、需求高度客製
RSS/官方降價通知❌免費無官方網站本身有支援

選擇邏輯很簡單:要監控的頁面超過 10 個、或想自己掌握資料、或想接本機 LLM,就直接自架 changedetection.io。 只有偶爾盯一兩個頁面、又不想碰 Docker,才考慮 SaaS。

台灣實戰場景

  • 電商降價與補貨:把商品頁丟進去、切到價格模式、設 3% 門檻,只在真的降價時收通知。(大型電商反爬較兇,若被擋,改用 Browser Steps 模擬正常瀏覽,並把檢查間隔拉長。)
  • 政府/公部門公告:招標公告、法規異動、榜單、開課名額這類頁面通常有穩定 HTML 結構,用 CSS selector 鎖定列表區塊就很好用。
  • 求職:盯公司 careers 頁或職缺平台的關鍵字搜尋結果,新職缺一出現就通知。
  • B2B 競品監控:盯競品定價頁與條款頁,改版當天就知道。
  • PDF 改版:規格書、辦法、費率表這類 PDF 檔案直接丟進去,它會比對文字內容。

⚠️ 合規提醒:專案 README 的免責聲明寫得很清楚——你必須自行確保監控行為符合目標網站的服務條款、robots.txt 與當地法律。 實務上請把檢查間隔設得合理(不要 1 分鐘打人家一次)、不要繞過付費牆、不要把抓到的個資存下來。這工具是幫你省時間,不是幫你踩線。

7 個新手一定會踩的陷阱

  1. 沒設選擇器就開始監控 → 整頁任何風吹草動都通知你,三天內你就會關掉它。先設 CSS selector 或減法選擇器。
  2. JS 網站沒開 Chrome fetcher → 抓到空殼、或每次快照都一模一樣。看到「明明有改卻沒通知」就先檢查 fetcher 對不對。
  3. 直接綁 0.0.0.0 開公網 → 你的監控清單與 API key 門戶洞開。請走反向代理+密碼保護。
  4. 檢查間隔設太短 → 被目標網站封 IP、或自己 VPS 被鄰居投訴。設 MINIMUM_SECONDS_RECHECK_TIME 當保險,預設至少 15 分鐘起。
  5. 把價格寫死在選擇器裡 → 前端一改 class 就壞掉。優先用 JSON-LD/json:$..price。
  6. 忘了 AI 功能會外傳內容 → 若監控的是內部或含敏感資料的頁面,請改接本機 Ollama,或直接 LLM_FEATURES_DISABLED=true。
  7. 更新容器時砍掉 volume → 所有 watch、快照與歷史都再見。更新只要 docker compose pull && docker compose up -d,不要加 -v。

備份與升級

資料全都住在 Docker volume 裡的 /datastore。備份就是打包它:

docker run --rm \
  -v changedetection-data:/data \
  -v "$PWD":/backup \
  alpine tar czf /backup/changedetection-backup-$(date +%F).tar.gz -C /data .

升級(保留資料):

docker compose pull
docker compose up -d

原始來源

站內延伸閱讀

📬 訂閱 most.tw 電子報

每週精選 AI 工具教學與技術乾貨,直接送到你的信箱。免費、隨時可退訂。

訂閱即表示同意收到 most.tw 電子報,隨時可一鍵退訂。

💬 有問題想討論?加 LINE 聯絡我

歡迎透過 LINE 官方帳號直接留言,我會盡快回覆你的問題。

加入 LINE 好友