const puppeteer = require('puppeteer'); const url = require('url'); const fs = require('fs'); // Хранение уникальных ссылок и их метаданных let visitedUrls = new Set(); let pagesMetadata = []; // Функция для извлечения всех ссылок с текущей страницы async function getLinksFromPage(page, currentUrl) { const links = await page.$$eval('a', anchors => anchors.map(a => a.href)); const sameDomainLinks = links.filter(link => { const parsedLink = url.parse(link); return parsedLink.hostname === url.parse(currentUrl).hostname; }); return sameDomainLinks; } // Функция для извлечения метаданных (title, description, keywords) async function getMetadataFromPage(page) { const title = await page.title(); const description = await page.$eval('meta[name="description"]', el => el.content, { defaultValue: '' }).catch(() => ''); const keywords = await page.$eval('meta[name="keywords"]', el => el.content, { defaultValue: '' }).catch(() => ''); return { title, description, keywords }; } async function getLargestPictureImage(page) { // Получаем все теги <picture> и их изображения const pictures = await page.$$eval('picture', pictureTags => { return pictureTags.map(picture => { const img = picture.querySelector('img'); if (img) { return { src: img.currentSrc || img.src, width: img.naturalWidth, height: img.naturalHeight }; } return null; }).filter(img => img !== null); }); if (pictures.length === 0) { return ''; // Если нет картинок в <picture>, возвращаем пустую строку } // Сортируем изображения по площади (width * height) и выбираем самое большое const largestPicture = pictures.reduce((largest, current) => { const currentArea = current.width * current.height; const largestArea = largest.width * largest.height; return currentArea > largestArea ? current : largest; }); return largestPicture.src; // Возвращаем URL самого крупного изображения } // Функция для поиска изображения обложки async function getCoverImage(page) { // 1. Попробуем найти изображение через meta og:image const ogImage = await page.$eval('meta[property="og:image"]', el => el.content, { defaultValue: '' }).catch(() => ''); if (ogImage) { return ogImage; // Если нашли og:image, возвращаем его } return getLargestPictureImage(page); } // Основная функция рендеринга и парсинга async function renderAndParsePage(currentUrl, depth = 0, maxDepth = 3) { if (depth > maxDepth) return; const browser = await puppeteer.launch(); const page = await browser.newPage(); try { // Открываем страницу await page.goto(currentUrl, { waitUntil: 'networkidle2' }); console.log(`Рендер страницы: ${currentUrl}`); // Получаем метаданные const metadata = await getMetadataFromPage(page); // Получаем изображение обложки const coverImage = await getCoverImage(page); // Добавляем информацию о странице в массив метаданных pagesMetadata.push({ url: currentUrl, title: metadata.title, description: metadata.description, keywords: metadata.keywords, coverImage: coverImage // Добавляем обложку в метаданные }); // Находим все ссылки на текущей странице const links = await getLinksFromPage(page, currentUrl); // Обрабатываем каждую ссылку for (let link of links) { if (!visitedUrls.has(link)) { visitedUrls.add(link); console.log(`Найден путь: ${link}`); await renderAndParsePage(link, depth + 1, maxDepth); // Рекурсивно обрабатываем новые ссылки } } } catch (error) { console.error(`Ошибка при рендере страницы: ${currentUrl}`, error); } finally { await browser.close(); } } // Запуск скрипта с главной страницы const urls = [ 'https://neiromidin.lbp.open.olainfarm.kz', 'https://neiromidin.stroke.open.olainfarm.kz', ]; // Запуск скрипта (async () => { for(let url of urls) { await renderAndParsePage(url); } // Записываем метаданные в файл fs.writeFileSync('pages_metadata.json', JSON.stringify(pagesMetadata, null, 2), 'utf-8'); console.log('Метаданные страниц успешно сохранены в pages_metadata.json'); })();