Як використовувати Selenium в NodeJS

Якщо ви хочете виконувати скрейпінг динамічних вебсайтів за допомогою Node.js та безголового браузера, інструменти, такі як Puppeteer і Selenium, є чудовими варіантами. Ми вже охопили веб-скрейпінг з Puppeteer, а сьогодні ми навчимося використовувати Selenium з Node.js для веб-скрейпінгу.

pic

Багато з вас вже можуть бути знайомі з 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().

pic

Видобуток даних за допомогою 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 на консоль.

Після виконання цього коду ви побачите такий результат.

pic

Тепер, якщо я хочу отримати заголовок і рейтинг фільмів на цій сторінці, мені потрібно використати клас By, щоб знайти певний CSS селектор.

pic

Частина рейтингу знаходиться всередині тега 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 я перебираю всі фільми і виводжу їх назви та рейтинги. Після запуску цього коду ви побачите це.

pic

Як реалізувати нескінченне прокручування

Багато інтернет-магазинів мають нескінченне прокручування, і для того щоб дістатися до самого низу, нам потрібно використовувати нескінченне прокручування для збору даних, які знаходяться внизу сторінки.

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, цикл припиняється.

pic

Як чекати елемент

Багато разів ви зіштовхнетеся з ситуацією, коли елемент може не завантажитися в певний проміжок часу.
Отже, вам потрібно почекати, поки цей елемент не завантажиться, перш ніж почати скрейпінг.

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 тут.

pic

Висновок

Підсумовуючи, Selenium у поєднанні з Node.js — це потужний дует для автоматизації веб-взаємодій і ефективного виконання завдань зі скрейпінгу. Незалежно від того, чи ви витягуєте динамічний контент, імітуєте дії користувача або прокручуєте сторінки з нескінченним прокручуванням, Selenium надає гнучкість для обробки складних сценаріїв з легкістю. Пройшовши цей посібник, ви дізналися, як налаштувати Selenium, виконати основний скрейпінг і взаємодіяти з реальними вебсайтами, включаючи введення тексту, натискання кнопок, прокручування і очікування елементів.

Тепер, якщо ви хочете уникнути роботи з безголовими браузерами, проксі-серверами і повторними спробами, рекомендується використовувати API для веб-скрейпінгу, такі як Scrapingdog.
API буде виконувати всі ці нудні завдання за вас, дозволяючи вам зосередитися лише на зборі необхідних даних.

Додаткові ресурси

Перекладено з: How to Use Selenium in NodeJS

Leave a Reply

Your email address will not be published. Required fields are marked *