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

:notebook_with_decorative_cover: 这是关于如何使用 Discourse API 获取主题所有帖子的操作指南

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

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

由于这种行为,您可以通过两种方式使用 Discourse API 来获取主题的所有帖子,使用 .../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。从流中删除前 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 调用时,如果遇到“错误:您已执行此操作多次,请稍后重试”的消息,这表明您遇到了 API 密钥速率限制。

Discourse 对每小时可以进行的 print=true 请求数量有限制,该限制由 max prints per hour per user 站点设置控制。此设置默认只允许用户每小时打印 5 个主题。您可以将该设置设置为 0 以禁用速率限制。

请注意,如果您使用 All Users API 密钥进行请求,并为请求的 Api-Username 参数提供站点管理员的用户名,则不会应用速率限制。这意味着,您不必禁用 max prints per hour per user 站点设置,只需为请求使用管理员用户名(例如 system)。

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

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

discourse/config/discourse_defaults.conf at main · discourse/discourse · GitHub

:grey_exclamation: 仅限自托管 - 请参阅:Available settings for global rate limits and throttling 了解有关调整 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 以禁用打印)”。