Веб-скрейпинг автозаполнения YouTube с помощью Nodejs


Что будет соскоблено

📌Примечание: На данный момент у нас нет API, поддерживающего извлечение данных автозаполнения.

Эта запись в блоге предназначена для того, чтобы показать вам, как вы можете сделать это самостоятельно, пока мы работаем над выпуском соответствующего API. Мы сообщим вам об этом в нашем Twitter, как только этот API будет выпущен.

Полный код

Если вам не нужны объяснения, посмотрите пример полного кода в онлайн IDE

const puppeteer = require("puppeteer-extra");
const StealthPlugin = require("puppeteer-extra-plugin-stealth");

puppeteer.use(StealthPlugin());

const queries = ["javascript", "node", "web scraping"];
const URL = "https://www.youtube.com";

async function getYoutubeAutocomplete() {
  const browser = await puppeteer.launch({
    headless: false,
    args: ["--no-sandbox", "--disable-setuid-sandbox"],
  });

  const page = await browser.newPage();

  await page.setDefaultNavigationTimeout(60000);
  await page.goto(URL);
  await page.waitForSelector("#contents");

  const autocompleteResults = [];
  for (query of queries) {
    await page.click("#search-input");
    await page.keyboard.type(query);
    await page.waitForTimeout(5000);
    const results = {
      query,
      autocompleteResults: await page.evaluate(() => {
        return Array.from(document.querySelectorAll(".sbdd_a li"))
          .map((el) => el.querySelector(".sbqs_c")?.textContent.trim())
          .filter((el) => el);
      }),
    };
    autocompleteResults.push(results);
    await page.click("#search-clear-button");
    await page.waitForTimeout(2000);
  }

  await browser.close();

  return autocompleteResults;
}

getYoutubeAutocomplete().then(console.log);
Вход в полноэкранный режим Выход из полноэкранного режима

Подготовка

Сначала нам нужно создать проект Node.js* и добавить пакеты npm puppeteer, puppeteer-extra и puppeteer-extra-plugin-stealth для управления Chromium (или Chrome, или Firefox, но сейчас мы работаем только с Chromium, который используется по умолчанию) через протокол DevTools в безголовом или неголовом режиме.

Для этого в директории с нашим проектом откройте командную строку и введите npm init -y, а затем npm i puppeteer puppeteer-extra puppeteer-extra-plugin-stealth.

*Если у вас не установлен Node.js, вы можете загрузить его с сайта nodejs.org и следовать документации по установке.

📌Примечание: также вы можете использовать puppeteer без каких-либо расширений, но я настоятельно рекомендую использовать его с puppeteer-extra с puppeteer-extra-plugin-stealth для предотвращения обнаружения веб-сайтом того, что вы используете безголовый Chromium или что вы используете веб-драйвер. Вы можете проверить это на сайте тестов безголового Chrome. На скриншоте ниже показана разница.

Процесс

Расширение SelectorGadget Chrome использовалось для захвата селекторов CSS при нажатии на нужный элемент в браузере. Если у вас возникли трудности с пониманием этого, у нас есть специальная статья в блоге SerpApi, посвященная веб-скрапингу с CSS-селекторами.

Приведенный ниже рисунок иллюстрирует подход к выбору различных частей результатов.

Объяснение кода

Объявите puppeteer для управления браузером Chromium из библиотеки puppeteer-extra и StealthPlugin для предотвращения обнаружения веб-сайта, что вы используете веб-драйвер из библиотеки puppeteer-extra-plugin-stealth:

const puppeteer = require("puppeteer-extra");
const StealthPlugin = require("puppeteer-extra-plugin-stealth");
Вход в полноэкранный режим Выход из полноэкранного режима

Далее мы «скажем» puppeteer использовать StealthPlugin, напишем поисковые запросы и URL YouTube:

puppeteer.use(StealthPlugin());

const queries = ["javascript", "node", "web scraping"];
const URL = "https://www.youtube.com";
Вход в полноэкранный режим Выход из полноэкранного режима

Далее напишите функцию для управления браузером и получения информации:

async function getYoutubeAutocomplete() {
  ...
}
Вход в полноэкранный режим Выход из полноэкранного режима

В этой функции сначала нужно определить browser, используя метод puppeteer.launch({options}) с текущими options, такими как headless: false и args: ["--no-sandbox", "--disable-setuid-sandbox"].

Эти опции означают, что мы используем режим headless и массив с аргументами, которые мы используем для разрешения запуска процесса браузера в онлайн IDE. Затем мы открываем новую страницу:

  const browser = await puppeteer.launch({
    headless: false,
    args: ["--no-sandbox", "--disable-setuid-sandbox"],
  });

  const page = await browser.newPage();
Войти в полноэкранный режим Выйти из полноэкранного режима

Далее мы изменяем время ожидания селекторов по умолчанию (30 сек) на 60000 мс (1 мин) для медленного интернет-соединения с помощью метода .setDefaultNavigationTimeout(), переходим на URL с помощью метода .goto() и используем метод .waitForSelector() для ожидания создания селектора #contents на странице…:

  await page.setDefaultNavigationTimeout(60000);
  await page.goto(URL);
  await page.waitForSelector("#contents");
Вход в полноэкранный режим Выход из полноэкранного режима

Затем мы определяем массив с результатами под названием autocompleteResults и запускаем цикл for...of для перебора всех запросов:

  const autocompleteResults = [];
  for (query of queries) {
    ...
  }
Вход в полноэкранный режим Выход из полноэкранного режима

Далее в цикле мы нажимаем на #search-input (метод .click()), вводим текущий query методом page.keyboard.type(query) и ждем 5 секунд, используя метод .waitForTimeout(5000):

    await page.click("#search-input");
    await page.keyboard.type(query);
    await page.waitForTimeout(5000);
Войти в полноэкранный режим Выход из полноэкранного режима

Затем мы создаем объект results, который имеет ключи query и autocompleteResults. Мы получаем autocompleteResults, используя метод page.evaluate() для выполнения кода в скобках в контексте браузера.

Там нам нужно использовать метод .querySelectorAll(), который возвращает статический NodeList, представляющий список элементов документа, соответствующих селекторам css в скобках, и преобразовать результат в массив с помощью метода Array.from() для итерации по этому массиву.

После этого мы находим элемент с именем класса .sbqs_c (метод .querySelector()), получаем необработанный текст (свойство textContent) и удаляем пробелы с обоих концов строки методом .trim() из каждого элемента .sbdd_a li. Поскольку иногда в конце встречаются пустые узлы, нам нужно отфильтровать наш массив и оставить истинные элементы (.filter((el) => el)):

    const results = {
      query,
      autocompleteResults: await page.evaluate(() => {
        return Array.from(document.querySelectorAll(".sbdd_a li"))
          .map((el) => el.querySelector(".sbqs_c")?.textContent.trim())
          .filter((el) => el);
      }),
    };
Вход в полноэкранный режим Выход из полноэкранного режима

Далее мы помещаем объект results из текущего шага итарации в массив autocompleteResults, нажимаем кнопку #search-clear-button для очистки ввода поиска и ждем 2 секунды перед следующей итарацией:

    autocompleteResults.push(results);
    await page.click("#search-clear-button");
    await page.waitForTimeout(2000);
Вход в полноэкранный режим Выход из полноэкранного режима

И, наконец, мы закрываем браузер и возвращаем полученные данные:

  await browser.close();

  return autocompleteResults;
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь мы можем запустить наш парсер:

$ node YOUR_FILE_NAME # YOUR_FILE_NAME is the name of your .js file
Войти в полноэкранный режим Выйти из полноэкранного режима

Выход

[
   {
      "query":"javascript",
      "autocompleteResults":[
         "javascript",
         "javascript tutorial for beginners",
         "javascript full course",
         "javascript tutorial",
         "javascript dom",
         "javascript mastery",
         "javascript course",
         "javascript interview questions and answers",
         "javascript for beginners",
         "javascript с нуля",
         "javascript project",
         "javascript ninja",
         "javascript game",
         "javascript interview"
      ]
   },
   {
      "query":"node",
      "autocompleteResults":[
         "node js",
         "node js tutorial",
         "node",
         "node js project",
         "node js express",
         "node js interview",
         "node video tutorial",
         "node video",
         "node js interview questions",
         "node js event loop",
         "node js уроки",
         "nodemailer",
         "node red",
         "nodemcu"
      ]
   },
   {
      "query":"web scraping",
      "autocompleteResults":[
         "web scraping weather data python",
         "web scraping",
         "web scraping python",
         "web scraping javascript",
         "web scraping amazon product",
         "web scraping amazon price",
         "web scraping amazon",
         "web scraping amazon reviews",
         "web scraping amazon reviews python",
         "web scraping indeed",
         "web scraping flight prices",
         "web scraping using python",
         "web scraping tutorial"
      ]
   }
]
Войти в полноэкранный режим Выход из полноэкранного режима

Извлечение предложений из Google Autocomplete Client

Предыдущий пример был «трудным» способом. Также вы можете разобрать данные, используя следующий URL, который выведет txt-файл:

"https://clients1.google.com/complete/search?client=youtube&hl=en&q=minecraft"
Войти в полноэкранный режим Выйти из полноэкранного режима

Если вы хотите увидеть некоторые проекты, сделанные с помощью SerpApi, пожалуйста, напишите мне сообщение.


Присоединяйтесь к нам на Twitter | YouTube

Add a Feature Request💫 or a Bug🐞

Оцените статью
devanswers.ru
Добавить комментарий