Passer au contenu principal
Powerstream est notre API de streaming en temps réel la plus rapide pour accéder aux données publiques de X. Similaire à l’API GNIP Powetrack héritée, elle utilise des règles pour filtrer les Publications en fonction de mots-clés, d’opérateurs et de métadonnées. Une fois qu’une connexion HTTP persistante est établie avec l’endpoint Powerstream, vous pouvez commencer à recevoir les Publications correspondantes presque en temps réel. Actuellement, Powerstream prend en charge jusqu’à 1 000 règles et chaque règle peut comporter 2 048 caractères.

Fonctionnalités clés :

  • Diffusion de données en temps réel : recevez presque en temps réel les données correspondant à vos règles.
  • Filtrage précis : filtrez exactement les données que vous recherchez à l’aide de requêtes booléennes et d’opérateurs.
  • Diffusion : réponse JSON via l’encodage de transfert fragmenté HTTP/1.1 (chunked transfer encoding).
  • Prise en charge du centre de données local : récupérez des Publications uniquement depuis le centre de données local pour réduire la latence en évitant le décalage dû à la réplication.
L’API Powerstream est une offre premium disponible dans le cadre de certains abonnements Enterprise.Si vous souhaitez accéder à Powerstream ou en savoir plus sur nos offres Enterprise, veuillez contacter notre équipe commerciale en remplissant le formulaire de demande Enterprise. Nous serons ravis d’échanger sur la manière dont Powerstream peut répondre à vos besoins.

Démarrage rapide

Cette section explique comment démarrer rapidement avec les endpoints PowerStream en Python à l’aide de la bibliothèque requests. Installez-la via pip install requests. Tous les exemples utilisent l’authentification OAuth 2.0 par Jeton Bearer. Remplacez YOUR_BEARER_TOKEN par votre jeton réel (stockez-le de manière sécurisée, par exemple via os.getenv('BEARER_TOKEN')). Nous passerons en revue chaque endpoint avec des extraits de code. Supposons ces imports en haut du fichier :
import requests
import json
import time
import sys
import os  # Pour les variables d'environnement

Configuration

bearer_token = os.getenv('BEARER_TOKEN') or "YOUR_BEARER_TOKEN"  # Utiliser une variable d'environnement pour des raisons de sécurité
base_url = "https://api.x.com/2/powerstream"
rules_url = f"{base_url}/rules"  # Pour la gestion des règles
headers = {
   "Authorization": f"Bearer {bearer_token}",
   "Content-Type": "application/json"
}

1. Créer des règles (POST /rules)

Ajoutez des règles pour filtrer votre flux.
data = {
   "rules": [
       {
           "value": "(cat OR dog) lang:en -is:retweet",
           "tag": "pet-monitor"
       },
       # Ajoutez d'autres règles si nécessaire (jusqu'à 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. Supprimer des règles (POST /rules)

Supprimez des règles via leur ID (recommandé) ou leur valeur.
data = {
   "rules": [
       {
           "value": "(cat OR dog) lang:en -is:retweet",
           "tag": "pet-monitor"
       },
       # Ajoutez d'autres règles au besoin (jusqu'à 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}")
Astuce : pour supprimer toutes les règles, commencez par les récupérer avec GET, extrayez les identifiants, puis supprimez-les en une seule opération.

3. Récupérer les règles (GET /rules)

Récupérez toutes les règles actives.
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)

Connectez-vous au flux en temps réel de Publications. Utilisez stream=True pour une lecture ligne à ligne. Implémentez une logique de reconnexion pour améliorer la robustesse.
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
                       )
                   )

Prise en charge du centre de données local

Pour optimiser la latence, Powerstream offre une option permettant de récupérer uniquement les Publications qui ont été créées dans le centre de données local où la connexion est établie. Cela évite le décalage de réplication, ce qui se traduit par une diffusion plus rapide que pour les Publications provenant d’autres centres de données. Pour activer cette option, ajoutez le paramètre de requête ?localDcOnly=true au point de terminaison du flux (par exemple, /2/powerstream?localDcOnly=true). Le centre de données auquel vous êtes connecté sera indiqué à la fois dans la charge utile de données initiale du flux et dans un en-tête HTTP de la réponse. Pour l’utiliser dans du code :
# Pour le centre de données local uniquement :
stream_url = "https://api.x.com/2/powerstream?localDcOnly=true"
Si le paramètre localDcOnly est activé, lorsque le flux se connecte pour la première fois, il inclura les en-têtes de réponse suivants, précisant le centre de données local utilisé :
'x-powerstream-datacenter': 'atla',
'x-powerstream-localdconly': 'true'
En outre, il enverra un payload initial précisant le centre de données :
{
    "type": "connection_metadata",
    "datacenter": "atla",
    "timestamp": 1762557264155
}
Conseil : Pour optimiser la latence, configurez des connexions depuis différentes zones géographiques (par exemple, une près d’Atlanta sur la côte Est des États-Unis et une autre près de Portland sur la côte Ouest), en activant localDcOnly=true pour chacune. Cela permet un accès plus rapide aux Publications depuis chaque centre de données. Agrégez les flux de votre côté pour combiner les données provenant de plusieurs centres de données.

Opérateurs

Pour définir des règles de filtrage, vous pouvez utiliser des mots-clés et des opérateurs. Consultez la liste des opérateurs disponibles ci-dessous.

Opérateurs par champ

Opérateurs utilisateur

OperatorSummaryExample
from:Sélectionne les publications provenant d’un utilisateur spécifiquefrom:xdevelopers ou from:123456
to:Sélectionne les publications adressées à un utilisateur spécifiqueto:jvaleski
retweets_of:Sélectionne les republications d’un utilisateur spécifiqueretweets_of:xdevelopers

Opérateurs de contenu

OpérateurRésuméExemple
contains:Renvoie les publications contenant un texte ou des mots-clés spécifiquescontains:hello ou contains:-2345.432
url_contains:Renvoie les publications dont les URL contiennent un texte spécifiqueurl_contains:"com/willplayforfood"
lang:Renvoie les publications dans des langues spécifiqueslang:en

Opérateurs d’entités

OpérateurDescriptionExemple
has:Renvoie les Publications contenant des entités spécifiques (Options : mentions, geo, links, media, lang, symbols, images, videos)has:images, has:geo, has:mentions
is:Renvoie les Publications d’un type spécifique ou possédant des propriétés spécifiques (Options : retweet, reply)is:retweet, is:reply

Opérateurs de localisation

OperatorSummaryExample
place:Correspond aux Publications provenant de lieux spécifiquesplace:"Belmont Central", place:02763fa2a7611cf3
bounding_box:Correspond aux Publications situées dans une zone géographique délimitéebounding_box:[-112.424083 42.355283 -112.409111 42.792311]
point_radius:Correspond aux Publications situées dans un rayon autour d’un pointpoint_radius:[-111.464973 46.371179 25mi], point_radius:[-111.464973 46.371179 15km]

Opérateurs avancés/de contenu

OpérateurRésuméExemple
bio:Renvoie les publications d’utilisateurs dont la bio contient un contenu spécifique (utilise la recherche par expression)N/A
bio_name:Renvoie les publications d’utilisateurs dont la bio contient un nom spécifique (utilise la recherche par expression)N/A

Opérateurs supplémentaires

OpérateurRésuméExemple
retweets_of_status_id:Correspond aux republications d’une publication spécifiqueretweets_of_status_id:1234567890123456789
in_reply_to_status_id:Correspond aux réponses à une publication spécifiquein_reply_to_status_id:1234567890123456789

Opérateurs sans champ

Opérateurs de syntaxe spéciale

OpérateurDescriptionExemple
@Opérateur de mention@username
Correspondance de phraseFait correspondre des expressions exactes"exact phrase"

Opérateurs logiques

OperatorSummaryExample
OROU logique entre expressionsx OR facebook
Space/ANDET logique entre expressionsx facebook (les deux termes doivent être présents)
()Regroupement d’expressions complexes(x OR facebook) iphone
-Négation/exclusionx -facebook (x mais pas facebook)

Réponses

La charge utile de l’API Powestream est au même format que celle de l’ancienne API GNIP Powertrack. Voici un exemple de réponse JSON :
[
   {
       "created_at": "Tue Mar 21 20:50:14 +0000 2006",
       "id": 20,
       "id_str": "20",
       "text": "je configure juste mon 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"
   }
]

Limites & Bonnes pratiques

  • Limites de taux : 50 requêtes/24 h pour la gestion des règles ; aucune limite pour les flux (mais des limites de connexion s’appliquent).
  • Reconnexion : backoff exponentiel en cas de déconnexion.
  • Surveillance : utilisez les en-têtes Connection: keep-alive.