HTTP FOUT 429 (te veel verzoeken) Python vermijden

Ik probeer Python te gebruiken om in te loggen op een website en informatie verzamelt uit verschillende webpagina’s en ik krijg de volgende foutmelding:

Traceback (most recent call last):
  File "extract_test.py", line 43, in <module>
    response=br.open(v)
  File "/usr/local/lib/python2.7/dist-packages/mechanize/_mechanize.py", line 203, in open
    return self._mech_open(url, data, timeout=timeout)
  File "/usr/local/lib/python2.7/dist-packages/mechanize/_mechanize.py", line 255, in _mech_open
    raise response
mechanize._response.httperror_seek_wrapper: HTTP Error 429: Unknown Response Code

Ik gebruikte time.sleep()En het werkt, maar het lijkt niet -intelligent en onbetrouwbaar, is er een andere manier om deze fout te ontwijken?

Hier is mijn code:

import mechanize
import cookielib
import re
first=("example.com/page1")
second=("example.com/page2")
third=("example.com/page3")
fourth=("example.com/page4")
## I have seven URL's I want to open
urls_list=[first,second,third,fourth]
br = mechanize.Browser()
# Cookie Jar
cj = cookielib.LWPCookieJar()
br.set_cookiejar(cj)
# Browser options 
br.set_handle_equiv(True)
br.set_handle_redirect(True)
br.set_handle_referer(True)
br.set_handle_robots(False)
# Log in credentials
br.open("example.com")
br.select_form(nr=0)
br["username"] = "username"
br["password"] = "password"
br.submit()
for url in urls_list:
        br.open(url)
        print re.findall("Some String")

Antwoord 1, Autoriteit 100%

Het ontvangen van een status 429 is geen fout, het is de andere server die u vriendelijk vraagt om te stoppen met het spammen van verzoeken. Het is duidelijk dat uw aantal verzoeken te hoog was en de server is niet bereid dit te accepteren.

Je moet dit niet proberen te “ontwijken”, of zelfs proberen de beveiligingsinstellingen van de server te omzeilen door te proberen je IP te vervalsen, je moet gewoon het antwoord van de server respecteren door niet te veel verzoeken te verzenden.

Als alles goed is ingesteld, heb je ook een “Retry-after”-header ontvangen samen met het 429-antwoord. Deze kop specificeert het aantal seconden dat u moet wachten voordat u opnieuw belt. De juiste manier om met dit “probleem” om te gaan, is door deze koptekst te lezen en uw proces zoveel seconden te laten slapen.

Meer informatie over status 429 vindt u hier: http://tools.ietf.org/html/rfc6585 #pagina-3


Antwoord 2, autoriteit 27%

Het schrijven van dit stukje code loste mijn probleem op:

requests.get(link, headers = {'User-agent': 'your bot 0.1'})

Antwoord 3, autoriteit 20%

Zoals MRA al zei, moet je niet proberen een 429 Too Many Requestste ontwijken, maar het in plaats daarvan dienovereenkomstig behandelen. Je hebt verschillende opties, afhankelijk van je gebruik:

1) Slaap je proces in. De server bevat meestal een Retry-afterheader in het antwoord met het aantal seconden dat je moet wachten voordat je het opnieuw probeert. Houd er rekening mee dat het slapen van een proces problemen kan veroorzaken, b.v. in een taakwachtrij, waar u de taak in plaats daarvan op een later tijdstip opnieuw moet proberen om de werknemer vrij te maken voor andere dingen.

2) Exponentiële uitstel. Als de server u niet vertelt hoe lang u moet wachten, kunt u uw verzoek opnieuw proberen met toenemende pauzes ertussen. De populaire taakwachtrij Celery heeft deze functie rechts ingebouwd.

3) Token-bucket. Deze techniek is handig als je van tevoren weet hoeveel verzoeken je in een bepaalde tijd kunt doen. Elke keer dat u de API opent, haalt u eerst een token op uit de bucket. De emmer wordt met een constante snelheid bijgevuld. Als de bucket leeg is, weet je dat je moet wachten voordat je weer op de API kunt klikken. Token-buckets worden meestal aan de andere kant (de API) geïmplementeerd, maar je kunt ze ook als proxy gebruiken om te voorkomen dat je ooit een 429 Too Many Requestskrijgt. De rate_limit-functie van Celery gebruikt een token-bucket-algoritme.

Hier is een voorbeeld van een Python/Celery-app die exponentiële uitstel en snelheidsbeperkende/token-bucket gebruikt:

class TooManyRequests(Exception):
"""Too many requests"""
@task(
   rate_limit='10/s',
   autoretry_for=(ConnectTimeout, TooManyRequests,),
   retry_backoff=True)
def api(*args, **kwargs):
  r = requests.get('placeholder-external-api')
  if r.status_code == 429:
    raise TooManyRequests()

Antwoord 4, autoriteit 6%

if response.status_code == 429:
  time.sleep(int(response.headers["Retry-After"]))

Antwoord 5, autoriteit 5%

Een andere oplossing zou zijn om je IP te vervalsen met een soort openbaar VPN- of Tor-netwerk. Dit zou uitgaan van de snelheidsbeperking op de server op IP-niveau.

Er is een korte blogpost die een manier laat zien om tor samen met urllib2 te gebruiken:

http://blog.flip-edesign.com/?p=119


Antwoord 6, autoriteit 4%

Ik heb een leuke oplossing gevonden voor IP-blokkeringbij het schrapen van sites. Hiermee kunt u een Scraper voor onbepaalde tijd uitvoeren door deze vanuit Google App Engine uit te voeren en automatisch opnieuw te implementeren wanneer u een 429 krijgt.

Bekijk dit artikel


Antwoord 7

In veel gevallen is het onethisch om door te gaan met het verzamelen van gegevens van een website, zelfs als de server u daarom vraagt. In de gevallen waarin dit niet het geval is, kunt u een lijst met openbare proxy’s gebruiken om een website met veel verschillende IP-adressen te schrapen.

Other episodes