

# 如何用 n8n 自動收集 Facebook 留言

把公開帖文連結排程，按設定的時間間隔自動執行。等待收集工作完成，然後取得所得的留言資料。用每則留言的唯一識別碼儲存，使重複的收集檢查不會建立重複紀錄。

本指南提供一個參考方法，供你在本地建立並測試，從而建立可重複的擷取工作流程，而不是預先建好的匯入，亦不是已驗證的完整部署。檢查點是已儲存的執行進度紀錄；upsert 是一項資料庫操作，會插入新列，或在唯一鍵重複相符時更新現有紀錄。

## 技術範圍與操作限制

在設定 n8n 工作流程之前，你必須了解這條擷取管道處理甚麼，以及其界限在哪裏。此系統只專注於自動資料擷取與持久儲存。它不會進行垃圾訊息篩選、情緒分析、客戶意圖評分、自動回覆或內容審核。如果你需要把留言歸入自訂類別，請閱讀我們的指南：[Facebook 留言客戶意見分析](/zh-Hant/articles/facebook-%E7%95%99%E8%A8%80%E5%8C%AF%E5%87%BA%E8%88%87%E9%A1%A7%E5%AE%A2%E6%84%8F%E8%A6%8B%E5%88%86%E6%9E%90/)。如果你需要把支援問題轉到使用中的服務台，請查看我們的教學：[Facebook 未回覆留言問題佇列](/zh-Hant/articles/%E6%89%BE%E5%87%BAfacebook%E7%95%99%E8%A8%80%E4%B8%AD%E6%9C%AA%E7%8D%B2%E5%9B%9E%E8%A6%86%E7%9A%84%E5%95%8F%E9%A1%8C/)。

本教學說明如何用標準 n8n 節點，以及 [Facebook Comments Scraper](https://apify.com/chronometrica/facebook-comments-scraper) 的 HTTP API 作技術實作。API（應用程式介面，Application Programming Interface）是一組規則與端點，讓不同軟件程式透過網絡互相通訊。此擷取工具接受指定且已知的公開帖文 URL 作為輸入。它不接受一般個人檔案連結、群組 URL 或品牌頻道頁面。執行時，擷取工具會回傳扁平的資料紀錄，格式為 JSON（JavaScript 物件表示法，JavaScript Object Notation），這是用來分享結構化資料的標準文字格式。

每一輸出列代表一則頂層留言，或一則直接的巢狀回覆。回傳的承載資料包含字串識別碼，例如 commentId 與 contentId。請注意，authorId 與 publishedAt 可以是 null；publishedAt 與 scrapedAt 是時間戳記；isReply 是布林值，而不是精確的字串識別碼。原始 JSON 物件會保留 parentCommentId、rootCommentId、isReply、text 以及 null 值。在各次執行之間，你的資料庫會用 contentId 與 commentId 上的複合唯一限制去除重複，並以參數化查詢實作。

設定管道時，請記住以下操作參數：

- 目標連結：你必須把 1 至 100 個明確的公開帖文 URL，作為字串項目放在一個陣列內。
- 結果上限：參數 maxResultsPerPost 設定每則帖文最多收集多少列留言與回覆。把此參數設為 25，會把該次執行限制為每則帖文最多 25 列。
- 回覆擷取：把 includeReplies 設為 true，即指示擷取工具在收集父留言的同時收集巢狀回覆。
- 完整擷取：把 collectAllAvailable 設為 true 會略過數字結果上限，但仍受平台可見度限制與運算收費約束。
- 排序參數：all、newest 或 most_relevant 等排序選項，決定 Facebook 在擷取前如何排列留言，並且獨立於結果上限運作。

## 核心 API 端點參考

下表摘要此工作流程所用的端點，以及其原始 URL 結構與預期的回應欄位：

| 端點 URL | 說明 | 預期回應欄位 |
| --- | --- | --- |
| [https://api.apify.com/v2/acts/chronometrica~facebook-comments-scraper/runs](https://api.apify.com/v2/acts/chronometrica~facebook-comments-scraper/runs) | 啟動擷取工具的執行 | data.id, data.defaultDatasetId, data.defaultKeyValueStoreId, data.status |
| [https://api.apify.com/v2/actor-runs/RUN_ID](https://api.apify.com/v2/actor-runs/RUN_ID) | 檢查執行狀態 | data.status |
| [https://api.apify.com/v2/datasets/DATASET_ID/items?format=json&clean=false&offset=0&limit=100](https://api.apify.com/v2/datasets/DATASET_ID/items?format=json&clean=false&offset=0&limit=100) | 取得資料集項目的分頁 | 留言紀錄的 JSON 陣列 |
| [https://api.apify.com/v2/key-value-stores/STORE_ID/records/OUTPUT](https://api.apify.com/v2/key-value-stores/STORE_ID/records/OUTPUT) | 檢視該次執行的摘要儲存 | 該次執行專用的摘要紀錄 |

注意：請把 RUN_ID、DATASET_ID 與 STORE_ID 等佔位符，換成你實際儲存的執行值。切勿把存取權杖直接寫入 URL 字串。

## 逐步架構與節點順序

要在 n8n 建立這條管道，你會設定一連串內建節點的結構化順序。你需要已安裝的 n8n、存放在 n8n Header Auth 憑證中的 Apify API 權杖（名稱為 Authorization，值為 Bearer your_token），以及一個關聯式資料庫憑證（例如 Postgres）。

### 1. 觸發條件與憑證設定

先在 n8n 建立新的工作流程。開啟工作流程設定，選取你的本地時區，並在建立與測試元件期間，讓工作流程保持未發佈。

你會建立兩個進入點：

- Schedule Trigger：按你的時區設定，自動觸發每日或每小時的重複收集執行。
- 手動觸發與復原輸入：供操作人員使用的獨立手動進入點。因為手動觸發不能直接接受執行 ID，請在其後放置一個 Edit Fields 節點，讓操作人員輸入已儲存的現有執行 ID。這樣你可以復原停滯的執行，而無需啟動新的擷取工作。

### 2. 啟動擷取工具

把排程觸發連接到名為 Launch Scraper 的 HTTP Request 節點。把方法設為 POST，並指向 Apify actor 執行端點。附上你的 Header Auth 憑證。用原始 URL 字串設定一個簡短的純 JSON 請求主體：

```text
{
  "startUrls": [
    "https://www.facebook.com/story.php?story_fbid=123456789&id=987654321"
  ],
  "maxResultsPerPost": 25,
  "includeReplies": true,
  "collectAllAvailable": false,
  "commentSortMode": "all"
}
```

逐步架構與節點順序

當此請求成功時，Apify API 會回傳一個包含執行中繼資料的封套。你的工作流程必須立即擷取並儲存四個值：data.id、data.defaultDatasetId、data.defaultKeyValueStoreId 與 data.status。

把這些值存入以執行 ID 為鍵的可持久資料庫檢查點，並把嘗試次數初始化為 0，下一個偏移量初始化為 0。可持久是指永久儲存在關聯式資料庫中，而不是暫存在工作流程記憶體內。

關鍵安全規則：如果發生網絡逾時，切勿自動重試一次結果不明的啟動 POST 請求。如果第一個請求已到達伺服器，盲目重試會啟動第二次會計費的擷取執行。如果某次啟動結果不明，請先手動查看你的 Apify 帳戶執行清單，然後才觸發新的一次。

### 3. 復原路徑

如果某次執行失敗或停滯，手動復原分支會用操作人員提供的執行 ID 選取現有的檢查點紀錄，並完全跳過啟動節點。

你的工作流程強制規定：每個執行 ID 只可有一個進行中的執行。如果復原的執行在資料庫中已顯示終端已儲存狀態 SUCCEEDED，工作流程會完全跳過狀態輪詢，並直接前往分頁載入。如果已儲存狀態是 failed，則轉往手動覆核。其他狀態會進入有界限的輪詢。復原執行永不自動重設嘗試次數。

### 4. 狀態輪詢與計數閘門

每次檢查狀態之前，工作流程會查詢資料庫，以檢查目前的嘗試次數。如果嘗試次數已達 30，系統會把執行轉到手動覆核分支，以防止無限迴圈。

如果次數低於 30，工作流程會在資料庫中遞增嘗試次數，用 Wait 節點暫停執行 10 秒，然後用 HTTP GET 請求向 Apify API 檢查執行狀態（[https://api.apify.com/v2/actor-runs/RUN_ID](https://api.apify.com/v2/actor-runs/RUN_ID)）。

輪詢期間的網絡請求錯誤，應使用有界限的讀取重試（最多 3 次嘗試，每次等待 10 秒），而不是重試 POST 請求。

工作流程會評估回傳的狀態：

- SUCCEEDED：工作流程把該扁平狀態儲存到資料庫，並繼續取得資料集。
- READY / RUNNING / ABORTING / TIMING-OUT：工作流程把執行轉回計數閘門，以便等待並再次檢查。
- FAILED / ABORTED / TIMED-OUT：工作流程記錄失敗狀態，然後停止或轉往手動覆核。
- 未知狀態：轉往手動覆核。

注意：停止輪詢迴圈並不會取消遠端的 Apify actor；它只是讓你的 n8n 工作流程停止等待。輪詢逾時並不表示該帖文有 0 則留言。

### 5. 分頁與頁面載入

一旦該次執行成功，工作流程便進入分頁迴圈。在取得每一頁之前，它會從資料庫重新載入目前的檢查點狀態，以取得最新的偏移量與資料集 ID。

它會發出 HTTP GET 請求以取得資料集項目（[https://api.apify.com/v2/datasets/DATASET_ID/items?format=json&clean=false&offset=0&limit=100](https://api.apify.com/v2/datasets/DATASET_ID/items?format=json&clean=false&offset=0&limit=100)，代入目前的偏移量與已儲存的資料集 ID）。你必須指向該次執行專用的資料集 ID，而不是泛用的 latest 別名。把請求格式設為 JSON，使用 clean=false，並設定 limit=100。

設定 HTTP 節點回傳完整的回應主體。在把資料傳給任何分割節點之前，先記錄傳入陣列的長度。如果第一頁的陣列完全是空的，請略過分割，並透過專用端點（[https://api.apify.com/v2/key-value-stores/STORE_ID/records/OUTPUT](https://api.apify.com/v2/key-value-stores/STORE_ID/records/OUTPUT)）用已儲存的儲存區 ID 檢查鍵值儲存的輸出紀錄，以判斷是否發生錯誤。對於其後的頁面，空陣列只是表示收集已結束。

### 6. 分割與資料庫 upsert

把資料集陣列傳入 Split Out 節點，並設定明確的目的地欄位，名稱為 comment。

下游的資料庫儲存節點會接收每個已分割的項目，並直接從 comment 對應欄位。它會驗證非空的字串識別碼與有效的時間戳記是否存在。它會對複合唯一鍵限制（contentId 與 commentId）執行使用參數化查詢的 upsert 操作。upsert 會插入新列，或在出現重複相符時更新現有紀錄。

為避免舊資料覆寫較新的更新，請設定資料庫更新條件，使傳入的文字與中繼資料只在傳入的 scrapedAt 時間戳記大於或等於已儲存的時間戳記時才更新。這代表該公開帖文最新被觀察到的狀態，而不是不可變更的歷史稽核紀錄，亦不是刪除證明。

### 7. 推進檢查點

當目前頁面的每個項目都成功寫入資料庫之後，工作流程會把資料庫中的檢查點偏移量加上 100。

關鍵規則：切勿按每則留言推進一次檢查點偏移量。你必須在整批成功之後，按每一頁剛好更新一次檢查點偏移量。如果資料庫寫入在一頁中途失敗，檢查點偏移量會保持不變，讓工作流程可以安全地重播該頁，而不會建立重複紀錄。

在分割步驟與資料庫步驟之間，另行保留目前頁面長度的中繼資料。最終檢查使用的是目前頁面的長度，而不是第一次迴圈的長度。如果目前頁面長度少於 100 個項目，收集便已完成，工作流程結束。如果頁面長度等於 100，工作流程會回到重新載入檢查點，並取得下一批。

## 讀者測試與驗證程序

在把工作流程發佈為於正式環境自動執行之前，你必須在本地建立並測試工作流程，並使用有結構的驗證檢查。不要依賴未經測試的範本。

1. 獨立擷取測試：把凍結的測試案例輸入 {body: [25 comments]} 直接注入一個 Split Out 節點。該節點接到你的資料庫節點，並設定為立即 STOP，略過所有即時的檢查點節點與頁面摘要節點。驗證資料庫剛好儲存 25 列。第二次執行完全相同的測試案例，結果是插入 0 列新紀錄，現有紀錄會被評估，且沒有倒退。加入一筆不同的第 26 筆紀錄，會剛好插入 1 列新紀錄。此外，驗證較舊的測試案例不能覆寫較新的文字。
2. 分頁測試案例：用一個以替身模擬的檢查點，以及分佈在 3 頁的 201 筆紀錄（分別為 100、100 與 1），測試你的偏移量迴圈，且不產生任何須付費的 Actor 呼叫。
3. 容錯與輪詢測試：測試在輪詢路徑上，輪詢次數達到上限時會正確觸發手動覆核。模擬中間某一頁的資料庫寫入失敗。驗證檢查點偏移量保持不變、復原不會重新啟動擷取工具，以及非成功狀態會正確阻止取得資料集。
4. 即時手動驗證：對一條真實的公開帖文連結執行一次手動測試。檢視你的平台限制、運算費用與執行日誌。

只有在所有本地測試都通過，而且排程時區已正確設定之後，你才應儲存並發佈你的 n8n 工作流程。

## 今天就自動收集你的 Facebook 留言

建立自訂的留言擷取管道，可讓你的團隊穩定取得公開討論資料，而無須手動匯出試算表。把標準 n8n 節點與可持久的資料庫檢查點及複合唯一限制配合使用，你便能建立一套能妥善處理網絡中斷的穩健擷取工作流程。今天就用 [Facebook Comments Scraper](https://apify.com/chronometrica/facebook-comments-scraper) 開始擷取有結構的社交對話。

## 來源與延伸閱讀

- [Facebook Comments Scraper Actor](https://apify.com/chronometrica/facebook-comments-scraper)
- [n8n Schedule Trigger 說明文件](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.scheduletrigger/)
- [n8n HTTP Request 節點說明文件](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/)
- [n8n Wait 節點說明文件](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.wait/)
- [n8n Postgres 節點說明文件](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.postgres/)
- [n8n Split Out 節點說明文件](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.splitout/)
- [Apify API 參考：取得 Actor 執行](https://docs.apify.com/api/v2/actor-run-get)
- [Apify API 參考：取得資料集項目](https://docs.apify.com/api/v2/dataset-items-get)
- [Chronometrica 意見分析指南](/zh-Hant/articles/facebook-%E7%95%99%E8%A8%80%E5%8C%AF%E5%87%BA%E8%88%87%E9%A1%A7%E5%AE%A2%E6%84%8F%E8%A6%8B%E5%88%86%E6%9E%90/)
- [Chronometrica 未回覆問題指南](/zh-Hant/articles/%E6%89%BE%E5%87%BAfacebook%E7%95%99%E8%A8%80%E4%B8%AD%E6%9C%AA%E7%8D%B2%E5%9B%9E%E8%A6%86%E7%9A%84%E5%95%8F%E9%A1%8C/)