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


93

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

6
주위에 방법이 없습니다. 이것은 서버 측에서 얼마나 많은 요청 / 시간 단위를 작성하는지 추적하는 시행입니다. 이 단위를 초과하면 일시적으로 차단됩니다. 일부 서버는이 정보를 헤더로 보내지 만 이러한 경우는 드뭅니다. 서버에서받은 헤더를 확인하고 사용 가능한 정보를 사용합니다. 그렇지 않으면 잡히지 않고 망치질 수있는 속도를 확인하고 sleep.
Torxed apr.

답변:


158

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

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

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

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


23
글쎄, 아무도 모든 웹 서버가 올바르게 구성되었다고 말한 적이 없습니다. 또한 대부분의 속도 제한 기가 IP로 방문자를 식별하므로 IP가 동적으로 공유되는 시나리오에서 문제가 발생할 수 있습니다. 너무 많은 요청을 보내지 않았다고 확신하지만 상태 429를 계속 수신하는 경우 사이트 관리자에게 문의하는 것이 좋습니다.
MRA

2
"Retry-after"헤더를 언급 해 주셔서 감사합니다. 나는 그 값을 얻는 방법을보기위한 코드 예제를 좋아할 것이다. (나는 urllib를 사용하여 OP 기계화를하고 있었다. 두 경우 모두 헤더가 제기 된 예외에 포함되어 있지 않다고 생각한다)
MacFreek

@MacFreek 특정 Python 코드 예제가 준비되어 있지 않지만 일반적으로 응답 헤더를 검색하는 방법에 대한 몇 가지 예제를이 질문에 대한 답변에서 가져올 수 있다고 가정합니다. stackoverflow.com/q/843392
MRA

@MRA 감사합니다. 예외에서도 헤더를 사용할 수 있음을 발견했습니다.을 잡은 후 에서 적어도 urllib2에 대해 HTTPError as my_exception사용할 수 있습니다 my_exception.headers.
MacFreek

38

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

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


26
이 답변은 반대 투표이지만 일부 사이트는 다른 사람의 남용으로 인해 사용자 에이전트가 금지되면 자동으로 오류 코드 429를 반환합니다. 몇 개의 요청 만 보냈 는데도 오류 코드 429가 표시되면 사용자 에이전트를 다른 것으로 설정해보십시오.
Ferry Boender

7
또한 추가하고 싶습니다. 일부 사이트는 사용자 에이전트가 전송되지 않는 한 요청을 명백히 거부하며 무수히 많은 다른 응답을 얻을 수 있습니다. 503/403 / 일부 일반 색인 페이지.
user3791372

1
이것을 확인할 수 있습니다. 그냥 레딧와 난 항상 오류 코드 429 얻고 있었다 사용자 에이전트를 설정하지 않고 파이썬 인터페이스하려고
Karrq

1
설명을 추가해 주시겠습니까?
Tokci

"이 코드 조각을 작성"하는 곳은 어디입니까? 이 솔루션에는 더 자세한 정보가 필요합니다.
Joe McLean

29

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

9

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

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

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


8
이것이 내가 항상 API 사용자가 요청을하기 위해 키를 등록하도록 요구하는 이유입니다. 이렇게하면 IP가 아닌 키로 요청을 제한 할 수 있습니다. 다른 키를 등록하는 것이 더 높은 제한을받을 수있는 유일한 방법입니다.
Mnebuerquo

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.