Браузеры в 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.
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
.
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.
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.
Значение тайм-аута зависит от времени работы краулера. Рекомендуется измерить время выполнения при локальном запуске краулера и установить тайм-аут соответственно.