Якщо ви хочете виконувати скрейпінг динамічних вебсайтів за допомогою 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