CoderCastrov logo
CoderCastrov
Программирование

Парсим трусики на JavaScript

Парсим трусики на JavaScript
просмотров
4 мин чтение
#Программирование

Необходимые зависимости: 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 код, без дополнительного текста