.. _spider_task:

=======
Задания
=======

Spider это по сути набор функций-обработчиков сетевых запросов. Каждый обработчик в свою очередь может создать новые запросы или просто сохранить куда-либо данные. Каждый запрос описывается Task-объектом. Паук добавляет каждый новый запрос в очередь и выполняет его по мере освобождения сетевых ресурсов. Каждому Task-объекту присваиваетя имя. Когда становится доступен результат сетевого запроса, то с помощью этого имени определяется имя функции-обработчика и вызывается эта функция.

Например, если мы создадим задание с именем "contact_page", то мы должны будем объявить в нашем классе паука метод c именем "task_contact_page"::

        ...
        self.add_task(Task('contact_page', url='http://domain.com/contact.html'))
        ...

    def task_contact_page(self, grab, task):
        ...

Имя функции-обработчика определяется так: берётся имя задания и добавляется префикс "task_".

Конструктор Task объекта
------------------------

Конструктор Task-объекта принимает множество аргументов. Вы должны обязательно указать имя задания и адрес документа, либо настроенный Grab-объект. Далее приведены примеры кода, который создаёт три одинаковых задания::

    # Using `url` argument
    t = Task('wikipedia', url 'http://wikipedia.org/')

    # Using Grab intance
    g = Grab()
    g.setup(url='http://wikipedia.org/')
    t = Task('wikipedia', grab=g)

    # Using configured state of Grab instance
    g = Grab()
    g.setup(url='http://wikipedia.org/')
    config = g.dump_config()
    t = Task('wikipedia', grab_config=config)

Также в конструкторе задания можно задать следующие свойства, работу которых вы сможете понять из описания других частей архитектуры Spider:

:priority: приоритет задания, целое положительное число, чем меньше число, тем выше приоритет.
:disable_cache: не использовать кэш паука для этого запроса, сетевой ответ в кэш сохранён не будет
:refresh_cache: не использовать кэш паука, в случае удачного ответа обновить запись в кэше
:valid_status: обрабатывать обычным способом указанные статусы. По умолчанию обрабатываются все статусы 2xx, а также статус 404.
:use_proxylist: использовать заданный глобально для паука список прокси. По умолчанию  опция включена.

За исключением вышеуказанных и ещё нескольих аргументов все аргументы просто сохраняются в Task-объект и доступны для дальнейшего использования. Таким образом Task-объект выступает как хранилище данных: можно запоминать данные и передавать их от запроса к запросу.

Task-объект как хранилище данных
--------------------------------

В асинхронном окружении часто бывает нужным куда-то записать информацию о запросе, а затем "вспомнить" её, когда будет готов ответ на запрос. Как было сказано выше, все неспециальные аргументы конструктора Task-объекта, просто запоминаются в объекте и доступны в дальнейшем как его атрибуты. Для удобства Task-объект имеет метод `get`, который возвращает None (или указанное вами значение), если запрошенного атрибута в Task-объекте не нашлось. Рассмотрим примеры::

    t = Task('bing', url='http://bing.com/', disable_cache=True, foo='bar')
    t.foo # == "bar"
    t.get('foo') # == "bar"
    t.get('asdf') # == None
    t.get('asdf', 'qwerty') # == "qwerty"

Клонирование Task-объекта
-------------------------

Иногда бывает удобно использовать существующий Task-объект для создания нового. Например, когда мы получили ответ на сетевой запрос и хотим сделать похожий запрос::

    # TODO: придумать вменяемый пример
