Краулер Puppeteer
В этом примере показано, как использовать PuppeteerCrawler
вместе с
RequestQueue
для рекурсивного сканирования сайта Hacker News с помощью безголового Chrome и Puppeteer.
Краулер начинает с одного URL-адреса, находит ссылки на следующие страницы, добавляет их в очередь и продолжает работу, пока не закончатся нужные ссылки. Результаты
сохраняются в датасет по умолчанию. При локальной конфигурации результаты сохраняются в виде JSON-файлов в директории ./storage/datasets/default
подсказка
Чтобы запустить этот пример на платформе Apify, выберите образ apify/actor-node-puppeteer-chrome
для вашего Dockerfile.
Run on
import { PuppeteerCrawler } from 'crawlee';
// Создаем экземпляр класса PuppeteerCrawler - краулера,
// который автоматически загружает URL в безголовом Chrome / Puppeteer.
const crawler = new PuppeteerCrawler({
// Здесь вы можете установить опции, которые передаются функции launchPuppeteer().
launchContext: {
launchOptions: {
headless: true,
// Другие опции Puppeteer
},
},
// Останавливаем краулинг после нескольких страниц
maxRequestsPerCrawl: 50,
// Эта функция будет вызываться для каждого URL для краулинга.
// Здесь вы можете написать скрипты Puppeteer, с которыми вы знакомы,
// за исключением того, что браузеры и страницы автоматически управляются Crawlee.
// Функция принимает один параметр, который является объектом с следующими полями:
// - request: экземпляр класса Request с информацией, такой как URL и HTTP-метод
// - page: объект Page Puppeteer (см. https://pptr.dev/#show=api-class-page)
async requestHandler({ pushData, request, page, enqueueLinks, log }) {
log.info(`Processing ${request.url}...`);
// Функция, которая будет вычислена в контексте браузерного контекста Puppeteer.
const data = await page.$$eval('.athing', ($posts) => {
const scrapedData: { title: string; rank: string; href: string }[] = [];
// Мы получаем заголовок, ранг и URL каждого поста на Hacker News.
$posts.forEach(($post) => {
scrapedData.push({
title: $post.querySelector('.title a').innerText,
rank: $post.querySelector('.rank').innerText,
href: $post.querySelector('.title a').href,
});
});
return scrapedData;
});
// Сохраняем результаты в датасет по умолчанию.
await pushData(data);
// Находим ссылку на следующую страницу и добавляем ее в очередь, если она существует.
const infos = await enqueueLinks({
selector: '.morelink',
});
if (infos.processedRequests.length === 0) log.info(`${request.url} is the last page!`);
},
// Эта функция вызывается, если обработка страницы завершилась неудачно более maxRequestRetries+1 раз.
failedRequestHandler({ request, log }) {
log.error(`Запрос ${request.url} не выполнен слишком много раз.`);
},
});
await crawler.addRequests(['https://news.ycombinator.com/']);
// Запускаем краулер и ждем, пока он закончит работу.
await crawler.run();
console.log('Краулер закончил работу.');