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

Cheerio на AWS Lambda

Хотя локально мы можем легко создать проект Crawlee с помощью npx crawlee create, для запуска на AWS Lambda потребуются некоторые изменения.

Изменение кода​

При создании нового краулера необходимо передавать уникальный экземпляр Configuration. По умолчанию все краулеры Crawlee используют общее хранилище - это удобно локально, но может вызвать проблемы с состоянием Lambda-функции.

Также при создании Configuration важно указать параметр persistStorage: false. Это указывает Crawlee использовать хранилище в памяти, так как файловая система Lambda доступна только для чтения.

src/main.js
// Подробнее на https://crawlee.dev/
import { CheerioCrawler, Configuration, ProxyConfiguration } from 'crawlee';
import { router } from './routes.js';

const startUrls = ['https://crawlee.dev'];

const crawler = new CheerioCrawler({
requestHandler: router,
}, new Configuration({
persistStorage: false,
}));

await crawler.run(startUrls);

Теперь обернем всю логику в функцию handler. Это и есть Lambda-функция, которую будет выполнять AWS.

src/main.js
// Подробнее на https://crawlee.dev/
import { CheerioCrawler, Configuration } from 'crawlee';
import { router } from './routes.js';

const startUrls = ['https://crawlee.dev'];

export const handler = async (event, context) => {
const crawler = new CheerioCrawler({
requestHandler: router,
}, new Configuration({
persistStorage: false,
}));

await crawler.run(startUrls);
};
Важно

Всегда создавайте новый экземпляр краулера для каждой Lambda-функции. AWS сохраняет среду выполнения некоторое время после первого запуска Lambda (для уменьшения времени холодного старта) - поэтому последующие вызовы будут использовать уже существующий экземпляр краулера.

Коротко: Lambda-функция должна быть без состояния.

И наконец, нужно вернуть собранные данные из Lambda после завершения работы краулера.

В итоге ваш скрипт main.js должен выглядеть примерно так:

src/main.js
// Подробнее на https://crawlee.dev/
import { CheerioCrawler, Configuration } from 'crawlee';
import { router } from './routes.js';

const startUrls = ['https://crawlee.dev'];

export const handler = async (event, context) => {
const crawler = new CheerioCrawler({
requestHandler: router,
}, new Configuration({
persistStorage: false,
}));

await crawler.run(startUrls);

return {
statusCode: 200,
body: await crawler.getData(),
}
};

Развертывание проекта​

Теперь пора развернуть наш скрипт на AWS!

Создадим ZIP-архив проекта (включая папку node_modules), выполнив команду zip -r package.zip . в папке проекта.

Большая папка node_modules?

AWS имеет ограничение в 50МБ для прямой загрузки файлов. Обычно проекты Crawlee не достигают этого лимита, но с большим количеством зависимостей это возможно.

Лучший способ установки зависимостей - использование Lambda Layers. С помощью слоев можно также делиться файлами между несколькими Lambda-функциями и сохранять сам код максимально компактным.

Для создания Lambda Layer необходимо:

  • Упаковать папку node_modules в отдельный ZIP-файл (архив должен содержать одну папку с именем node_modules)
  • Создать новый Lambda Layer из этого архива. Вероятно, потребуется загрузить файл в AWS S3 и создать Layer оттуда
  • После создания просто указать использование этого слоя в Lambda-функции

Для развертывания кода загружаем архив package.zip как исходный код.

В настройках Runtime указываем handler на главную функцию краулера. Используйте слеши для описания структуры каталогов и точку для именованного экспорта. Наша функция называется handler и экспортируется из src/main.js, поэтому укажем src/main.handler.

Готово! Нажав кнопку Test, можно отправить тестовое событие в новую Lambda-функцию. Содержимое события пока не важно - при желании можно параметризовать работу краулера, анализируя объект event, который AWS передает первым аргументом в handler.

подсказка

На вкладке Configuration в панели управления AWS Lambda можно настроить объем памяти и размер временного хранилища.

Объем памяти может существенно влиять на скорость выполнения Lambda.

Подробнее о том, как производительность и стоимость масштабируются с увеличением памяти, смотрите в официальной документации.