Перейти к основному содержимому

Первый краулер

Сейчас мы создадим ваш первый краулер. Но прежде чем начать, давайте кратко познакомимся с основными классами Crawlee, которые будут использоваться в процессе.

Как работает Crawlee

В Crawlee доступны 3 основных класса краулеров:

О различиях между ними мы поговорим позже. Сейчас давайте рассмотрим то, что у них общего.

Основная идея работы каждого краулера заключается в том, чтобы перейти на веб-страницу, открыть её, выполнить определенные действия, сохранить результаты, перейти к следующей странице и повторять этот процесс, пока работа не будет завершена. Таким образом, краулеру всегда нужно найти ответы на два вопроса: Куда идти? и Что там делать? Настройка ответов на эти два вопроса - это единственное, что обязательно требуется. Для всего остального у краулеров есть разумные значения по умолчанию.

Куда - Request и RequestQueue

Все краулеры используют экземпляры класса Request, чтобы определить, куда им нужно перейти. Каждый запрос может содержать много информации, но как минимум он должен содержать URL - адрес веб-страницы для открытия. Но наличие только одного URL не имело бы смысла для краулинга. Иногда у вас есть готовый список URL-адресов, которые вы хотите посетить, возможно, их тысяча. В других случаях вам нужно создавать этот список динамически в процессе краулинга, добавляя все больше и больше URL-адресов по мере продвижения. Чаще всего вы будете использовать оба варианта.

Запросы хранятся в RequestQueue - динамической очереди экземпляров Request. Вы можете заполнить её начальными URL-адресами, а также добавлять новые запросы во время работы краулера. Это позволяет краулеру открывать одну страницу, извлекать интересующие URL-адреса, например, ссылки на другие страницы того же домена, добавлять их в очередь (это называется enqueuing) и повторять этот процесс для создания очереди практически неограниченного количества URL-адресов.

Что - requestHandler

В requestHandler вы указываете краулеру, что делать на каждой посещаемой странице. Вы можете использовать его для извлечения данных со страницы, их обработки, сохранения, вызова API, выполнения вычислений и так далее.

requestHandler - это определяемая пользователем функция, которая автоматически вызывается краулером для каждого Request из RequestQueue. Она всегда получает один аргумент - CrawlingContext. Его свойства меняются в зависимости от используемого класса краулера, но всегда включают свойство request, которое представляет текущий обрабатываемый URL и связанные с ним метаданные.

Создание краулера

Давайте применим теорию на практике и начнем с чего-то простого. Посетим страницу и получим её HTML-заголовок. В этом руководстве мы будем скрапить сайт Crawlee https://crawlee.dev, но тот же код будет работать для любого веб-сайта.

Конфигурация Top level await

В наших примерах мы используем функцию JavaScript под названием Top level await. Для её использования может потребоваться дополнительная настройка. А именно, требуется использование ECMAScript Modules - это означает, что вам нужно либо добавить "type": "module" в файл package.json, либо использовать расширение *.mjs для ваших файлов. Кроме того, если вы работаете в проекте TypeScript, вам нужно установить параметры компилятора module и target на ES2022 или выше.

Добавление запросов в очередь краулинга

Ранее вы узнали, что краулер использует очередь запросов как источник URL-адресов для обхода. Давайте создадим её и добавим первый запрос.

src/main.js
import { RequestQueue } from 'crawlee';

// Сначала создаем экземпляр очереди запросов
const requestQueue = await RequestQueue.open();
// Затем добавляем один или несколько запросов
await requestQueue.addRequest({ url: 'https://crawlee.dev' });

Функция requestQueue.addRequest() автоматически преобразует объект с URL-строкой в экземпляр Request. Теперь у вас есть requestQueue, которая содержит один запрос, указывающий на https://crawlee.dev.

Массовое добавление запросов

Приведенный выше код служит для иллюстрации концепции очереди запросов. Скоро вы узнаете о методе `crawler.addRequests()``, который позволяет пропустить этот код инициализации и также поддерживает добавление большого количества запросов без блокировки.

Создание CheerioCrawler

Crawlee поставляется с тремя основными классами краулеров: CheerioCrawler, PuppeteerCrawler и PlaywrightCrawler. Вы можете прочитать их краткие описания в уроке Быстрый старт.

Если у вас нет веских причин начать с другого, вам следует попробовать сначала создать CheerioCrawler. Это HTTP-краулер с поддержкой HTTP2, функциями защиты от блокировки и встроенным HTML-парсером - Cheerio. Он быстрый, простой, экономичный в работе и не требует сложных зависимостей. Единственный недостаток в том, что он не будет работать "из коробки" для веб-сайтов, требующих рендеринга JavaScript. Но возможно, вам вообще не нужен рендеринг JavaScript, так как многие современные веб-сайты используют серверный рендеринг.

Продолжим предыдущий пример с RequestQueue.

src/main.js
// Добавляем импорт CheerioCrawler
import { RequestQueue, CheerioCrawler } from 'crawlee';

const requestQueue = await RequestQueue.open();
await requestQueue.addRequest({ url: 'https://crawlee.dev' });

// Создаем краулер и добавляем очередь с нашим URL
// и обработчик запросов для обработки страницы
const crawler = new CheerioCrawler({
requestQueue,
// Аргумент `$` - это объект Cheerio,
// который содержит разобранный HTML веб-сайта
async requestHandler({ $, request }) {
// Извлекаем текст <title> с помощью Cheerio.
// См. документацию Cheerio для API
const title = $('title').text();
console.log(`Заголовок "${request.url}" : ${title}.`);
}
})

// Запускаем краулер и ждем его завершения
await crawler.run();

Когда вы запустите пример, вы увидите заголовок https://crawlee.dev, выведенный в лог. На самом деле CheerioCrawler сначала делает HTTP-запрос к https://crawlee.dev, затем разбирает полученный HTML с помощью Cheerio и делает его доступным как аргумент $ в requestHandler.

Заголовок "https://crawlee.dev" : Crawlee · The scalable web crawling, scraping and automation library for JavaScript/Node.js | Crawlee.

Добавление запросов быстрее

Ранее мы упоминали, что вы узнаете, как использовать метод crawler.addRequests() для пропуска инициализации очереди запросов. Это просто. У каждого краулера есть неявный экземпляр RequestQueue, и вы можете добавлять запросы к нему с помощью метода crawler.addRequests(). Фактически, вы можете пойти еще дальше и просто использовать первый параметр crawler.run()!

src/main.js
// Больше не нужно импортировать RequestQueue
import { CheerioCrawler } from 'crawlee';

const crawler = new CheerioCrawler({
async requestHandler({ $, request }) {
const title = $('title').text();
console.log(`Заголовок "${request.url}" : ${title}.`);
}
})

// Запускаем краулер с предоставленными URL
await crawler.run(['https://crawlee.dev']);

Когда вы запустите этот код, вы увидите точно такой же вывод, как и в предыдущем, более длинном примере. RequestQueue все еще существует, просто теперь она автоматически управляется краулером.

к сведению

Этот метод не только делает код короче, но и поможет с производительностью! Он будет ждать добавления в очередь только начальной партии из 1000 запросов, прежде чем продолжить выполнение, что означает почти мгновенное начало обработки. После этого он продолжит добавлять оставшиеся запросы в фоновом режиме (опять же, партиями по 1000 элементов, раз в секунду).

Следующие шаги

Далее вы узнаете о краулинге ссылок. Это означает поиск новых URL на страницах, которые вы обходите, и добавление их в RequestQueue для посещения краулером.