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

Браузеры в AWS Lambda

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

Управление бинарными файлами браузера

К счастью, существуют NPM-пакеты, которые помогают управлять установкой бинарных файлов браузера:

  • @sparticuz/chromium - это NPM-пакет, содержащий сжатые brotli-архивом бинарные файлы chromium. При запуске в среде Lambda пакет распаковывает файлы в директорию /tmp/ и возвращает путь к исполняемому файлу.

Достаточно добавить этот пакет в зависимости проекта и заархивировать папку node_modules.

# Установка пакета
npm i -S @sparticuz/chromium

# Архивация зависимостей
zip -r dependencies.zip ./node_modules

Теперь нужно загрузить dependencies.zip как Lambda Layer в AWS. Прямая загрузка невозможна из-за ограничения в 50МБ (сжатый Chromium примерно такого же размера). Поэтому сначала загрузим архив в хранилище S3 и при создании слоя укажем ссылку на этот объект.

Модификация кода

Необходимо внести некоторые изменения в код Crawlee:

  • Во-первых, передаем новый экземпляр Configuration в Crawler. Таким образом, каждый экземпляр краулера будет иметь собственное хранилище и не будет конфликтовать с другими краулерами в среде Lambda.
src/main.js
import { Configuration, PlaywrightCrawler } from 'crawlee';
import { router } from './routes.js';

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

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

await crawler.run(startUrls);
  • Далее, нужно указать путь к Chromium из пакета @sparticuz/chromium. Поскольку в AWS Lambda отсутствует поддержка GPU-ускорения, необходимо передать параметры aws_chromium.args в параметр args.
src/main.js
import { Configuration, PlaywrightCrawler } from 'crawlee';
import { router } from './routes.js';
import aws_chromium from '@sparticuz/chromium';

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

const crawler = new PlaywrightCrawler({
requestHandler: router,
launchContext: {
launchOptions: {
executablePath: await aws_chromium.executablePath(),
args: aws_chromium.args,
headless: true
}
}
}, new Configuration({
persistStorage: false,
}));
  • И наконец, оборачиваем код в экспортируемую функцию handler - это точка входа, которую будет вызывать AWS Lambda.
src/main.js
import { Configuration, PlaywrightCrawler } from 'crawlee';
import { router } from './routes.js';
import aws_chromium from '@sparticuz/chromium';

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

export const handler = async (event, context) => {
const crawler = new PlaywrightCrawler({
requestHandler: router,
launchContext: {
launchOptions: {
executablePath: await aws_chromium.executablePath(),
args: aws_chromium.args,
headless: true
}
}
}, new Configuration({
persistStorage: false,
}));

await crawler.run(startUrls);

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

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

Теперь можно упаковать код в zip-архив (без папки node_modules, которая уже находится в Lambda Layer). Загружаем архив с кодом в AWS как тело Lambda-функции, настраиваем Lambda для использования слоя с зависимостями и тестируем созданную Lambda-функцию.

Настройки памяти

Поскольку мы используем полноценный браузер, необходимо скорректировать настройки Lambda. Важно установить объем памяти не менее 1024 МБ и настроить тайм-аут Lambda.

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