

# 如何用 n8n 自动采集 Facebook 评论

按设定间隔自动运行公开帖子链接。等待采集任务完成，然后获取得到的评论数据。用每条评论的唯一标识保存该评论，这样重复采集检查不会产生重复记录。

本指南提供一套供你在本地构建和测试的参考方法，用来建立可重复的摄取工作流，而不是预先建好的导入，也不是经过验证的完整部署。检查点是已保存的执行进度记录。upsert 是一种数据库操作：插入新行；如果唯一键匹配到重复记录，则更新已有记录。

## 技术范围与运行限制

配置 n8n 工作流之前，你必须了解这条提取管道处理什么，以及它的边界在哪里。本系统只做自动数据提取和持久存储。它不做垃圾信息过滤、情感分析、客户意图评分、自动回复或内容审核。如果需要把评论分到自定义类别，请阅读我们的指南：[Facebook 评论客户反馈分析](/zh-Hans/articles/%E5%A6%82%E4%BD%95%E5%AF%BC%E5%87%BAfacebook%E8%AF%84%E8%AE%BA%E5%B9%B6%E5%88%86%E6%9E%90%E5%AE%A2%E6%88%B7%E5%8F%8D%E9%A6%88/)。如果需要把支持问题路由到正在处理的服务台，请查看我们的教程：[Facebook 未回复评论问题队列](/zh-Hans/articles/%E5%A6%82%E4%BD%95%E6%9F%A5%E6%89%BEfacebook%E8%AF%84%E8%AE%BA%E4%B8%AD%E6%9C%AA%E5%9B%9E%E7%AD%94%E7%9A%84%E9%97%AE%E9%A2%98/)。

本教程使用标准 n8n 节点和 [Facebook Comments Scraper](https://apify.com/chronometrica/facebook-comments-scraper) 的 HTTP API 讲解技术实现。API（应用程序接口）是一组规则和端点，让不同软件程序可以通过网络互相通信。抓取器只接受具体、已知的公开帖子 URL 作为输入。它不接受一般的个人主页链接、小组 URL 或品牌频道页面。执行后，抓取器返回格式为 JSON（JavaScript 对象表示法）的扁平数据记录。JSON 是用于共享结构化数据的标准文本格式。

每一条输出行要么是一条顶层评论，要么是一条直接的嵌套回复。返回的载荷包含 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 评论抓取器 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-Hans/articles/%E5%A6%82%E4%BD%95%E5%AF%BC%E5%87%BAfacebook%E8%AF%84%E8%AE%BA%E5%B9%B6%E5%88%86%E6%9E%90%E5%AE%A2%E6%88%B7%E5%8F%8D%E9%A6%88/)
- [Chronometrica 未回复问题指南](/zh-Hans/articles/%E5%A6%82%E4%BD%95%E6%9F%A5%E6%89%BEfacebook%E8%AF%84%E8%AE%BA%E4%B8%AD%E6%9C%AA%E5%9B%9E%E7%AD%94%E7%9A%84%E9%97%AE%E9%A2%98/)