使用 API 获取主题中的所有帖子

:notebook_with_decorative_cover: 本指南介绍如何使用 Discourse API 获取某个主题下的所有帖子。

Discourse API 对许多路由返回的结果都是分页的。

例如,“获取单个主题” 的 API 端点(示例:https://examplesite/t/{id}.json)默认仅返回 20 条帖子,即使该主题包含超过 20 条帖子。

由于这一行为,使用 .../t/{id}.json 端点获取主题下所有帖子有两种方法:

添加查询参数

获取主题下所有帖子的最简单方法是在请求 URL 中添加 print=true 查询参数。

示例:https://examplesite/t/{id}.json?print=true

添加 print=true 查询参数后,Discourse 会将返回的帖子数量 chunk_size 设置为 1000。这意味着,只要您确定主题中的帖子不超过 1000 条,这种方法就非常适用。

多次 API 请求

另一种获取所有帖子的方法是发起多次 API 请求,以获取主题中的所有帖子:

  1. 首先,向 .../t/{id}.json 端点发起初始 GET 请求。该响应将包含一个 posts_stream 哈希,其中包含 posts 数组和 stream 数组。posts 数组将提供前 20 条帖子。

  2. 接下来,您需要遍历 stream 数组,该数组包含主题中所有帖子的 ID。请从 stream 中移除前 20 个帖子 ID(否则您将无意义地重新下载它们)。

  3. 然后,您可以向 “获取主题中的特定帖子”.../t/{id}/posts.json 端点发起额外请求,附加 post_ids[] 参数,并以每批 20 个的方式传入 stream 数组中的所有 ID。示例:
    .../t/{id}/posts.json?post_ids[]=46&post_ids[]=47&post_ids[]=48&post_ids[]=49&post_ids[]=50&post_ids[]=51&post_ids[]=52&post_ids[]=53&post_ids[]=54&post_ids[]=55&post_ids[]=56&post_ids[]=57&post_ids[]=58&post_ids[]=59&post_ids[]=60&post_ids[]=61&post_ids[]=62&post_ids[]=63&post_ids[]=64&post_ids[]=65

速率限制

如果在发起多次 API 调用时遇到 Error: you have performed this action many times, please try again later 错误,这表明您已触达 API 密钥的速率限制。

Discourse 对每小时可发起的 print=true 请求数量有限制,该限制由站点设置 max prints per hour per user 控制。该设置默认仅允许用户每小时打印 5 个主题。将其设置为 0 将完全禁用打印功能(带有 print=true 的请求将返回 403 错误)。

请注意,如果请求用户是管理员,则不会应用速率限制。这意味着,您可以在请求的 Api-Username 参数中使用管理员用户名(例如 system)来绕过打印速率限制。

如果您在使用不包含 print=true 的 API 请求时遇到速率限制错误,建议为您的 API 脚本添加超时机制,以避免超出速率限制。或者,您可以监听 429(请求过多)错误代码,并在收到该响应时降低请求频率。

供参考,以下默认速率限制适用于我们的标准版和企业版托管计划:

:grey_exclamation: 仅限自托管环境 - 详细信息请参阅:https://meta.discourse.org/t/available-settings-for-global-rate-limits-and-throttling/78612,了解如何调整 Discourse API 的速率限制。

11 个赞

是否支持 ?page 查询参数?它确实有效,但方式有些出人意料——?page=1 只返回主题中的第一篇帖子,因此要使用该参数进行分页,您需要从 https://example.com/t/slug/topicId.json 开始,然后跳到 https://example.com/t/slug/topicId.json?page=2,然后继续,直到最终收到 404 响应。

您好 Simon,

使用 ?page=1 参数配合 Get a single topic endpoint 将会返回一个主题的前 20 篇帖子,后续的页码将返回最多 20 篇帖子。

当没有更多帖子可用时(例如,页码过高且无效),您将收到 404 响应。

如果您不指定页码,代码将默认页码为 1,因此 ?page=1 与不显式附加页码到主题请求的效果相同。

如果您想使用此方法获取主题中的所有帖子,即使 Discourse API Docs 中没有提及,您也应该能够做到。

3 个赞

谢谢!正在开发一个 Matrix 机器人来获取帖子!

我认为这是错误的。设置为 0 将完全禁用打印。此设置的最新描述是“最大打印/print页面印象数(设置为 0 以禁用打印)”。