Способы создания заданий — Grab 0.6.30 documentation

### Navigation

- index
- modules |
- next |
- previous |
- Grab 0.6.30 documentation »

# Способы создания заданий

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-заданий.

## initial_urls

В атрибуте паука initial_urls Можно указать список адресов, с обработки которых паук должен начать свою работу:

    class ExampleSpider(Spider):
        initial_urls = ['http://google.com/', 'http://yahoo.com/']

Для всех адресов, перечисленных в initial_urls будет создано задание с именем ‘initial’. Это самый простой способ создания заданий, вы не можете управлять ничем кроме адресов запрашиваемых документов.

## task_generator

Более сложный способ создания начальных заданий. Метод с именем task_generator должен являться python-генератором т.е. функцией выдающей множество значений с помощью инструкции yield. Spider будет обращаться к новым задания из task_generator каждый раз, когда его очередь будет опустошаться. Это позволяет не опасаться того, что вы создадите слишком много заданий. Выглядит это так: в начале работы паук извлекает некоторое количество заданий с помощью task_generator и помещает их в очередь, далее он выполняет запросы и следит за количеством заданий в очереди. Как только их становится слишком мало, паук обращется ещё раз к task_generator и добавляет новые задания.

К примеру, вы можете открыть файл с миллионом записей и последовательно читать строки из него, создавая всё новые и новые задания:

    class ExampleSpider(Spider):
        def task_generator(self):
            for line in open('var/urls.txt'):
                yield Task('download', url=line.strip())

## add_task

Независимо от того, каким способом вы создали новое задание, в очередь заданий оно попадёт с помощью метода add_task. В случае использования intial_urls или task_generator метод add_task будет вызван неявно, но вы, конечно, можете использовать его напрямую, чтобы добавить новое задание в любом месте выполнения программы. Это можно делать даже до начала работы паука. Например:

    bot = ExampleSpider()
    bot.add_task('google', url='http://google.com')
    bot.run()

## yield

Инструкцию yield для создания заданий вы можете использовать в двух местах, во-первых, в методе task_generator, о чём уже писалось выше, во-вторых, в любой функции-обработчике результата. При вызове функции-обработчика Spider ловит все задания, которые она генерирует и складывает в очередь заданий. Создание заданий с помощью yield ничем не отличается от использования метода add_task, разве что запись получается более короткая:

    class ExampleSpider(Spider):
        initial_urls = ['http://google.com']

        def task_initial(self, grab, task):
            # Google page was fetched
            # Now let's download yahoo page
            yield Task('yahoo', url='yahoo.com')

        def task_yahoo(self, grab, task):
            pass

## Резюме

Для задания начальных заданий используйте атрибут initial_urls, если вам нужна более сложная логика создания начальных заданий, используйте метод task_generator. Для создания заданий внутри функций-обработчиков используйте инструкцию yield. Использовать метод add_task напрямую вам практически никога не понадобится.

Есть также ряд методов для типичных случаев генерации новых заданий: обработка пагинации, обработка списка ссылок. Смотрите модуль grab.spider.pattern.

### Navigation

- index
- modules |
- next |
- previous |
- Grab 0.6.30 documentation »