如何避免HTTP错误429(请求太多)python

2024-05-08 21:47:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我正试图使用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")

Tags: inpybrimportcomtrueurlexample
3条回答

编写这段代码解决了我的问题:

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

接收状态429不是错误,而是另一个服务器“友好地”要求您停止垃圾邮件请求。显然,您的请求率太高,服务器不愿意接受。

您不应该试图“躲开”这一点,甚至试图通过欺骗您的IP来规避服务器安全设置,您应该只尊重服务器的回答,不发送太多请求。

如果一切设置正确,您还将收到一个“Retry after”头和429响应。此头指定在进行另一个调用之前应等待的秒数。处理这个“问题”的正确方法是阅读这个标题并让进程睡眠那么多秒。

您可以在这里找到有关状态429的更多信息:http://tools.ietf.org/html/rfc6585#page-3

正如MRA所说,您不应该试图回避一个429 Too Many Requests,而应该相应地处理它。根据您的用例,您有几个选项:

1)睡眠您的过程。服务器通常在响应中包含一个Retry-after头,其中包含您在重试之前应该等待的秒数。请记住,睡眠进程可能会导致问题,例如在任务队列中,您应该稍后重试该任务,以释放工作进程的其他资源。

2)Exponential backoff。如果服务器不告诉您等待多长时间,您可以使用中间不断增加的暂停来重试请求。受欢迎的任务队列芹菜具有此功能built right-in

3)Token bucket。如果事先知道在给定时间内可以发出多少请求,则此技术非常有用。每次访问API时,首先从bucket中获取一个令牌。桶是以恒定的速率重新装满的。如果bucket是空的,您知道在再次命中API之前必须等待。令牌桶通常在另一端(API)实现,但也可以将它们用作代理,以避免获得429 Too Many Requests。芹菜的rate_limit功能使用令牌桶算法。

下面是一个使用指数退避和速率限制/令牌桶的Python/芹菜应用程序示例:

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

相关问题 更多 >