.. _spider_error_handling:

================
Обработка ошибок
================

Правила обработки запросов
--------------------------

* Если запрос выполнен успешно, то вызывается метод-обработчик, связанный с заданием по его имени.
* Если запрос был нарушен из-за сетевой ошибки, то задание снова отправляется в очередь заданий.
* Если произошла непредвиденная ошибка в обработчике задания, то обработка задания прекращается немедленно. Ошибка в обработчике не фатальна: она не влияет на работу обработчиков других заданий.

Сетевые ошибки
--------------

Сетевой ошибокй считаются следующие случаи:
* произошла ошибка во время передачи данных, например, сервер отверг запрос на соеденине или оборвал связь до того, как данные были переданы или данные передавались слишком долго
* данные были переданы, но HTTP-статус ответа отличен от 2xx или 404

Cуществует ряд настроек, для задания критериев, по которым сетеовой запрос помечается как ошибочный.

Вы можете управлять таймаутами: :ref:`option_timeout` и :ref:`option_connect_timeout`. Для задания этих настроек вам нужно конструировать Task-обеъкт с помощью настроенного Grab-объекта::
    
    g = Grab(timeout=5, connect_timeout=1, url='http://example.com')
    t = Task('example', grab=g)

Вы можете указывать дополнительный список HTTP-статусов, которые будут считаться успешными::

    t = Task('example', url='http://example.com', valid_status=(500, 501, 502))


Повторно выполнение заданий
---------------------------

Завершившееся сетевой ошибкой задание повторно отправляется в очередь заданий. Количество попыток зависит от атрибута `Spider.network_try_limit` и по умолчанию равно десяти. Номер попытки хранится в атрибуте `Task.network_try_count`. Если все попытки исчерпаны, то задание больше не добавляетя в очередь. Кроме того, если в пауке определён метод `task_<имя задания>_fallback`, то он вызывается и получает в качестве единственного аргумента Task-объект, невыполненного задания.

Также бывает, что хотя HTTP-статус не содержит ошибки, но данные ответа являются неверными, например, когда отправленная форма отображается ещё раз из-за неверно заполненного поля или когда сайт показывает каптчу или сообщение о том, что ваш IP забанен. В таких случаях нужно вручную (из метода-обработчика) отправить это задание ещё раз в очередь. Дабы избежать бесконечного добавления такого задания в очередь существует ещё один счётчик: `Task.task_try_count` и соответсвующее ему ограничение в пауке `Spider.task_try_limit`. Важное замечание, в случае использования `task_try_count` вы должны самостоятельно увеличивать его значение при повторной отправке задания в очередь::

    def task_google(self, grab, task):
        if captcha_found(grab):
            yield Task('google', url=grab.config['url'], task_try_count=task.task_try_count + 1)

    def task_google_fallback(self, task):
        print 'Google is not happy with you IP address'


Статистика ошибок
-----------------

После завершения работы паука, или даже во время его работы, вы можете получить суммарную информацию о количестве сделанных запросов и количестве различных ошибок с помощью метода `Spider.render_stats`.
