Évitez la limitation de L'API Twitter avec Tweepy

j'ai vu dans une question sur Stack Exchange que la limitation peut être fonction du nombre de requêtes par 15 minutes et dépend aussi de la complexité de l'algorithme, sauf qu'il ne s'agit pas d'un problème complexe.

alors j'utilise ce code:

import tweepy
import sqlite3
import time

db = sqlite3.connect('data/MyDB.db')

# Get a cursor object
cursor = db.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS MyTable(id INTEGER PRIMARY KEY, name TEXT, geo TEXT, image TEXT, source TEXT, timestamp TEXT, text TEXT, rt INTEGER)''')
db.commit()

consumer_key = ""
consumer_secret = ""
key = ""
secret = ""

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(key, secret)

api = tweepy.API(auth)

search = "#MyHashtag"

for tweet in tweepy.Cursor(api.search,
                           q=search,
                           include_entities=True).items():
    while True:
        try:
            cursor.execute('''INSERT INTO MyTable(name, geo, image, source, timestamp, text, rt) VALUES(?,?,?,?,?,?,?)''',(tweet.user.screen_name, str(tweet.geo), tweet.user.profile_image_url, tweet.source, tweet.created_at, tweet.text, tweet.retweet_count))
        except tweepy.TweepError:
                time.sleep(60 * 15)
                continue
        break
db.commit()
db.close()

j'ai toujours le Twitter de limitation d'erreur:

Traceback (most recent call last):
  File "stream.py", line 25, in <module>
    include_entities=True).items():
  File "/usr/local/lib/python2.7/dist-packages/tweepy/cursor.py", line 153, in next
    self.current_page = self.page_iterator.next()
  File "/usr/local/lib/python2.7/dist-packages/tweepy/cursor.py", line 98, in next
    data = self.method(max_id = max_id, *self.args, **self.kargs)
  File "/usr/local/lib/python2.7/dist-packages/tweepy/binder.py", line 200, in _call
    return method.execute()
  File "/usr/local/lib/python2.7/dist-packages/tweepy/binder.py", line 176, in execute
    raise TweepError(error_msg, resp)
tweepy.error.TweepError: [{'message': 'Rate limit exceeded', 'code': 88}]
24
demandé sur Peter Mortensen 2014-01-23 16:53:21

4 réponses

Le problème est que votre try: except: block est au mauvais endroit. Insérer des données dans la base de données ne soulèvera jamais un TweepError - c'est une itération sur Cursor.items() qui sera. Je suggère de modifier votre code pour appeler le next méthode Cursor.items() dans une boucle infinie. Cet appel devrait être placé dans le try: except: bloc, car il peut déclencher une erreur.

Ici (à peu près) ce que le code doit ressembler à ça:

# above omitted for brevity
c = tweepy.Cursor(api.search,
                       q=search,
                       include_entities=True).items()
while True:
    try:
        tweet = c.next()
        # Insert into db
    except tweepy.TweepError:
        time.sleep(60 * 15)
        continue
    except StopIteration:
        break

cela fonctionne parce que lorsque Tweepy soulève un TweepError, il n'a pas mis à jour les données du curseur. La prochaine fois qu'il fait la demande, il utilisera les mêmes paramètres que la demande qui a déclenché la limite de débit, en la répétant effectivement jusqu'à ce qu'elle passe.

23
répondu Aaron Hill 2014-03-11 01:26:16

pour toute personne qui trébuche sur ce sujet sur Google, tweepy 3.2 + a des paramètres supplémentaires pour le tweepy.api classe, en particulier:

  • wait_on_rate_limit - qu'il faille ou non attendre automatiquement que les limites de taux se rétablissent
  • wait_on_rate_limit_notify - qu'il s'agisse ou non d'imprimer un avis lorsque Tweepy attend que les limites de taux se rétablissent

paramétrage de ces drapeaux à True délègue l'attente à L'instance API, ce qui est suffisant pour le plus simple des cas d'utilisation.

46
répondu Dan Nguyen 2015-08-06 22:36:04

si vous voulez éviter les erreurs et respecter la limite de taux, vous pouvez utiliser la fonction suivante qui prend votre api objet comme argument. Il récupère le nombre de demandes restantes du même type que la dernière demande et attend jusqu'à ce que la limite de vitesse ait été réinitialisée si désiré.

def test_rate_limit(api, wait=True, buffer=.1):
    """
    Tests whether the rate limit of the last request has been reached.
    :param api: The `tweepy` api instance.
    :param wait: A flag indicating whether to wait for the rate limit reset
                 if the rate limit has been reached.
    :param buffer: A buffer time in seconds that is added on to the waiting
                   time as an extra safety margin.
    :return: True if it is ok to proceed with the next request. False otherwise.
    """
    #Get the number of remaining requests
    remaining = int(api.last_response.getheader('x-rate-limit-remaining'))
    #Check if we have reached the limit
    if remaining == 0:
        limit = int(api.last_response.getheader('x-rate-limit-limit'))
        reset = int(api.last_response.getheader('x-rate-limit-reset'))
        #Parse the UTC time
        reset = datetime.fromtimestamp(reset)
        #Let the user know we have reached the rate limit
        print "0 of {} requests remaining until {}.".format(limit, reset)

        if wait:
            #Determine the delay and sleep
            delay = (reset - datetime.now()).total_seconds() + buffer
            print "Sleeping for {}s...".format(delay)
            sleep(delay)
            #We have waited for the rate limit reset. OK to proceed.
            return True
        else:
            #We have reached the rate limit. The user needs to handle the rate limit manually.
            return False 

    #We have not reached the rate limit
    return True
16
répondu Till Hoffmann 2014-08-05 15:34:42

il suffit de remplacer

api = tweepy.API(auth)

api = tweepy.API(auth, wait_on_rate_limit=True)
1
répondu Mayank Khullar 2018-02-14 19:36:22