Как использовать node.js, request и cheerio для настройки простой веб-скребок

Вступление:

В этом уроке мы очистим первую страницу Hacker News, чтобы получить все ссылки верхнего рейтинга, а также их метаданные, такие как заголовок, URL-адрес и количество полученных баллов / комментариев. Это один из многих методов для извлечения данных с веб-страниц с помощью node.js и в основном использует модуль cheerio от Matthew Mueller, который реализует подмножество jQuery, специально разработанное для использования на сервере.

Cheerio легкий, быстрый, гибкий и простой в использовании, если вы уже привыкли работать с jQuery. Мы также будем использовать отличный модуль запросов Микаэла Роджерса в качестве упрощенного HTTP-клиента.

Требования:

Я предполагаю, что вы уже знакомы с node.js, jQuery и базовыми административными задачами Linux, такими как подключение к VPS с использованием SSH.

Если вы незнакомы с node.js или если вы еще не установили его, обратитесь к разделу «Статьи и учебники» выше, чтобы найти инструкции по установке для вашей операционной системы.

Код:

Чтобы установить необходимые модули с помощью NPM, просто введите следующую команду:

npm install request cheerio

Это будет устанавливать модули только в вашем текущем рабочем каталоге.

Чтобы установить модули во всем мире: npm install -g request cheerio

Создайте файл scrape.jsи добавьте следующие строки:

var request = require ('request');
var cheerio = require ('cheerio');

Это загрузит все наши зависимости модуля.

Теперь мы загрузим первую страницу Hacker News простым запросом и отобразим HTML-код страницы, если ошибка не возникает, а код статуса HTTP равен 200.

Добавьте эти строки в файл:

request ('https://news.ycombinator.com', функция (ошибка, ответ, html) {
  if (! error && response.statusCode == 200) {
    console.log (HTML);
  }
});

Попробуйте запустить скрипт, node scrape.jsи вы увидите, что HTML-код регистрируется в окне терминала.

Чтобы узнать, как извлечь нужные метаданные, нам нужно знать, как элементы структурированы в HTML-коде. Предпочтительным способом является использование инструментов веб-разработчика, встроенных в Google Chrome, для проверки желаемого целевого элемента на веб-странице, просто щелкнув его правой кнопкой мыши и выбрав «Осмотреть элемент».

В этом примере я открыл Hacker News в Chrome, щелкнул правой кнопкой мыши и просмотрел заголовок топ-рейтинга:

Инструменты для веб-разработчиков Chrome

После быстрого просмотра консоли веб-разработчика я пришел к выводу, что мы можем просто выбрать каждый элемент «span», который имеет класс, добавленный к нему с именем «comhead», и выбрать элемент «a» над ним, используя jQuery API prev (), чтобы легко разобрать все 30 лучших рейтинговых ссылок и их заголовки.

Мы можем проверить мое предположение, изменив наш код запроса на это:

request('https://news.ycombinator.com', function (error, response, html) {
  if (!error && response.statusCode == 200) {
    var $ = cheerio.load(html);
    $('span.comhead').each(function(i, element){
      var a = $(this).prev();
      console.log(a.text());
    });
  }
});

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

request('https://news.ycombinator.com', function (error, response, html) {
  if (!error && response.statusCode == 200) {
    var $ = cheerio.load(html);
    $('span.comhead').each(function(i, element){
      var a = $(this).prev();
      var rank = a.parent().parent().text();
      var title = a.text();
      var url = a.attr('href');
      var subtext = a.parent().parent().next().children('.subtext').children();
      var points = $(subtext).eq(0).text();
      var username = $(subtext).eq(1).text();
      var comments = $(subtext).eq(2).text();
      // Our parsed meta data object
      var metadata = {
        rank: parseInt(rank),
        title: title,
        url: url,
        points: parseInt(points),
        username: username,
        comments: parseInt(comments)
      };
      console.log(metadata);
    });
  }
});

Вот обзор того, что делает добавленный код:

Выберите предыдущий элемент:

var a = $ (this) .prev ();

Получите ранг, проанализировав элемент на два уровня выше элемента «a»:

var rank = a.parent (). parent (). text ();

Разберите название ссылки:

var title = a.text ();

Разберите атрибут href из элемента «a»:

var url = a.attr ('href');

Получите дочерние подтексты из следующей строки в таблице HTML:

var subtext = a.parent (). parent (). next (). children ('. subtext'). children ();

Извлеките соответствующие данные от детей:

var points = $ (подтекст) .eq (0) .text ();
var username = $ (subtext) .eq (1) .text ();
var comments = $ (subtext) .eq (2) .text ();

Запуск измененного скрипта должен выводить массив таких объектов:

[ { rank: 1,
    title: 'The Meteoric Rise of DigitalOcean ',
    url: 'http://news.netcraft.com/archives/2013/06/13/the-meteoric-rise-of-digitalocean.html',
    points: 240,
    username: 'beigeotter',
    comments: 163 },
  { rank: 2,
    title: 'Introducing Private Networking',
    url: 'https://www.digitalocean.com/blog_posts/introducing-private-networking',
    points: 172,
    username: 'Goranek',
    comments: 75 },
...

Это оно! Теперь вы можете сохранить извлеченные данные в базе данных, например MongoDB или Redis, для дальнейшей обработки. Вот полный исходный код нашего файла scrape.js:

var request = require('request');
var cheerio = require('cheerio');

request('https://news.ycombinator.com', function (error, response, html) {
  if (!error && response.statusCode == 200) {
    var $ = cheerio.load(html);
    var parsedResults = [];
    $('span.comhead').each(function(i, element){
      // Select the previous element
      var a = $(this).prev();
      // Get the rank by parsing the element two levels above the "a" element
      var rank = a.parent().parent().text();
      // Parse the link title
      var title = a.text();
      // Parse the href attribute from the "a" element
      var url = a.attr('href');
      // Get the subtext children from the next row in the HTML table.
      var subtext = a.parent().parent().next().children('.subtext').children();
      // Extract the relevant data from the children
      var points = $(subtext).eq(0).text();
      var username = $(subtext).eq(1).text();
      var comments = $(subtext).eq(2).text();
      // Our parsed meta data object
      var metadata = {
        rank: parseInt(rank),
        title: title,
        url: url,
        points: parseInt(points),
        username: username,
        comments: parseInt(comments)
      };
      // Push meta-data into parsedResults array
      parsedResults.push(metadata);
    });
    // Log our finished parse results in the terminal
    console.log(parsedResults);
  }
});

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *