API を使用してトピックのすべての投稿を取得する

:notebook_with_decorative_cover: これは、Discourse API を使用してトピックからすべての投稿を取得する方法を説明するハウツーガイドです

Discourse API が多くのルートで返す結果はページネーションされています。

例えば、「単一のトピックを取得」の API エンドポイント - 例:https://examplesite/t/{id}.json は、トピックに 20 件以上の投稿が含まれていても、デフォルトでは 20 件の投稿のみを返します。

この動作により、.../t/{id}.json エンドポイントを使用してトピックのすべての投稿を取得するには、Discourse API を使うための 2 つの方法があります。

クエリパラメータを追加する

トピックからすべての投稿を取得する最も簡単な方法は、リクエストを行う 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. 次に、トピック内のすべての投稿 ID を提供する stream 配列をループ処理する必要があります。ストリームから最初の 20 件の投稿 ID を削除してください(そうしないと、不要に再ダウンロードすることになります)。

  3. その後、追加のリクエストを「トピックからの特定の投稿を取得」.../t/{id}/posts.json エンドポイントに行い、post_ids[] を追加して、stream 配列から取得した ID を 20 件ずつのチャンクで渡します。例:\n.../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 には、1 時間あたりに行える print=true リクエストの数に制限があり、これは「ユーザーあたりの 1 時間あたりの最大印刷数」というサイト設定によって制御されています。この設定のデフォルト値は、ユーザーが 1 時間あたり 5 トピックのみを印刷できるように設定されています。この値を 0 に設定すると、印刷機能が完全に無効になります(print=true を含むリクエストは 403 エラーを返します)。

なお、リクエストを行うユーザーが管理者である場合は、レート制限は適用されません。つまり、リクエストの Api-Username パラメータに管理者のユーザー名(例:system)を使用して API キーを指定することで、印刷のレート制限を回避できます。

print=true を含まない API リクエストでレート制限エラーが発生する場合は、レート制限を超えないように API スクリプトにタイムアウトを設定することをお勧めします。あるいは、429(リクエストが多すぎます)エラーコードを監視し、そのレスポンスを受け取った際にリクエストをバックオフ(待機)させることもできます。

参考までに、以下に記載されているデフォルトのレート制限は、標準およびビジネスホスティングプランに適用されます。

:grey_exclamation: セルフホスト版のみ - 詳細については、Discourse API のレート制限を調整する方法を Available settings for global rate limits and throttling を参照してください。

「いいね!」 11

?page クエリパラメータはサポートされていますか? 動作はしますが、予期しない方法です。?page=1 はトピックの最初の投稿しか返さないため、パラメータでページネーションするには https://example.com/t/slug/topicId.json から開始し、https://example.com/t/slug/topicId.json?page=2 にスキップし、最終的に 404 レスポンスが得られるまで続行する必要があります。

サイモン様

?page=1 パラメータを Get a single topic endpoint と共に使用すると、トピックから最初の 20 件の投稿が返され、それ以降のページ番号ごとに最大 20 件の投稿が返されます。

投稿がこれ以上ない場合(例:ページ番号が高すぎて無効な場合)、404 レスポンスが返されます。

ページ番号を指定しない場合、コードはページ番号を 1 に設定するため、?page=1 はトピックリクエストに明示的なページを追加しないのと同じです。

この方法を使用してトピックからすべての投稿を取得したい場合、Discourse API Docs に記載されていなくても、それが可能であるはずです。

「いいね!」 3

ありがとうございます!投稿を取得するMatrixボットを開発中です!

これは間違っていると思います。0に設定すると、印刷が完全に無効になります。この設定の最新の説明は、「/print ページの最大表示回数(印刷を無効にするには0に設定)」です。