[PYTHON] Je ne peux pas utiliser le paramètre "next_results" dans l'API de recherche d'API Twitter! ?? Causes et remèdes

J'étais accro à la collecte de tweets en utilisant l'API Twitter API de recherche. !! Il y a un écueil dans un lieu inattendu ...

À propos de l'API de recherche Twitter

Cette fois, j'ai utilisé l'API de recherche pour obtenir des tweets. Un bref résumé des spécifications de l'API de recherche.

Il existe trois types d'API de recherche.

Cette fois, nous utiliserons l'API de recherche standard, qui peut être utilisée gratuitement.

Fonctionnalités de l'API de recherche standard

Paramètres de demande

Paramètres La description Remarques
q Requête de recherche (obligatoire) Une recherche similaire à la recherche de tweet sur Twitter est possible, seules les chaînes de caractères sont possibles
geocode Où tu as tweeté Spécifié par latitude, longitude, rayon
lang Spécifier la langue du tweet
locale Spécification du langage de requête Actuellement en japonaisjaUniquement valable
result_type Spécifiez le type de tweet acquis recentPuis le dernier tweet,popularPuis des tweets populaires,mixedPuis les deux
count Précisez le nombre d'acquisitions La valeur par défaut est 15 et le maximum est 100.
until Spécifier l'heure du tweet YYYY-MM-Recevez des tweets avant le DD (impossible avant 7 jours)
since_id Spécification de la valeur d'identification Obtenez des tweets avec des valeurs d'ID supérieures à la valeur d'ID spécifiée
max_id Spécification de la valeur d'identification Obtenez des tweets avec des valeurs d'ID inférieures à la valeur d'ID spécifiée
include_entities entitiesAvec ou sans falseSi vous spécifiez, obtenez des tweets sans inclure les informations sur les entités

Paramètres de réponse

Paramètres La description Remarques
statuses Liste des tweets L'objet Tweet est stocké dans une liste
search_metadata Rechercher des métadonnées Contient des métadonnées de recherche

Exemple de réponse

python


{
  "statuses": [
(Omis car il s'agit d'un objet tweet),
    ...
  ],
  "search_metadata": {
    "max_id": 250126199840518145,
    "since_id": 24012619984051000,
    "refresh_url": "?since_id=250126199840518145&q=%23freebandnames&result_type=mixed&include_entities=1",
    "next_results": "?max_id=249279667666817023&q=%23freebandnames&count=4&include_entities=1&result_type=mixed",
    "count": 4,
    "completed_in": 0.035,
    "since_id_str": "24012619984051000",
    "query": "%23freebandnames",
    "max_id_str": "250126199840518145"
  }
}

Occurrence du problème

Contexte

J'essayais de collecter beaucoup de tweets avec le hashtag # Qiita.

Cependant, l'API de recherche standard ne peut récupérer que 100 tweets en une seule demande. Par conséquent, j'ai essayé d'obtenir 1000 tweets en appelant l'API de manière récursive en utilisant le paramètre de requête next_results. Une requête est stockée dans next_results, et en exécutant cette requête, vous pouvez obtenir le 101e tweets et les suivants. En d'autres termes

Request-> Response-> Parse next_results-> Aller au paramètre de requête suivant-> Request-> ...

Je le ferai jusqu'à ce que j'obtienne 1000 caisses.

(Référence: Obtenez plus de 100 tweets avec la recherche / tweets de l'API Twitter (PHP))

Cependant, ** les requêtes ne sont exécutées que 3 fois ** et seuls 200 tweets peuvent être pris! (Le nombre de tweets acquis est de 0 dans la troisième réponse) Même s'il y a clairement plus de 200 tweets ...

programme

Le code a été écrit en Python. De plus, diverses clés API sont enregistrées dans des variables d'environnement.

get_tweet.py


from requests_oauthlib import OAuth1Session
import os
import json

#Installation de la clé API
CONSUMER_KEY = XXXXXXXXXXXXXXXXXXXXXX #API key 
CONSUMER_SECRET = XXXXXXXXXXXXXXXXXXXXXX #API secret
ACCESS_TOKEN = XXXXXXXXXXXXXXXXXXXXXX
ACCESS_SECRET = XXXXXXXXXXXXXXXXXXXXXX

#URL pour recevoir des tweets
SEARCH_URL = 'https://api.twitter.com/1.1/search/tweets.json'


def search(params):
    twitter = OAuth1Session(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_SECRET)
    req = twitter.get(SEARCH_URL, params = params)
    tweets = json.loads(req.text)
    return tweets

#Analyser en PHP_Au lieu de la fonction str
def parseToParam(parse_str, parse=None):
    if parse is None:
        parse = '&'
    return_params = {}
    parsed_str = parse_str.split(parse)
    for param_string in parsed_str:
        param, value = param_string.split('=', 1)
        return_params[param] = value
    return return_params

def main():
    search_word = '#Qiita'
    tweet_data = []

    # Tweet Search
    params = {
                'q'  : search_word,
            'count'  : 100,
             }
    tweet_count = 0

    while tweet_count < 1000:
        tweets = search(params)
        for tweet in tweets['statuses']:
            tweet_data.append(tweet)
        # tweets['search_metadata']['next_results']Analyser le paramètre
        if 'next_results' in tweets['search_metadata'].keys():
            next_results = tweets['search_metadata']['next_results']
            next_results = next_results.lstrip('?') #Au début?Effacer
            params = parseToParam(next_results)
            tweet_count += len(tweets['statuses'])
        else:
            break

if __name__=='__main__':
    main()

Enquête sur la cause

Puisque le paramètre de réponse next_results est utilisé pour le paramètre de requête suivant, --Paramètres de demande --Paramètre de réponse next_results Vérifiez les deux points.

Vérifier les paramètres de demande et les paramètres de réponse

Première fois Paramètres de demande

{
  'q'    : '#Qiita',
  'count': 100
}

Paramètre de réponse next_results

?max_id=1250763045871079425&q=%23Qiita&count=100&include_entities=1

Deuxième fois Paramètres de demande

{
 'max_id': '1250763045871079425', 
  'q'    : '%23Qiita',
  'count': 100,
  'include_entities': '1'
}

Paramètre de réponse next_results

?max_id=1250673475351572480&q=%2523Qiita&count=100&include_entities=1

Troisième fois Paramètres de demande

{
 'max_id': '1250673475351572480', 
  'q'    : '%2523Qiita',
  'count': 100,
  'include_entities': '1'
}

Paramètre de réponse next_results

None

Résultats du sondage

Apparemment, la même requête est héritée à l'origine #Qiita%23Qiita%2523Qiita Il semble que la requête change.

# Qiita et% 23Qiita sont compatibles l'un avec l'autre par encodage d'URL, mais% 2523Qiita est une requête complètement différente. (Vous pouvez le vérifier en essayant l'encodage / décodage à ici.)

C'est, Il semble que la cause du problème soit que **% est décodé ** dans le processus de % 23Qiita% 2523Qiita.

Solution

Après avoir analysé le paramètre de réponse next_results, remplacez **% 25 dans le paramètre de requête par% **.

Modification du programme

Ajout du traitement de remplacement des paramètres dans l'instruction while

get_tweet.py


    while tweet_count < 1000:
        tweets = search(params)
        for tweet in tweets['statuses']:
            tweet_data.append(tweet)
        # tweets['search_metadata']['next_results']Analyser le paramètre
        if 'next_results' in tweets['search_metadata'].keys():
            next_results = tweets['search_metadata']['next_results']
            next_results = next_results.lstrip('?') #Au début?Effacer
            params = parseToParam(next_results)
            # %Ajout de 25 processus de remplacement
            params['q'] = params['q'].replace('%25', '%') 
            tweet_count += len(tweets['statuses'])
        else:
            break

Résumé

Dans la requête q incluse dans le paramètre de réponse next_results,% après le codage de l'URL a été codé de manière supplémentaire. Par conséquent, l'héritage des requêtes ne fonctionnait pas et il y avait un problème pour obtenir des tweets.

La solution était de restaurer le% extra-encodé dans next_results avec remplacement de chaîne.

référence

Documentation officielle de l'API Twitter https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets Traduction japonaise du document développeur Twitter http://westplain.sakuraweb.com/translate/twitter/Documentation/REST-APIs/Public-API/GET-search-tweets.cgi Obtenez plus de 100 tweets avec la recherche / tweets de l'API Twitter (PHP) https://blog.apar.jp/php/3007/ Encodage / décodage d'URL https://tech-unlimited.com/urlencode.html

Recommended Posts

Je ne peux pas utiliser le paramètre "next_results" dans l'API de recherche d'API Twitter! ?? Causes et remèdes
Je ne peux pas utiliser la commande darknet dans Google Colaboratory!
Accéder à l'API Twitter avec Python
Tweet à l'aide de l'API Twitter en Python
Exemple de code pour obtenir oauth_token et oauth_token_secret de l'API Twitter en Python 2.7
Je ne peux pas obtenir l'élément dans Selenium!
Utiliser l'API Twitter (enregistrement de compte API et acquisition de tweet)
Je ne peux pas saisir de caractères dans la zone de texte! ?? !! ?? !! !! ??
C'est trop facile d'accéder à l'API Twitter avec rauth et je l'ai ...
J'ai étudié le temps de calcul de "X dans la liste" (recherche linéaire / recherche dichotomique) et "X dans l'ensemble"
Exploration avec Python et Twitter API 1 - Fonction de recherche simple
Utiliser l'API de recherche de la Bibliothèque du Parlement national en Python
[Note] Le module installé ne peut pas être appelé dans jupyter.
Je veux utiliser le jeu de données R avec python
Avant de le savoir, je ne pouvais pas utiliser de traits d'union dans l'ID client de l'API Channel de GAE.
Essayez d'utiliser l'API Twitter rapidement et facilement avec Python
J'ai essayé la gestion du suivi avec l'API Twitter et Python (facile)
Recherchez le pandas.DataFrame avec une variable et obtenez la ligne correspondante.
Rationalisez la collecte d'informations avec l'API Twitter et les robots Slack
J'ai essayé d'illustrer le temps et le temps du langage C
J'ai essayé de programmer le test du chi carré en Python et Java.
Je n'arrive pas à me connecter à la page d'administration avec Django 3
J'ai implémenté N-Queen dans différentes langues et mesuré la vitesse