tutorial bot python python-2.7 twitter tweepy

python - bot - tweepy tutorial



Evitar la limitaciĆ³n de Twitter API con Tweepy (4)

Vi en alguna pregunta en Stack Exchange que la limitación puede ser una función del número de solicitudes por 15 minutos y también depende de la complejidad del algoritmo, excepto que no es complejo.

Entonces uso este código:

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()

Siempre recibo el error de limitación de Twitter:

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}]


El problema es que su try: except: bloqueo está en el lugar equivocado. Insertar datos en la base de datos nunca TweepError un TweepError ; se Cursor.items() sobre Cursor.items() . Sugeriría refactorizar su código para llamar al next método de Cursor.items() en un bucle infinito. Esa llamada debe colocarse en el try: except: bloquear, ya que puede generar un error.

Aquí está (más o menos) cómo debería verse el código:

# 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

Esto funciona porque cuando Tweepy genera un TweepError , no ha actualizado ninguno de los datos del cursor. La próxima vez que realice la solicitud, utilizará los mismos parámetros que la solicitud que desencadenó el límite de frecuencia, repitiéndolo de manera efectiva hasta que finalice.


Para cualquiera que se tropiece con esto en Google, tweepy 3.2+ tiene parámetros adicionales para la clase tweepy.api , en particular:

  • wait_on_rate_limit : si se espera o no automáticamente los límites de velocidad para reponer
  • wait_on_rate_limit_notify - Si se imprime o no una notificación cuando Tweepy está esperando que se carguen los límites de la tasa

Establecer estos indicadores en True delegará la espera a la instancia de la API, que es lo suficientemente buena para la mayoría de los casos de uso simple.


Si desea evitar errores y respetar el límite de velocidad, puede usar la siguiente función que toma su objeto api como argumento. Recupera el número de solicitudes restantes del mismo tipo que la última solicitud y espera hasta que se haya restablecido el límite de velocidad si así lo desea.

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


Simplemente reemplace

api = tweepy.API(auth)

con

api = tweepy.API(auth, wait_on_rate_limit=True)