Руководство для начинающих о том, как создать парсер с помощью Node.js и Cheerio.

Здравствуйте друзья,

Сегодня мы делаем кое-что очень крутое (и простое — так что не уходите). Мы собираемся создать парсер с помощью Javascript. Я собираюсь показать вам очень простой и понятный пример, и на его основе вы сможете построить что-то, применить его к другим проектам и, надеюсь, создать классные вещи.

Что такое веб-скрейпер?

Веб-скребок — это, по сути, инструмент, который извлекает данные из Интернета и использует их осмысленным образом.

Сегодня для нашего проекта мы собираемся извлечь данные со страницы Википедии Список исполнителей, которые чаще всего транслируются на Spotify.

Более конкретно, мы собираемся получить данные из этой таблицы:

В этой таблице показаны лучшие исполнители Spotify с наибольшим количеством слушателей в месяц (очевидно, за последние 30 дней). Данные будут меняться с течением времени. Мы собираемся узнать имя исполнителя, его ранг и ежемесячную аудиторию.

После того, как мы соберем эти данные, вы можете делать с ними все, что захотите. Например, вы можете разместить его на своем веб-сайте. Лично я использовал его для создания API, но это выходит за рамки этого руководства. Следуйте за мной, и, возможно, вы увидите этот урок в ближайшем будущем.

Итак, давайте начнем.

Подготовка

Для начала нам понадобится несколько инструментов.

Обычно, как показано в моем Учебнике по Axios или Учебнике по React, я рекомендую установить Node.js и VS Code. Если вы не знаете, что такое NodeJS, рекомендую прочитать мое Введение в NodeJS.

Но для этого проекта, я думаю, мы пойдем по более простому пути, чтобы процесс не был таким обширным и пугающим.

Если у вас уже установлены NodeJS и VS Code, смело используйте их. Следовать за ним будет чрезвычайно легко. В противном случае, если вы новичок, переходите к Replit.

Инструкции по повторению

Replit — это онлайн-среда разработки, которая может компилировать NodeJS. Вам не нужно ничего устанавливать на свой компьютер. Так что легко начать.

Сначала создайте новую учетную запись.

Затем создайте проект, как показано ниже:

Появится всплывающее окно, как показано ниже:

В качестве шаблона выберите Node.js. И тогда вы можете назвать свой проект как хотите. Я собираюсь назвать свой «WebScraper». После этого создайте свой проект. Пропустите следующий раздел «Подготовка кода VS» и перейдите к «Установка пакетов», чтобы начать.

Подготовка кода VS

Это набор инструкций, если вы используете VS Code. Если вы используете VS Code, я предполагаю, что вы знаете, что делаете, поэтому я не буду углубляться в это.

Создайте свой проект, запустите npm init в своем терминале, а также создайте файл index.js.

Установка пакетов

Для начала нам нужно установить два пакета: Request и Cheerio.

Запрос — это пакет npm, который позволяет нам отправлять HTTP-запросы. Мы используем запрос, чтобы получить HTML-код страницы. Нам нужно получить доступ к HTML-странице, если мы хотим собирать данные с веб-страницы.

Например:

<body>
    <h1>Hello World</h1>
</body>

Если бы мы хотели получить заголовок страницы — в данном примере это «Hello World» — вы можете ясно видеть, что мы бы извлекли его из HTML. Надеюсь, это понятно.

Двигаемся дальше, нам нужен Cheerio. Итак, запрос дает нам HTML, но нам нужен Cheerio, чтобы мы могли разобрать HTML. Нам нужны только определенные фрагменты HTML. Нам все это не нужно. Cheerio помогает нам извлекать нужные фрагменты. Таким образом, используя cheerio, мы можем изолировать «Hello World» от всего HTML-кода и использовать его осмысленно.

Надеюсь, это имеет смысл. Если это не так, вот еще один способ подумать об этом.

Для этого проекта мы получаем данные Spotify Monthly Streams со страницы статьи Википедии Список исполнителей, которые чаще всего транслируются на Spotify.

Запрос будет отправлять HTML для всей веб-страницы. Нам все это не нужно. Поэтому, чтобы получить нужные нам фрагменты, такие как имя исполнителя и ежемесячное количество слушателей, мы будем использовать cheerio.

Как установить пакеты

Установка пакетов в Replit чрезвычайно проста и удобна для начинающих. На левой боковой панели нажмите кнопку, как показано выше. Это расширит меню, в котором вы можете ввести пакеты, которые хотите установить.

Введите «cheerio».

Нам нужен тот, который просто говорит «cheerio». Нажмите кнопку +, чтобы установить.

Далее мы хотим установить request. Хотя вы можете установить пакет запроса, используя процесс, который мы только что использовали, я хочу показать вам другой способ установки пакетов.

Ваш экран должен выглядеть примерно так. С правой стороны откройте свою оболочку. Я обвел его красным. Это откроет ваш терминал.

В вашем терминале напишите следующую команду для установки запроса.

npm install request

Этот процесс также показан выше. Он должен быть успешно установлен.

Как только эти два пакета будут установлены, мы можем двигаться дальше.

Требуйте наши пакеты

Теперь, когда наши пакеты установлены, мы наконец можем приступить к работе с нашим файлом index.js. Чтобы получить доступ к этому файлу, перейдите на боковую панель и щелкните значок документа вверху. Я обвел его для вас на скриншоте выше.

Если (по какой-то причине) у вас нет файла index.js, создайте его.

Итак, первое, что мы собираемся сделать, это сделать наши пакеты доступными для использования в нашем файле Javascript. Напишите следующее в самом верху вашего файла index.js:

const request = require("request");
const cheerio = require("cheerio");

Что происходит?

require("package-name") в основном позволяет использовать пакеты в нашем скрипте. Обратите внимание, что имена пакетов чувствительны к регистру. Например, не пишите require('Request').

И вы можете видеть, что мы храним их в константной переменной. Эта константная переменная — это то, как мы собираемся получить доступ к функциям, предлагаемым этими пакетами. Чтобы было ясно, вы можете думать об этих пакетах как о библиотеках. В пакетах есть функции/методы, упрощающие кодирование.

Итак, опять же, если бы мы хотели использовать функцию загрузки Cheerio, мы бы написали cheerio.load().

Получить HTML

Теперь мы собираемся получить HTML-код веб-страницы, которую мы хотим очистить. Если вы хотите просмотреть данные Wall Street Journal, домашнюю страницу Стэнфорда или страницу вакансий Disney, вы можете это сделать.

В этом проекте мы собираем статью из Википедии Список исполнителей, которые чаще всего транслируются на Spotify.

Таким образом, первый шаг к очистке веб-страниц — это получение URL-адреса веб-страницы, которую вы хотите очистить. URL-адрес:



Следующим шагом является ввод этого URL в качестве параметра для функции request.

Функция запроса выглядит примерно так:

request("URL-here", function());

Первый параметр — это URL-адрес веб-страницы, которую вы хотите очистить.

Второй параметр — это функция, которая предоставляет инструкции о том, что вы хотите сделать после выполнения HTTP-запроса.

Вот как выглядит наша функция запроса:

request("https://en.wikipedia.org/wiki/List_of_most-streamed_artists_on_Spotify", function(error, response, html){
   ...code here
});

Вы видите, что у функции есть параметры: error, response и HTML? Таким образом, после выполнения HTTP-запроса будет получен HTTP-ответ. Ответ будет включать в себя, если произошла ошибка, код состояния ответа (указывающий, был ли ответ успешным) и код HTML.

Эти параметры в функции позволяют нам использовать информацию в ответе HTTP — и да, порядок имеет значение.

request("https://en.wikipedia.org/wiki/List_of_most-streamed_artists_on_Spotify", function(error, response, html){
   if(!error && response.statusCode == 200){
   }
});

Итак, внутри нашей функции мы собираемся добавить оператор if, как показано ниже. По сути, это говорит: «Если ошибок нет и ответ был успешным, давайте продолжим.

Верно? Потому что если были ошибки и HTML не получился, то мы ничего не можем сделать.

Распечатать HTML

Итак, давайте проведем небольшую проверку. Внутри оператора if давайте выведем HTML-код на консоль. Мы делаем это только для того, чтобы увидеть, успешно ли мы получили HTML.

const request = require("request");
const cheerio = require("cheerio");
request("https://en.wikipedia.org/wiki/List_of_most-streamed_artists_on_Spotify", function(error, response, html){
   if(!error && response.statusCode == 200){
      console.log(html)
   }
});

Если вы запустите его, вы увидите, что мы успешно получили HTML. HTML был напечатан в нашей консоли (которая показана справа).

Теперь, когда у нас есть HTML, мы можем использовать Cheerio для сбора нужных фрагментов.

Манипуляции с DOM

Прежде чем мы сможем углубиться в cheerio, вам нужно понять селекторы. Если у вас есть опыт работы с jQuery, манипулированием DOM или даже с селекторами CSS, не стесняйтесь пропустить этот раздел. В противном случае, пожалуйста, найдите время, чтобы узнать о них.

В W3 Schools есть отличная страница Справочник по селекторам. Проверьте это. Поиграйте с ними и посмотрите, как они работают.

Вот пример:

<div>
   <h2> Kyle </h2>
   <p> is a developer </p>
</div>

Чтобы выбрать h2, мы можем использовать следующие селекторы:

div h2 или просто h2

Очевидно, что по мере того, как HTML-документы становятся все более длинными и громоздкими, селекторы становятся не такими простыми. Но если вы это понимаете, смело продолжайте. В противном случае, узнать больше об этом,

Cheerio нагрузки

Итак, у нас есть HTML. Теперь нам нужно дать Cheerio этот HTML.

const $ = cheerio.load(html);

Вот как это делается. Это стандартный способ сделать это. Теперь мы можем использовать $ как способ выбора элементов из HTML. Так, например, если мы хотим выбрать элемент ‹body› из HTML, мы можем написать $("body") .

Если бы мы хотели выбрать элемент h1 из HTML, мы могли бы написать $("h1")

Если бы мы хотели выбрать элемент с идентификатором img-container, мы могли бы написать $("#img-container") и так далее. Это действительно все, чем Cheerio является. Это позволяет нам извлекать вещи.

К сожалению, HTML-код Википедии очень сложен. На скриншоте выше я показываю вам страницу Википедии слева и HTML-код справа.

(Чтобы получить доступ к HTML-коду любой веб-страницы, просто щелкните правой кнопкой мыши и нажмите «Проверить».)

Как показано на снимке экрана, чтобы получить эту точку данных 83,95, HTML усложняется. Число действительно вложено в миллиард различных элементов. По этой причине я просто дам вам селектор. Весь смысл этого урока в том, чтобы приветствовать, а не в селекторах; поэтому давайте сосредоточимся на приветствии.

Соберите данные об исполнителе

Для нашей первой задачи мы собираемся собрать массив имен художников.

const request = require("request");
const cheerio = require("cheerio");
request("https://en.wikipedia.org/wiki/List_of_most-streamed_artists_on_Spotify", function(error, response, html){
   if(!error && response.statusCode == 200){
      const $ = cheerio.load(html);
      let names = [];
      $(".mw-body .mw-body-content .mw-parser-output .wikitable tbody td a").each((i,el) => {
         const item = $(el).text().replace(/[0-9]/g, '').replace(/[\[\]']+/g,'');
         if(names.length < 20 && item != ""){
            names.push(item);
          }
      })
       console.log(names)
      }//end if statement
});

Запустите его, и вы должны увидеть массив имен исполнителей.

Давайте разберем это, чтобы вы поняли.

#1

const $ = cheerio.load(html);
let names = [];

Мы начали с загрузки нашего HTML в Cheerio и создания пустого массива с именами. В именах массивов мы будем хранить имена певцов.

#2

Затем мы использовали селектор Cheerio:

$(".mw-body .mw-body-content .mw-parser-output .wikitable tbody td a")

Выбранный элемент — это имя исполнителя из таблицы. Видите, как в конце селектора мы написали td a? Таким образом, a является якорным тегом. А анкорным текстом является имя исполнителя.

#3

Прикрепленный к селектору, вы видели каждую функцию:

$(".mw-body .mw-body-content .mw-parser-output .wikitable tbody td a").each((i,el) => {
   const item = $(el).text().replace(/[0-9]/g, '').replace(/[\[\]']+/g,'');
   if(names.length < 20 && item != ""){
      names.push(item);
   }
})

Что он делает? Посмотрите на таблицу Википедии выше. Вы видите, что за этим столом у нас несколько артистов? Таким образом, предоставленный нами селектор («.mw-body .mw-body-content .mw-parser-output .wikitable tbody td a») может описывать все эти записи в этой таблице. Селектор можно использовать для получения имен всех исполнителей.

Если вы этого не понимаете, подумайте о селекторе h2. Селектор можно использовать для выбора всех элементов h2 в документе. Верно? Или подумайте о .img-container, который является классом. Этот селектор класса можно использовать для выбора всех элементов, использующих этот класс. Верно?

Точно так же наш селектор можно использовать для выбора всех этих исполнителей. Таким образом, каждая функция в основном будет выбирать все элементы, которые может выбрать селектор. Другими словами, он собирается собрать имена всех художников.

#4

$(".mw-body .mw-body-content .mw-parser-output .wikitable tbody td a").each((i,el) => {
const item = $(el).text().replace(/[0-9]/g, '').replace(/[\[\]']+/g,'');
if(names.length < 20 && item != ""){
names.push(item);
}
})

Здесь мы видим короткую линию. Много чего происходит.

Итак, здесь переменная el представляет имя исполнителя. Вы можете видеть, что мы сделали $(el).text().

Если мы не добавим text(), вы получите ответ HTTP. Это будет выглядеть так:

Это совсем ничего. Но если мы добавим text(), мы получим фактический текст, встроенный в элементы.

Например, from <a href=””> text </a> or <div> text</div> мы получим только текст. Это то, чего мы хотим.

Вы видите все цифры и квадратные скобки? Нам не нужны эти цифры.

Чтобы избавиться от этого, мы добавляем .replace(/[0–9]/g, ‘’).replace(/[\[\]’]+/g,’’)

Вы видите все пустые строки? А тот факт, что там написано «еще 84 предмета»?

Нам нужны только 20 лучших исполнителей, и нам не нужны пустые строки. Чтобы исправить это, мы добавляем следующее:

if(names.length < 20 && item != ""){
   names.push(item);
}

По сути, если в массиве менее 20 исполнителей и строка не пуста, добавьте строку в массив.

Красивый.

Затем мы просто повторяем этот процесс для ежемесячного количества слушателей.

Соберите ежемесячное количество слушателей

Мы создаем новый пустой массив для хранения нашего ежемесячного количества слушателей.

let numbers = [];

Затем мы добавляем наш селектор:

$(".mw-body .mw-body-content .mw-parser-output .wikitable tbody tr td").each((i,el) => {
const item = $(el).html();
if(numbers.length < 20 && !isNaN(parseFloat(item))){
numbers.push(item);
}
})

Применяется та же логика из предыдущего раздела. Наш селектор можно использовать для выбора множества различных элементов. Вот почему мы используем каждую функцию.

Обратите внимание, что в этом примере мы используем $(el).html(), что отличается от предыдущего раздела, где мы использовали text(). Это связано с тем, как устроен DOM Википедии. html() вернет строку HTML — и именно так мы можем извлечь числа. Использование text() было бы невозможно.

Чтобы узнать больше об этом, я думаю, что лучший способ узнать это — просто экспериментировать. Проверьте это сами.

Запустите код

const request = require("request");
const cheerio = require("cheerio");
request("https://en.wikipedia.org/wiki/List_of_most-streamed_artists_on_Spotify", function(error, response, html){
if(!error && response.statusCode == 200){
const $ = cheerio.load(html);
let names = [];
let numbers = [];
$(".mw-body .mw-body-content .mw-parser-output .wikitable tbody td a").each((i,el) => {
const item = $(el).text().replace(/[0-9]/g, '').replace(/[\[\]']+/g,'');;
if(names.length < 20 && item != ""){
names.push(item);
}
})
console.log(names)
$(".mw-body .mw-body-content .mw-parser-output .wikitable tbody tr td").each((i,el) => {
const item = $(el).html();
if(numbers.length < 20 && !isNaN(parseFloat(item))){
numbers.push(item);
}
})
console.log(numbers)
}//end if statement
});

Это полный код.

Он также доступен в моем репозитории GitHub SpotifyMonthlyStreams. Проверьте это.

Я надеюсь, что этот учебник помог. Пока я писал это, с селекторами становилось все сложнее. Возможно, я сделаю более простой учебник в ближайшем будущем.

Спасибо за чтение.

Дальнейшее чтение





Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord.