Что такое Apify и его основные возможности
Apify представляет собой облачную платформу для веб-скрапинга и автоматизации задач в интернете. Она предоставляет разработчикам инструменты и инфраструктуру для создания, запуска и управления веб-краулерами (Actors). Ключевые возможности включают:
- Apify Actors: Переиспользуемые серверные облачные программы для выполнения задач скрапинга или автоматизации.
- Apify SDK: Библиотека для Node.js, упрощающая разработку Actors.
- Apify Store: Маркетплейс готовых Actors для различных задач.
- Прокси-серверы: Встроенные решения для обхода блокировок (датацентровые, резидентные, мобильные).
- Управление данными: Хранение и экспорт собранных данных в различных форматах (JSON, CSV, Excel).
- Планировщик: Автоматический запуск Actors по расписанию.
Преимущества использования Node.js для веб-скрапинга
Node.js, благодаря своей асинхронной природе и событийно-ориентированной архитектуре, идеально подходит для задач веб-скрапинга, требующих обработки множества I/O операций.
- Производительность: Асинхронность позволяет эффективно обрабатывать множество одновременных HTTP-запросов.
- Экосистема: Огромное количество библиотек (npm) для работы с HTTP, парсинга HTML (Cheerio), управления браузерами (Puppeteer, Playwright).
- JavaScript: Единый язык для фронтенда и бэкенда, включая скрипты автоматизации браузера.
- Apify SDK: Нативная интеграция с платформой Apify через официальный SDK.
Сравнение Apify с другими инструментами веб-скрапинга
По сравнению с библиотеками типа Requests + BeautifulSoup (Python) или Scrapy (Python), Apify предлагает комплексное платформенное решение.
- Инфраструктура: Apify берет на себя управление прокси, масштабирование, хранение данных и мониторинг, что отсутствует в отдельных библиотеках.
- Управление браузером: Легкая интеграция с Puppeteer/Playwright для скрапинга динамических сайтов, что сложнее настроить с нуля.
- Облако vs. Локально: Apify ориентирован на облачное выполнение, тогда как Scrapy или связка Requests/BeautifulSoup чаще используются для локальной разработки и запуска (хотя их можно развернуть в облаке).
- Модель Actors: Позволяет легко переиспользовать и делиться кодом, в отличие от более монолитных проектов на Scrapy.
Настройка Apify SDK в Node.js
Установка Apify CLI и Node.js
Предполагается, что Node.js (версия 16 или выше) и npm уже установлены. Установка Apify CLI выполняется глобально через npm:
npm install -g apify-cli
После установки проверьте доступность команды:
apify --version
Инициализация нового проекта Apify
Для создания структуры проекта Actor используется команда apify create:
apify create my-scraper
CLI предложит выбрать шаблон. Для Node.js проектов обычно выбирают Getting started with Actor source code in Node.js. Это создаст базовую структуру проекта.
Для входа в аккаунт Apify (необходимо для развертывания в облаке) используется команда:
apify login
Обзор структуры проекта Apify
Стандартная структура проекта Apify Actor на Node.js включает:
.actor/: Папка с конфигурацией Actor (actor.json).storage/: Локальное хранилище данных (эмулирует Apify Cloud Storage).src/: Исходный код Actor (основной файл —main.js).package.json: Зависимости Node.js проекта.Dockerfile: (Опционально) для кастомных сборок.README.md: Описание Actor.
Файл main.js является точкой входа. .actor/actor.json определяет метаданные Actor, включая входную схему (inputSchema).
Автоматизация веб-скрапинга с помощью Apify и Node.js
Использование Apify Actors для извлечения данных
Основной инструмент — Apify SDK. Он предоставляет классы для управления процессом скрапинга:
Apify.Actor.main(): Основная функция для запуска логики Actor.RequestQueue: Управление очередью URL для обхода.BasicCrawler,CheerioCrawler,PuppeteerCrawler,PlaywrightCrawler: Классы для реализации логики обхода и парсинга.Dataset: Хранение извлеченных данных.
Обход блокировок и ограничений веб-сайтов
Apify предоставляет встроенные механизмы:
- Apify Proxy: Автоматическая ротация IP-адресов. Настраивается при запуске Crawler или глобально.
- User Agents: Использование реалистичных User-Agent строк.
- Задержки и параллелизм: Настройка задержек между запросами (
maxRequestRetries,maxRequestsPerMinute) для имитации человеческого поведения. - Браузерные отпечатки: При использовании
PuppeteerCrawlerилиPlaywrightCrawler, можно применять техники маскировки отпечатков (fingerprinting).
Примеры кода для скрапинга данных с популярных веб-сайтов
Пример: Скрапинг заголовков новостей с помощью CheerioCrawler
// src/main.js
import { Actor } from 'apify';
import { CheerioCrawler, log } from '@crawlee/cheerio';
/**
* @typedef {object} Input
* @property {string} startUrl - The starting URL, e.g., a news site.
*/
/**
* Main Actor function
*/
Actor.main(async () => {
const input = await Actor.getInput();
// Type assertion for input
const { startUrl } = /** @type {Input} */ (input);
if (!startUrl) {
log.error('Missing startUrl in input.');
await Actor.fail();
return;
}
const requestQueue = await Actor.openRequestQueue();
await requestQueue.addRequest({ url: startUrl });
log.info('Starting crawler...');
const crawler = new CheerioCrawler({
requestQueue,
maxRequestsPerCrawl: 100, // Limit crawl depth
/**
* Handles each page request.
* @param {import('@crawlee/cheerio').CheerioCrawlingContext} context
*/
async requestHandler({ request, $, log }) {
log.info(`Processing ${request.url}...`);
// Example: Extract news headlines (selector depends on the target site)
const titles = [];
$('h2 a').each((index, element) => {
const title = $(element).text().trim();
if (title) {
titles.push(title);
}
});
// Save results to dataset
await Actor.pushData({
url: request.url,
extractedTitles: titles,
});
},
/**
* Handles failed requests.
* @param {import('@crawlee/core').FailedRequestContext} context
*/
failedRequestHandler({ request, log }) {
log.error(`Request ${request.url} failed too many times.`);
},
});
await crawler.run();
log.info('Crawler finished.');
});
Управление браузером с помощью Apify и Puppeteer/Playwright
Интеграция Puppeteer или Playwright в Apify Actors
Apify SDK (через @crawlee/puppeteer или @crawlee/playwright) предоставляет классы PuppeteerCrawler и PlaywrightCrawler, которые абстрагируют управление браузером.
// Пример использования PlaywrightCrawler
import { Actor } from 'apify';
import { PlaywrightCrawler, log } from '@crawlee/playwright';
Actor.main(async () => {
// ... (input handling, requestQueue setup) ...
const crawler = new PlaywrightCrawler({
requestQueue,
launchContext: {
// Use Apify Proxy Configuration for browser requests
proxyConfiguration: await Actor.createProxyConfiguration(),
// Options for Playwright launch
launchOptions: {
headless: true, // Run in headless mode
},
},
maxRequestsPerCrawl: 50,
/**
* Handles page navigation and interaction.
* @param {import('@crawlee/playwright').PlaywrightCrawlingContext} context
*/
async requestHandler({ page, request, log }) {
log.info(`Navigated to ${request.url}`);
const title = await page.title();
log.info(`Page title: ${title}`);
// Further interactions or data extraction...
await Actor.pushData({ url: request.url, title });
},
// ... (failedRequestHandler etc.)
});
await crawler.run();
});
Автоматизация действий пользователя на веб-страницах (клики, заполнение форм)
Используя page объект из PuppeteerCrawler или PlaywrightCrawler, можно эмулировать действия пользователя.
// Внутри requestHandler
/**
* @param {import('@crawlee/playwright').PlaywrightCrawlingContext} context
*/
async requestHandler({ page, request, log }) {
log.info(`Processing form on ${request.url}`);
// Example: Fill and submit a login form
await page.waitForSelector('#username');
await page.type('#username', 'your_username');
await page.waitForSelector('#password');
await page.type('#password', 'your_password');
await page.waitForSelector('button[type="submit"]');
// Use Promise.all for concurrent navigation wait and click
await Promise.all([
page.waitForNavigation(), // Wait for navigation triggered by click
page.click('button[type="submit"]'),
]);
log.info('Form submitted successfully.');
// Extract data after login or action
const dashboardData = await page.locator('.dashboard-metric').textContent();
await Actor.pushData({ url: request.loadedUrl, data: dashboardData });
}
Скрапинг динамически генерируемого контента
Браузерные Crawler (PuppeteerCrawler, PlaywrightCrawler) идеально подходят для сайтов, активно использующих JavaScript для рендеринга контента (SPA — Single Page Applications).
Ключевые моменты:
- Ожидание элементов: Использование
page.waitForSelector(),page.waitForFunction(),page.waitForResponse()для ожидания появления нужных данных или завершения AJAX-запросов. - Выполнение JS:
page.evaluate()для выполнения произвольного JavaScript в контексте страницы и извлечения данных, недоступных через DOM селекторы. - Перехват запросов:
page.route()для модификации или анализа сетевых запросов, например, для извлечения данных из API-вызовов, инициированных страницей.
Продвинутые техники и советы по работе с Apify и Node.js
Параллелизация скрапинга для повышения производительности
Apify SDK автоматически управляет параллелизмом через настройки Crawler:
maxConcurrency: Максимальное количество одновременно обрабатываемых страниц/запросов.maxRequestsPerMinute: Ограничение скорости для избежания блокировок.
Подбор оптимальных значений зависит от целевого сайта и ограничений инфраструктуры Apify (или локальной машины).
Обработка ошибок и повторные попытки
Crawler автоматически обрабатывает сетевые ошибки и ошибки HTTP (статусы 5xx) с помощью повторных попыток (maxRequestRetries). Логику обработки специфичных ошибок (например, страница бана) следует реализовывать в failedRequestHandler или внутри requestHandler с использованием блоков try...catch.
Можно использовать request.pushErrorMessage() для сохранения информации об ошибках.
Использование Apify Cloud для масштабирования и мониторинга
- Развертывание:
apify pushзагружает код Actor в Apify Cloud. - Масштабирование: Запуск Actor в облаке позволяет использовать инфраструктуру Apify (прокси, вычислительные ресурсы) для обработки больших объемов данных.
- Мониторинг: Веб-интерфейс Apify предоставляет логи, статистику выполнения, просмотр хранилища данных (Dataset, KeyValueStore, RequestQueue).
- Веб-хуки и API: Интеграция с другими системами через API Apify или веб-хуки по завершении выполнения Actor.
Интеграция с другими сервисами и базами данных
Собранные данные (Dataset) можно экспортировать вручную или автоматически через API/веб-хуки.
- API Apify: Использовать клиент Apify (
apify-clientв Node.js) для программного доступа к данным. - Веб-хуки: Настроить веб-хук, который будет отправлять уведомление (например, с ID датасета) на ваш сервер по завершении Actor. Ваш сервер затем может скачать данные и импортировать их в БД (PostgreSQL, MongoDB и т.д.) или отправить в другие сервисы (Google Sheets, BI-системы).
- Прямая запись: В коде Actor можно использовать соответствующие Node.js библиотеки для прямой записи в базу данных, но это требует осторожного управления соединениями и обработкой ошибок, особенно при параллельном выполнении.