Задания

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: придумать вменяемый пример