Парсим трусики на JavaScript
Table Of Content
Необходимые зависимости: node.js; модули для node.js — puppeteer.js, fs(file-system). Качестве сайта для примера буду использовать https://www.calvinklein.ru/
const puppeteer = require('puppeteer');
const fs = require('fs');
let photos = Array();
Создаем переменную puppeteer для дальнейшего использования и подключаем модуль puppeteer, аналогичные действия с file-stystem
const puppeteer = require('puppeteer');
const fs = require('fs');
Создаем массив для ссылок от изображений чтобы в дальнейшем скачать через fs в нашу папку
let photos = Array();
Часть #1
Дальше создаем конструктор async для асинхронности кода, чтобы было все по феншую и пишем дефолтные настройки для Chromium. P.S Chromium это один из безголовых браузеров, с его помощью можно управлять браузером через код, в данном туториале с помощью модуля puppeteer.js
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1920, height: 3080 });
await page.goto('[https://www.calvinklein.ru/%D0%B6%D0%B5%D0%BD%D1%81%D0%BA%D0%B8%D0%B5-%D1%82%D1%80%D1%83%D1%81%D0%B8%D0%BA%D0%B8-%D0%BC%D1%83%D0%BB%D1%8C%D1%82%D0%B8%D0%BF%D0%B0%D0%BA%D0%B5%D1%82#:_0000D3445ESRU'](https://www.calvinklein.ru/%D0%B6%D0%B5%D0%BD%D1%81%D0%BA%D0%B8%D0%B5-%D1%82%D1%80%D1%83%D1%81%D0%B8%D0%BA%D0%B8-%D0%BC%D1%83%D0%BB%D1%8C%D1%82%D0%B8%D0%BF%D0%B0%D0%BA%D0%B5%D1%82#:_0000D3445ESRU'));
})();
Создаем константу browser и далее запускаем наш безголовый браузер
const browser = await puppeteer.launch();
Создаем константу page и открываем новую страницу в браузере, теперь константа page это наш главный помощник, он ссылается на данную страницу и именно через него мы будем передавать методы для манипулирования страницей
const page = await browser.newPage();
Через метод setViemport в параметрах указываю ширину и высоту страницы, я выставляю 1920x1080 дефолтный монитор по нынешним меркам
await page.setViewport({ width: 1920, height: 1080 });
Вбиваем в адресную строку текущей страницы ссылку сайта куда хотим перейти, это можно осуществить с помощью метода goto(); в качестве параметра принимает строку
await page.goto('[https://www.calvinklein.ru/%D0%B6%D0%B5%D0%BD%D1%81%D0%BA%D0%B8%D0%B5-%D1%82%D1%80%D1%83%D1%81%D0%B8%D0%BA%D0%B8-%D0%BC%D1%83%D0%BB%D1%8C%D1%82%D0%B8%D0%BF%D0%B0%D0%BA%D0%B5%D1%82#:_0000D3445ESRU'](https://www.calvinklein.ru/%D0%B6%D0%B5%D0%BD%D1%81%D0%BA%D0%B8%D0%B5-%D1%82%D1%80%D1%83%D1%81%D0%B8%D0%BA%D0%B8-%D0%BC%D1%83%D0%BB%D1%8C%D1%82%D0%B8%D0%BF%D0%B0%D0%BA%D0%B5%D1%82#:_0000D3445ESRU'));
Часть #2
Юзаем метод evaluate(); что это за метод? Этот метод пробираеться в DOM дерево и манипулирует с элементами, в этом методе console.log(); не будет выводиться в нашем терминале т.к это Страница браузера
await page.on('console', function (msg) {});
await page.evaluate(async () => {
await Promise((resolve, reject) => { });
});
С помощью метода параметра ‘console’ в методе on(); мы можем перехватить все логи из консоли на страницу браузер и записать их куда угодно, записывать мы будем чуть позже
await page.on('console', function (_msg_) {});
В методе evaluate(); мы будем использовать метод setInterval(); поэтому на нужен метод Promise(); т.к все манипуляции мы проводим в конструкторе async
await page.evaluate(async () => {
await Promise((resolve, reject) => { });
});
Часть #3
И так страница динамически подгружает итемы с изображениями трусиков, логика следующая мы скролим страницу по 100 пикселей вниз до тех пор, пока не прогрузятся все итемы. После того, как страница доскролена, мы перебираем все итемы и забираем ссылку на изображение наших заветных трусиков. Затем пушим ссылки в наш массив ‘photos’.
await page.on('console', function (msg) {
if (msg.text()[0] === 'h') photos.push(msg.text());
});
await page.evaluate(async () => {
await Promise((resolve, reject) => {
let lastScroll = 0;
const interval = setInterval(() => {
window.scrollBy(0, 100);
const scrollTop = document.documentElement.scrollTop;
if (scrollTop === lastScroll) {
var childPi = document.querySelectorAll('#productListContainer > .product');
childPi.forEach(function (el, i) {
let childFind = el.querySelector('.setCatalogImg');
let str = childFind.getAttribute('data-primaryimagesrc');
console.log('[http://'](http://') + str.slice(2, -1) + '$');
});
clearInterval(interval);
resolve();
} else {
lastScroll = scrollTop;
}
}, 100);
});
});
Часть #4
Перебираем наш массив с ссылками, переходим по ссылке, скачиваем изображения с помощью параметра await viewSource.buffer() в методе writeFile() модуля fs, после скачивания сохраняем в нашу папку, путь к папке передается первым параметром метода writeFile(). После скачивания всех фотографий закрываем браузер методом close().
for (let i = 0; i < photos.length; i++) {
var viewSource = await page.goto(photos[i]);
fs.writeFile('img/anu_' + i + '.jpg', await viewSource.buffer(), function (err) {
if (err) {
return console.log(err);
}
console.log("Файл сохранен!");
});
}
browser.close();
Итоговый код:
const puppeteer = require('puppeteer');
const fs = require('fs');
var photos = Array();(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1920, height: 3080 });
await page.goto('[https://www.calvinklein.ru/%D0%B6%D0%B5%D0%BD%D1%81%D0%BA%D0%B8%D0%B5-%D1%82%D1%80%D1%83%D1%81%D0%B8%D0%BA%D0%B8-%D0%BC%D1%83%D0%BB%D1%8C%D1%82%D0%B8%D0%BF%D0%B0%D0%BA%D0%B5%D1%82#:_0000D3445ESRU'](https://www.calvinklein.ru/%D0%B6%D0%B5%D0%BD%D1%81%D0%BA%D0%B8%D0%B5-%D1%82%D1%80%D1%83%D1%81%D0%B8%D0%BA%D0%B8-%D0%BC%D1%83%D0%BB%D1%8C%D1%82%D0%B8%D0%BF%D0%B0%D0%BA%D0%B5%D1%82#:_0000D3445ESRU'));await page.on('console', function (msg) {
if (msg.text()[0] === 'h') photos.push(msg.text());
});await page.evaluate(async () => {
await Promise((resolve, reject) => {
let lastScroll = 0;
const interval = setInterval(() => {
window.scrollBy(0, 100);
const scrollTop = document.documentElement.scrollTop;
if (scrollTop === lastScroll) {
var childPi = document.querySelectorAll('#productListContainer > .product');
childPi.forEach(function (el, i) {
let childFind = el.querySelector('.setCatalogImg');
let str = childFind.getAttribute('data-primaryimagesrc');
console.log('[http://'](http://') + str.slice(2, -1) + '$');
});
clearInterval(interval);
resolve();
} else {
lastScroll = scrollTop;
}
}, 100);
});
});for (let i = 0; i < photos.length; i++) {
var viewSource = await page.goto(photos[i]);
fs.writeFile('img/anu_' + i + '.jpg', await viewSource.buffer(), function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
}
browser.close();
})();
Результат:
Переведи введенный markdown код с английского на русский. Сохрани оригинальную разметку markdown и изображения на своих местах. Вместо слов scraping/scraper/scrapping используй parsing/parser/parse. Возвращай только markdown код, без дополнительного текста