メインコンテンツへスキップ
Powerstream は、公開 X データにアクセスするための、当社で最速のリアルタイムストリーミング API です。従来の GNIP Powetrack API と同様に、キーワード、オペレーター、メタデータに基づいてポストをフィルタリングするルールを使用します。Powerstream エンドポイントへの永続的な HTTP 接続が確立されると、ほぼリアルタイムで条件に一致するポストを受信し始めることができます。 現在、Powerstream は最大 1,000 個のルールをサポートしており、各ルールは 2048 文字まで指定できます。

主な機能:

  • リアルタイムなデータ配信: ルールに一致するデータをほぼリアルタイムで取得できます。
  • 高精度なフィルタリング: 演算子付きのブールクエリを使用して、必要なデータだけを正確にフィルタリングできます。
  • 配信方式: HTTP/1.1 のチャンク転送エンコーディングを用いた JSON レスポンス。
  • ローカルデータセンター対応: レプリケーション遅延を回避してレイテンシを低減するために、ローカルデータセンターからの投稿のみを取得できます。
Powerstream API は、一部の Enterprise プランで利用可能なプレミアムなサービスです。Powerstream へのアクセスや Enterprise 向けサービスの詳細にご興味がある場合は、Enterprise Request Form から営業チームまでお問い合わせください。 Powerstream がどのようにお客様のニーズにお応えできるか、喜んでご相談させていただきます。

クイックスタート

このセクションでは、Python の requests ライブラリを使用して PowerStream エンドポイントをすぐに使い始める方法を紹介します。pip install requests でインストールしてください。すべての例は OAuth 2.0 ベアラートークン認証を使用します。YOUR_BEARER_TOKEN を実際のトークンに置き換えてください (os.getenv('BEARER_TOKEN') などを使って安全に保存してください) 。 各エンドポイントについて、コードスニペットとともに紹介します。ファイルの先頭に次の import があるものとします。
import requests
import json
import time
import sys
import os  # 環境変数用

セットアップ

bearer_token = os.getenv('BEARER_TOKEN') or "YOUR_BEARER_TOKEN"  # セキュリティのため環境変数を使用
base_url = "https://api.x.com/2/powerstream"
rules_url = f"{base_url}/rules"  # ルール管理用
headers = {
   "Authorization": f"Bearer {bearer_token}",
   "Content-Type": "application/json"
}

1. ルールの作成 (POST /rules)

ストリームを絞り込むためのルールを追加します。
data = {
   "rules": [
       {
           "value": "(cat OR dog) lang:en -is:retweet",
           "tag": "pet-monitor"
       },
       # 必要に応じてルールを追加してください(最大100件まで)
   ]
}

response = requests.post(rules_url, headers=headers, json=data)
if response.status_code == 201:
   rules_added = response.json().get("data", {}).get("rules", [])
   print("Rules added:")
   for rule in rules_added:
       print(f"ID: {rule['id']}, Value: {rule['value']}, Tag: {rule.get('tag', 'N/A')}")
else:
   print(f"Error {response.status_code}: {response.text}")

2. ルールを削除する (POST /rules)

id (推奨) または value を指定して、ルールを削除します。
data = {
   "rules": [
       {
           "value": "(cat OR dog) lang:en -is:retweet",
           "tag": "pet-monitor"
       },
       # 必要に応じてルールを追加してください(最大100件)
   ]
}

response = requests.delete(rules_url, headers=headers, json=data)
if response.status_code == 200:
   deleted = response.json().get("data", {})
   print(f"Deleted count: {deleted.get('deleted', 'N/A')}")
   if 'not_deleted' in deleted:
       print("Not deleted:", deleted['not_deleted'])
else:
   print(f"Error {response.status_code}: {response.text}")
ヒント: すべてのルールを削除するには、まず GET リクエストで取得し、ID を抽出してから一括削除します。

3. ルールの取得 (GET /rules)

すべての有効なルールを取得します。
response = requests.get(rules_url, headers=headers)
if response.status_code == 200:
   rules = response.json().get("data", {}).get("rules", [])
   if rules:
       print("Active rules:")
       for rule in rules:
           print(f"ID: {rule['id']}, Value: {rule['value']}, Tag: {rule.get('tag', 'N/A')}")
   else:
       print("No active rules.")
else:
   print(f"Error {response.status_code}: {response.text}")

4. PowerStream (GET /stream)

リアルタイムの投稿を取得するためにストリームに接続します。行ごとに読み取るには stream=True を使用します。堅牢性を高めるために、再接続ロジックを実装してください。
stream_url = base_url

def main():
   while True:
       response = requests.request("GET", stream_url, headers=headers, stream=True)
       print(response.status_code)
       for response_line in response.iter_lines():
           if response_line:
               json_response = json.loads(response_line)
               print(json.dumps(json_response, indent=4, sort_keys=True))
               if response.status_code != 200:
                   print(response.headers)
                   raise Exception(
                       "Request returned an error: {} {}".format(
                           response.status_code, response.text
                       )
                   )

ローカルデータセンターサポート

レイテンシを最適化するために、Powerstream では、接続が確立されているローカルデータセンター発 (で作成された) 投稿のみを取得できるオプションを提供しています。これによりレプリケーション遅延を回避でき、他のデータセンターからの投稿と比べて、より高速に配信されます。これを有効にするには、クエリパラメータ ?localDcOnly=true をストリームエンドポイント (例: /2/powerstream?localDcOnly=true) に追加します。接続しているデータセンターは、ストリームの初期データペイロード内とレスポンスの HTTP ヘッダーの両方で示されます。 コードで利用するには:
# ローカルデータセンターのみの場合:
stream_url = "https://api.x.com/2/powerstream?localDcOnly=true"
localDcOnly パラメータが有効になっている場合、ストリームが最初に接続されると、どのローカルデータセンターが使用されているかを示す次のレスポンスヘッダーが含まれます。
'x-powerstream-datacenter': 'atla',
'x-powerstream-localdconly': 'true'
これに加えて、データセンターを指定する初回のペイロードも送信されます。
{
    "type": "connection_metadata",
    "datacenter": "atla",
    "timestamp": 1762557264155
}
ヒント: レイテンシーを最適化するには、複数の地理的ロケーション (例:米国東海岸のアトランタ近郊と米国西海岸のポートランド近郊) から接続を構成し、それぞれで localDcOnly=true を有効にします。これにより、各データセンター内の投稿へより高速にアクセスできます。データセンター間のデータを統合するには、クライアント側でストリームを集約してください。

演算子

フィルタリングルールを設定するには、キーワードと演算子を使用します。利用可能な演算子は以下のとおりです。

フィールドベースの演算子

ユーザー演算子

OperatorSummaryExample
from:特定のユーザーからの投稿に一致しますfrom:xdevelopers or from:123456
to:特定のユーザー宛ての投稿に一致しますto:jvaleski
retweets_of:特定のユーザーのリポストに一致しますretweets_of:xdevelopers

コンテンツ演算子

OperatorSummaryExample
contains:特定のテキストやキーワードを含む投稿にマッチしますcontains:hello または contains:-2345.432
url_contains:URL に特定のテキストが含まれる投稿にマッチしますurl_contains:"com/willplayforfood"
lang:特定の言語の投稿にマッチしますlang:en

エンティティオペレーター

OperatorSummaryExample
has:特定のエンティティを含む投稿に一致します (指定可能な値: mentions, geo, links, media, lang, symbols, images, videos)has:images, has:geo, has:mentions
is:特定の種類、または特定のプロパティを持つ投稿に一致します (指定可能な値: retweet, reply)is:retweet, is:reply

ロケーション演算子

OperatorSummaryExample
place:特定の場所からの投稿に一致しますplace:"Belmont Central", place:02763fa2a7611cf3
bounding_box:地理的なバウンディングボックス内の投稿に一致しますbounding_box:[-112.424083 42.355283 -112.409111 42.792311]
point_radius:ある地点を中心とした半径内の投稿に一致しますpoint_radius:[-111.464973 46.371179 25mi], point_radius:[-111.464973 46.371179 15km]

高度/コンテンツオペレーター

OperatorSummaryExample
bio:特定の自己紹介文を持つユーザーの投稿に一致します (フレーズマッチを使用)N/A
bio_name:自己紹介文内に特定の名前を含むユーザーの投稿に一致します (フレーズマッチを使用)N/A

追加のオペレーター

OperatorSummaryExample
retweets_of_status_id:特定の投稿のリポストに一致しますretweets_of_status_id:1234567890123456789
in_reply_to_status_id:特定の投稿に対する返信に一致しますin_reply_to_status_id:1234567890123456789

フィールド以外の演算子

特殊構文演算子

演算子概要
@メンション演算子@username
フレーズマッチフレーズの完全一致検索"exact phrase"

論理演算子

OperatorSummaryExample
OR複数の式の論理和 (OR)x OR facebook
Space/AND複数の式の論理積 (AND)x facebook (両方の語が含まれている必要があります)
()複雑な式をまとめてグループ化(x OR facebook) iphone
-否定/除外x -facebook (x だが facebook は含まない)

レスポンス

Powerstream API のペイロードは、レガシー版 GNIP Powertrack API と同じ形式です。JSON レスポンスの例は次のとおりです。
[
   {
       "created_at": "Tue Mar 21 20:50:14 +0000 2006",
       "id": 20,
       "id_str": "20",
       "text": "just setting up my twttr",
       "truncated": false,
       "entities": {
           "hashtags": [],
           "symbols": [],
           "user_mentions": [],
           "urls": []
       },
       "source": "<a href=\"http://x.com\" rel=\"nofollow\">X Web Client</a>",
       "in_reply_to_status_id": null,
       "in_reply_to_status_id_str": null,
       "in_reply_to_user_id": null,
       "in_reply_to_user_id_str": null,
       "in_reply_to_screen_name": null,
       "user": {
           "id": 12,
           "id_str": "12",
           "name": "jack",
           "screen_name": "jack",
           "location": "",
           "description": "no state is the best state",
           "url": "https://t.co/ZEpOg6rn5L",
           "entities": {
               "url": {
                   "urls": [
                       {
                           "url": "https://t.co/ZEpOg6rn5L",
                           "expanded_url": "http://primal.net/jack",
                           "display_url": "primal.net/jack",
                           "indices": [
                               0,
                               23
                           ]
                       }
                   ]
               },
               "description": {
                   "urls": []
               }
           },
           "protected": false,
           "followers_count": 6427829,
           "friends_count": 3,
           "listed_count": 32968,
           "created_at": "Tue Mar 21 20:50:14 +0000 2006",
           "favourites_count": 36306,
           "utc_offset": null,
           "time_zone": null,
           "geo_enabled": true,
           "verified": false,
           "statuses_count": 30134,
           "lang": null,
           "contributors_enabled": false,
           "is_translator": false,
           "is_translation_enabled": false,
           "profile_background_color": "EBEBEB",
           "profile_background_image_url": "http://abs.twimg.com/images/themes/theme7/bg.gif",
           "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme7/bg.gif",
           "profile_background_tile": false,
           "profile_image_url": "http://pbs.twimg.com/profile_images/1661201415899951105/azNjKOSH_normal.jpg",
           "profile_image_url_https": "https://pbs.twimg.com/profile_images/1661201415899951105/azNjKOSH_normal.jpg",
           "profile_banner_url": "https://pbs.twimg.com/profile_banners/12/1742427520",
           "profile_link_color": "990000",
           "profile_sidebar_border_color": "DFDFDF",
           "profile_sidebar_fill_color": "F3F3F3",
           "profile_text_color": "333333",
           "profile_use_background_image": true,
           "has_extended_profile": true,
           "default_profile": false,
           "default_profile_image": false,
           "following": null,
           "follow_request_sent": null,
           "notifications": null,
           "translator_type": "regular",
           "withheld_in_countries": []
       },
       "geo": null,
       "coordinates": null,
       "place": null,
       "contributors": null,
       "is_quote_status": false,
       "retweet_count": 122086,
       "favorite_count": 263321,
       "favorited": false,
       "retweeted": false,
       "lang": "en"
   }
]

制限事項とベストプラクティス

  • レート制限: ルール管理は 24時間あたり 50 リクエスト。ストリーム自体に制限はありません (ただし接続数の制限が適用されます) 。
  • 再接続: 切断時は指数バックオフ方式で再接続します。
  • 監視: Connection: keep-alive ヘッダーを使用します。