Якщо ви хочете виконувати скрейпінг динамічних вебсайтів за допомогою Node.js та безголового браузера, інструменти, такі як Puppeteer і Selenium, є чудовими варіантами. Ми вже охопили веб-скрейпінг з Puppeteer, а сьогодні ми навчимося використовувати Selenium з Node.js для веб-скрейпінгу.
Багато з вас вже можуть бути знайомі з Selenium, якщо ви використовували його для веб-скрейпінгу з Python. В цій статті ми розглянемо, як використовувати Selenium з Node.js для веб-скрейпінгу з нуля. Ми охопимо такі теми, як скрейпінг вебсайту, очікування завантаження конкретних елементів і багато іншого.
Налаштування Selenium в Node.js
Перед тим як почати використовувати Selenium для веб-скрейпінгу, потрібно переконатися, що ваше середовище готове. Дотримуйтесь цих кроків для встановлення і налаштування Selenium з Node.js.
Встановлення Node.js
Сподіваюся, що ви вже встановили Node.js на вашому комп'ютері. Якщо ні, ви можете завантажити його тут. Перевірте встановлення за допомогою цієї команди.
node -v
Створення нового проекту Node.js
Створіть папку з будь-якою назвою. Ми зберігатимемо всі наші .js файли в цій папці.
mkdir selenium-nodejs-demo
cd selenium-nodejs-demo
Потім ініціалізуйте файл package.json.
npm init -y
Встановлення необхідних пакетів
Щоб взаємодіяти з браузером, нам потрібно встановити пакет selenium-webdriver.
npm install selenium-webdriver
Тепер, якщо ви збираєтесь використовувати браузер Google Chrome, вам також потрібно встановити chromedriver.
npm install chromedriver
Ми завершили частину встановлення. Тепер давайте перевіримо нашу налаштування.
Як запустити Selenium з Node.js
const { Builder } = require('selenium-webdriver');
async function testSetup() {
let driver = await new Builder().forBrowser('chrome').build();
await driver.get('https://www.scrapingdog.com/');
console.log('Браузер успішно запущено!');
await driver.quit();
}
testSetup();
Спочатку ми імпортуємо клас Builder з бібліотеки Selenium WebDriver для створення нового екземпляра WebDriver для автоматизації браузера. Потім створюємо новий екземпляр WebDriver для автоматизації Google Chrome. Екземпляр браузера запускається за допомогою методу build(). На наступному кроці драйвер переходить на сайт www.scrapingdog.com.
Після запуску браузера виводиться повідомлення для підтвердження. Потім ми закриваємо драйвер за допомогою методу .quit().
Видобуток даних за допомогою Selenium та Node.js
Візьмемо цю сторінку IMDB як приклад URL для цієї частини.
const { Builder } = require('selenium-webdriver');
async function testSetup() {
let driver = await new Builder().forBrowser('chrome').build();
await driver.get('https://www.imdb.com/chart/moviemeter/');
let html = await driver.getPageSource();
console.log(html);
await driver.quit();
}
testSetup();
Використовуючи функцію .getPageSource(), ми видобуваємо сирий HTML цільового вебсайту.
Тоді, перед тим як закрити браузер, ми виводимо сирий HTML на консоль.
Після виконання цього коду ви побачите такий результат.
Тепер, якщо я хочу отримати заголовок і рейтинг фільмів на цій сторінці, мені потрібно використати клас By, щоб знайти певний CSS селектор.
Частина рейтингу знаходиться всередині тега span з CSS селектором .ipc-rating-star — imdb span:nth-child(2)
Давайте витягнемо ці дані за допомогою By.
const { Builder, By } = require('selenium-webdriver');
async function testSetup() {
let driver = await new Builder().forBrowser('chrome').build();
await driver.get('https://www.imdb.com/chart/moviemeter/');
await driver.sleep(5000);
let movies = await driver.findElements(By.css('.ipc-title--title a'));
let ratings = await driver.findElements(By.css('.ipc-rating-star--imdb span:nth-child(2)'));
console.log(`Знайдено ${movies.length} фільмів і ${ratings.length} рейтингів.`);
for (let i = 0; i < movies.length; i++) {
let title = await movies[i].getText();
let rating = ratings[i] ? await ratings[i].getText() : 'N/A';
console.log(`${title} - ${rating}`);
}
} catch (err) {
console.error('Сталася помилка:', err);
} finally {
await driver.quit();
}
}
testSetup();
У наведеному коді я використовую .findElements(), щоб знайти ці CSS селектори в DOM.
Далі за допомогою циклу for я перебираю всі фільми і виводжу їх назви та рейтинги. Після запуску цього коду ви побачите це.
Як реалізувати нескінченне прокручування
Багато інтернет-магазинів мають нескінченне прокручування, і для того щоб дістатися до самого низу, нам потрібно використовувати нескінченне прокручування для збору даних, які знаходяться внизу сторінки.
const { Builder } = require('selenium-webdriver');
async function infiniteScrollExample() {
let driver = await new Builder().forBrowser('chrome').build();
try {
// Перехід на цільовий сайт
await driver.get('https://www.imdb.com/chart/top/'); // Замість цього використовуйте ваш URL
console.log('Сторінка завантажена.');
let lastHeight = 0;
while (true) {
// Прокручування до кінця сторінки
await driver.executeScript('window.scrollTo(0, document.body.scrollHeight);');
console.log('Прокручено донизу.');
// Зачекайте 3 секунди для завантаження контенту
await driver.sleep(3000);
// Отримуємо поточну висоту сторінки
const currentHeight = await driver.executeScript('return document.body.scrollHeight;');
// Вихід з циклу, якщо новий контент не завантажується
if (currentHeight === lastHeight) {
console.log('Немає більше контенту для завантаження. Виходимо з нескінченного прокручування.');
break;
}
// Оновлюємо lastHeight для наступної ітерації
lastHeight = currentHeight;
}
} catch (error) {
console.error('Сталася помилка:', error);
} finally {
// Закриваємо драйвер
await driver.quit();
}
}
infiniteScrollExample();
У наведеному коді є цикл while, який продовжується, поки висота сторінки більше не змінюється після прокручування, що вказує на те, що більше контенту не завантажується.
Коли currentHeight стає рівним lastHeight, цикл припиняється.
Як чекати елемент
Багато разів ви зіштовхнетеся з ситуацією, коли елемент може не завантажитися в певний проміжок часу.
Отже, вам потрібно почекати, поки цей елемент не завантажиться, перш ніж почати скрейпінг.
const { Builder, By, until } = require('selenium-webdriver');
async function waitForSearchBar() {
let driver = await new Builder().forBrowser('chrome').build();
await driver.get('https://www.imdb.com/chart/top/');
let searchBar = await driver.wait(
until.elementLocated(By.css('.ipc-title__text')),
5000 // Чекаємо до 5 секунд
);
await driver.quit();
}
waitForSearchBar();
Тут ми чекаємо 5 секунд на вибраний елемент. Ви можете звернутися до офіційної документації Selenium тут, щоб дізнатися більше про метод wait.
Як вводити текст і натискати кнопку
Іноді вам потрібно буде зібрати контент, який з’являється після введення тексту або натискання кнопки. Наприклад, давайте здійснимо пошук на Google. Спочатку ми введемо запит у поле введення Google. Потім виконаємо пошук, натискаючи кнопку пошуку.
const { Builder, By } = require('selenium-webdriver');
async function typeInFieldExample() {
let driver = await new Builder().forBrowser('chrome').build();
try {
// Перехід на сайт з полем введення
await driver.get('https://www.google.com');
// Знайти поле введення для пошуку і ввести запит
let searchBox = await driver.findElement(By.name('q'));
await searchBox.sendKeys('Scrapingdog');
await driver.sleep(3000);
console.log('Текст успішно введено!');
} catch (error) {
console.error('Сталася помилка:', error);
} finally {
await driver.quit();
}
}
typeInFieldExample();
Використовуючи локатори, такі як By.id, By.className, By.css або By.xpath, ми знаходимо елемент. Потім за допомогою методу .sendKeys() ми вводимо Scrapingdog у поле введення на Google. Тепер давайте натиснемо кнопку Enter для пошуку.
const { Builder, By } = require('selenium-webdriver');
async function typeInFieldExample() {
let driver = await new Builder().forBrowser('chrome').build();
try {
// Перехід на сайт з полем введення
await driver.get('https://www.google.com');
// Знайти поле введення для пошуку і ввести запит
let searchBox = await driver.findElement(By.name('q')); // 'q' — атрибут name поля пошуку Google
await searchBox.sendKeys('Scrapingdog');
await driver.sleep(3000);
let searchButton = await driver.findElement(By.name('btnK'));
await searchButton.click(); // Натискаємо кнопку
await driver.sleep(3000);
console.log('Текст успішно введено!');
} catch (error) {
console.error('Сталася помилка:', error);
} finally {
await driver.quit();
}
}
typeInFieldExample();
Після запуску цього коду ви побачите, як браузер переходить на google.com, вводить запит для пошуку і натискає кнопку Enter самостійно. Дізнайтеся більше про sendKeys тут.
Висновок
Підсумовуючи, Selenium у поєднанні з Node.js — це потужний дует для автоматизації веб-взаємодій і ефективного виконання завдань зі скрейпінгу. Незалежно від того, чи ви витягуєте динамічний контент, імітуєте дії користувача або прокручуєте сторінки з нескінченним прокручуванням, Selenium надає гнучкість для обробки складних сценаріїв з легкістю. Пройшовши цей посібник, ви дізналися, як налаштувати Selenium, виконати основний скрейпінг і взаємодіяти з реальними вебсайтами, включаючи введення тексту, натискання кнопок, прокручування і очікування елементів.
Тепер, якщо ви хочете уникнути роботи з безголовими браузерами, проксі-серверами і повторними спробами, рекомендується використовувати API для веб-скрейпінгу, такі як Scrapingdog.
API буде виконувати всі ці нудні завдання за вас, дозволяючи вам зосередитися лише на зборі необхідних даних.
Додаткові ресурси
- Веб-скрейпінг з Node.js
- Веб-скрейпінг з Selenium і Python
- Як знайти елемент за допомогою Xpath в Selenium
Перекладено з: How to Use Selenium in NodeJS