É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}]
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.
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établissentwait_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.
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
il suffit de remplacer
api = tweepy.API(auth)
api = tweepy.API(auth, wait_on_rate_limit=True)