Program Club

HTTP 오류 429 (너무 많은 요청)를 피하는 방법

proclub 2020. 10. 28. 21:15
반응형

HTTP 오류 429 (너무 많은 요청)를 피하는 방법


Python을 사용하여 웹 사이트에 로그인하고 여러 웹 페이지에서 정보를 수집하려고하는데 다음 오류가 발생합니다.

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

나는 사용 time.sleep()하고 작동하지만 지능이없고 신뢰할 수없는 것처럼 보입니다.이 오류를 피할 다른 방법이 있습니까?

내 코드는 다음과 같습니다.

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

상태 429를받는 것은 오류 가 아니라 다른 서버에서 "친절하게"스팸 요청을 중지 해달라고 요청하는 것입니다. 분명히 귀하의 요청 비율이 너무 높았으며 서버는이를 수락하지 않습니다.

이를 "회피"하거나 IP를 스푸핑하여 서버 보안 설정을 우회하려고해서는 안됩니다. 너무 많은 요청을 보내지 않음으로써 서버의 응답을 존중해야합니다.

모든 것이 올바르게 설정되면 429 응답과 함께 "Retry-after"헤더도 수신됩니다. 이 헤더는 다른 호출을하기 전에 기다려야하는 시간 (초)을 지정합니다. 이 "문제"를 처리하는 적절한 방법은이 헤더를 읽고 그 수 초 동안 프로세스를 휴면하는 것입니다.

상태 429에 대한 자세한 정보는 http://tools.ietf.org/html/rfc6585#page-3 에서 확인할 수 있습니다.


이 코드를 작성하면 문제가 해결되었습니다.

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


MRA가 말했듯이, a를 피하려고하지 429 Too Many Requests말고 그에 따라 처리하십시오. 사용 사례에 따라 몇 가지 옵션이 있습니다.

1) Sleep your process. The server usually includes a Retry-after header in the response with the number of seconds you are supposed to wait before retrying. Keep in mind that sleeping a process might cause problems, e.g. in a task queue, where you should instead retry the task at a later time to free up the worker for other things.

2) Exponential backoff. If the server does not tell you how long to wait, you can retry your request using increasing pauses in between. The popular task queue Celery has this feature built right-in.

3) Token bucket. This technique is useful if you know in advance how many requests you are able to make in a given time. Each time you access the API you first fetch a token from the bucket. The bucket is refilled at a constant rate. If the bucket is empty, you know you'll have to wait before hitting the API again. Token buckets are usually implemented on the other end (the API) but you can also use them as a proxy to avoid ever getting a 429 Too Many Requests. Celery's rate_limit feature uses a token bucket algorithm.

Here is an example of a Python/Celery app using exponential backoff and rate-limiting/token bucket:

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

Another workaround would be to spoof your IP using some sort of Public VPN or Tor network. This would be assuming the rate-limiting on the server at IP level.

There is a brief blog post demonstrating a way to use tor along with urllib2:

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

참고URL : https://stackoverflow.com/questions/22786068/how-to-avoid-http-error-429-too-many-requests-python

반응형