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