[python] 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) 수면 과정 . 서버는 일반적으로 Retry-after재 시도하기 전에 기다려야하는 시간 (초)과 함께 응답에 헤더를 포함합니다 . 프로세스를 휴면하면 문제가 발생할 수 있습니다 (예 : 작업 대기열에서). 대신 나중에 작업을 재 시도하여 작업자가 다른 작업을 수행 할 수 있도록해야합니다.

2) 지수 백 오프 . 서버가 대기 시간을 알려주지 않는 경우 중간에 일시 중지를 늘려 요청을 재 시도 할 수 있습니다. 인기있는 작업 대기열 Celery에는이 기능이 내장되어 있습니다.

3) 토큰 버킷 . 이 기술은 주어진 시간에 얼마나 많은 요청을 할 수 있는지 미리 알고있는 경우에 유용합니다. API에 액세스 할 때마다 먼저 버킷에서 토큰을 가져옵니다. 버킷은 일정한 비율로 다시 채워집니다. 버킷이 비어 있으면 API를 다시 사용하기 전에 기다려야한다는 것을 알고 있습니다. 토큰 버킷은 일반적으로 다른 쪽 끝 (API)에서 구현되지만 429 Too Many Requests. Celery의 rate_limit 기능은 토큰 버킷 알고리즘을 사용합니다.

다음은 지수 백 오프 및 속도 제한 / 토큰 버킷을 사용하는 Python / Celery 앱의 예입니다.

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


답변

또 다른 해결 방법은 일종의 공용 VPN 또는 Tor 네트워크를 사용하여 IP를 스푸핑하는 것입니다. 이것은 IP 수준에서 서버의 속도 제한을 가정하는 것입니다.

urllib2와 함께 tor을 사용하는 방법을 보여주는 간단한 블로그 게시물이 있습니다.

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


답변

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


답변