如何避免 HTTP 错误429(请求过多) 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")
380470 次浏览

另一个解决办法是使用某种公共 VPN 或 Tor 网络来欺骗您的 IP。这将假设服务器上 IP 级别的速率限制。

有一篇简短的博客文章展示了一种使用 tor 和 urllib2的方法:

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

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

您不应该寻求“规避”这一点,甚至尝试规避服务器的安全设置,试图欺骗您的 IP,您应该尊重服务器的答案,不要发送太多的请求。

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

你可以在这里找到更多关于状态429的信息: https://www.rfc-editor.org/rfc/rfc6585#page-3

在请求修复我的问题时编写这段代码:

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

这是因为当没有提供用户代理时,站点有时会返回“请求过多(429)”错误。例如,Reddit 的 API 只有在应用用户代理时才能工作。

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

1) 睡眠过程.服务器通常在响应中包含一个 Retry-after头,其中包含在重试之前应该等待的秒数。请记住,睡眠一个进程可能会导致问题,例如在任务队列中,您应该在以后的时间重试该任务,以便将工作者腾出来做其他事情。

2) 返回文章页面截断二进制指数避退算法.如果服务器没有告诉您需要等待多长时间,您可以使用中间增加的暂停来重试请求。流行的任务队列 Celery 具有这个特性 内置的

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

下面是一个 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()
if response.status_code == 429:
time.sleep(int(response.headers["Retry-After"]))

我发现了一个不错的 解决 IP 阻塞的办法当刮网站。它可以让你运行一个 Scraper 无限期从谷歌应用程序引擎和重新部署它自动当你得到一个429。

看看 这篇文章

在许多情况下,即使服务器要求你不要继续从网站上获取数据也是不道德的。但是,如果不是这样的话,您可以利用一个公共代理列表来获取具有许多不同 IP 地址的网站。