Я пытаюсь использовать 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")
python
http
mechanize
http-status-code-429
Aous1000
источник
источник
sleep
.Ответы:
Получение статуса 429 не является ошибкой , это другой сервер «любезно» просит вас прекратить рассылать спам-запросы. Очевидно, ваша скорость запросов была слишком высокой, и сервер не желает принимать это.
Вы не должны пытаться «уклоняться» от этого или даже пытаться обойти настройки безопасности сервера, пытаясь подделать ваш IP-адрес, вы должны просто уважать ответ сервера, не посылая слишком много запросов.
Если все настроено правильно, вы также получите заголовок «Retry-after» вместе с ответом 429. Этот заголовок определяет количество секунд, которое вы должны подождать, прежде чем сделать следующий звонок. Правильный способ справиться с этой «проблемой» - прочитать этот заголовок и приостановить ваш процесс на столько секунд.
Дополнительную информацию о статусе 429 можно найти здесь: http://tools.ietf.org/html/rfc6585#page-3.
источник
HTTPError as my_exception
они доступныmy_exception.headers
, по крайней мере, для urllib2.Написание этого фрагмента кода устранило мою проблему:
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
. Функция 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()
источник
Другой обходной путь - подделка вашего IP-адреса с помощью какой-либо общедоступной VPN или сети Tor. Это предполагает ограничение скорости на сервере на уровне IP.
В блоге есть краткое сообщение, демонстрирующее способ использования tor вместе с urllib2:
http://blog.flip-edesign.com/?p=119
источник
if response.status_code == 429: time.sleep(int(response.headers["Retry-After"]))
источник
Я нашел хороший способ обхода блокировки IP-адресов при парсинге сайтов. Он позволяет вам запускать Scraper на неопределенный срок, запустив его из Google App Engine и автоматически повторно развернув, когда вы получите 429.
Прочтите эту статью
источник