Первый краулер
Сейчас мы создадим ваш первый краулер. Но прежде чем начать, давайте кратко познакомимся с основными классами 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, но тот же код будет работать для любого веб-сайта.
В наших примерах мы используем функцию JavaScript под названием Top level await. Для её использования может потребоваться дополнительная настройка. А именно, требуется использование ECMAScript Modules - это означает, что вам нужно либо добавить "type": "module"
в файл package.json
, либо использовать расширение *.mjs
для ваших файлов. Кроме того, если вы работаете в проекте TypeScript, вам нужно установить параметры компилятора module
и target
на ES2022
или выше.
Добавление запросов в очередь краулинга
Ранее вы узнали, что краулер использует очередь запросов как источник URL-адресов для обхода. Давайте создадим её и добавим первый запрос.
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
.
// Добавляем импорт 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()
!
// Больше не нужно импортировать 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
для посещения краулером.