Рубрики
Без рубрики

Построить веб-API с Express и Cheerio

Автор оригинала: Adam McQuistan.

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

Наиболее распространенными способами собирать и совокупные данные, доступные в Интернете, являются (1), чтобы запросить его из API с такими технологиями, как Отдых или Мыло и (2) Чтобы написать программу для анализа или соскрести его от слабо структурированных данных, таких как HTML. Первый – это безусловно, предпочтительный метод для программиста потребляет информацию, но это часто не является возможностью из-за времени разработки и ресурсов, необходимых на стороне производителя. Следовательно, чаще всего не единственное доступное средство для попадания в ценные данные состоит в том, чтобы соскрести его.

Эта статья собирается представлять технику для создания автономного приложения Node.js, который собирает (царапины) налоговые данные для штата Небраска и представляет эту информацию пользователю или вычислять налоги на основе поставленных налогов на город и поставленную сумму.

Технологии, которые необходимо использовать:

  • Node.js: JavaScript Runtime, построенный на двигателе V8 Chrome
  • Экспресс: веб-каркас Node.js
  • Cheerio: библиотека Parsing HTML, которая отражает знакомый API jQuery Bibile API

Исходный код можно найти на Github здесь Отказ

Настройка базового проекта

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

Инициализируйте проект, принимающий основные параметры по умолчанию:

Установка зависимостей:

Базовая структура проекта:

выражать

Мы будем использовать Экспресс Чтобы построить нашу спокойную API для налогового расчета приложения. Express – это Web Application Framework для приложений узла, которая оба гибко в том, что она налагает несколько ограничений в том, как вы разрабатываете свои приложения, но очень мощные, поскольку он обеспечивает несколько полезных функций, которые используются во множестве веб-приложений.

Настройка экспресс

В Server.js мы будем включать в себя несколько кода установки CoilerPlate Express, который создаст приложение Express, затем зарегистрируйте модуль маршрутов, которые мы сделаем в следующем подразделе. В конце файла мы проинструктируем приложение Express прислушиваться к предоставленному порту или 3500, который является жесткодируемым портом.

В Server.js Скопируйте и вставьте в следующий код:

'use strict';

const express = require('express');
const app = express();
const port = process.env.PORT || 3500;

const routes = require('./api/routes');
routes(app);

app.listen(port);

console.log("Node application running on port " + port);

Маршруты

Мы создадим маршрутизацию в нашем приложении, чтобы ответить на запросы, внесенные в определенные и значимые пути URI. Что я имею в виду под значимым, вы можете спросить? Хорошо в остальных парадигмах маршрута дороги предназначены для выставления ресурсов в приложении в себе, описывающие способы.

В маршрутах/index.js Файловая копия и вставка в следующий код:

'use strict';

const taxCtrl = require('../controllers');

module.exports = (app) => {
    app.use(['/calculate/:stateName/:cityName/:amount', '/taxrate/:stateName/:cityName'], (req, res, next) => {
        const state = req.params.stateName;
        if (!taxCtrl.stateUrls.hasOwnProperty(state.toLowerCase())) {
            res.status(404)
                    .send({message: `No state info found for ${state}`});
        } else {
            next();
        }
    });

    app.route('/taxrate/:stateName/:cityName')
        .get(taxCtrl.getTaxRate);

    app.route('/calculate/:stateName/:cityName/:amount')
        .get(taxCtrl.calculateTaxes);
  
    app.use((req, res) => {
        res.status(404)
            .send({url: `sorry friend, but url ${req.originalUrl} is not found`});
    });
}

Две маршруты, определенные в этом модуле, являются /Taxrate/: stateName/: CityName и /рассчитать/: stateName/: cityname/: сумма Отказ Они зарегистрированы в приложение Объект, который был передан в модуль с скрипта Server.js, описанный выше, вызывая метод маршрута на приложение Отказ В рамках метода маршрута указан маршрут, а затем получить Способ называется или цепной, на результате вызовов маршрута. Внутри сетевого метода Get – это функция обратного вызова, которую мы далее обсудим в разделе на контроллерах. Этот метод определения маршрутов известен как «цепочка маршрута».

Первый маршрут описывает конечную точку, которая будет отображать государственные и городские налоговые ставки в ответ на запрос на получение, соответствующие : stateName и : CityName , соответственно. В Express вы указываете, что известно как «маршрутные параметры», предшествующие разрезе маршрута, разграниченного между форвардными сушими, с толстой кишкой, чтобы указать заполнитель для значимого параметра маршрута. Второй маршрут /рассчитать/: stateName/: cityname/: сумма Описывает конечную точку, которая рассчитывает городские и государственные налоговые суммы, а также общую сумму, основанную от параметра суммы маршрута.

Две другие вызовы приложение Объект указывает промежуточное программное обеспечение. Express.js промежуточное ПО является невероятно полезной особенностью, которая имеет много приложений, которые могут легко оправдать свою собственную серию статей, поэтому я не буду здесь большую глубину. Просто знайте, что промежуточное программное обеспечение – это функции, которые могут подключаться к, доступ и изменять запрос, ответ, ошибку и следующие объекты экспресс-цикла ответа-ответа.

Вы регистрируете функцию промежуточного программного обеспечения, вызывая использовать Метод на приложение Объект и прохождение в уникальных комбинациях маршрутов и функций обратного вызова. Первое промежуточное программное обеспечение, заявленное в объекте приложения, указывает наши два URL в массиве и функцию обратного вызова, которая проверяет, доступна ли государство для запрашивания налоговой информации.

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

Контроллеры

Контроллеры являются частью экспресс-приложения, которое обрабатывает фактические запросы, выполненные на определенные маршруты и возвращает ответ. Строго говоря, контроллеры не являются требованием для разработки экспресс-приложений. Функция обратного вызова, анонимное или иное, можно использовать, но с использованием контроллеров приводит к лучшему организованному коду и разделению проблем. Это, как говорят, мы будем использовать контроллеры, так как всегда есть хорошая идея, чтобы следовать за лучшими практиками.

В ваших контроллерах/index.js скопируйте и вставьте следующий код.

'use strict';

const svc = require('../services');

const getTaxRate = (req, res) => {
    const state = req.params.stateName;
    svc.scrapeTaxRates(state, stateUrls[state.toLowerCase()], (rates) => {
        const rate = rates.find(rate => {
            return rate.city.toLowerCase() === req.params.cityName.toLowerCase();
        });
        res.send(rate);
    });
}

const calculateTaxes = (req, res) => {
    const state = req.params.stateName;
    svc.scrapeTaxRates(state, stateUrls[state.toLowerCase()], (rates) => {
        const rate = rates.find(rate => {
            return rate.city.toLowerCase() === req.params.cityName.toLowerCase();
        });
        res.send(rate.calculateTax(parseFloat(req.params.amount)));
    });
}


const stateUrls = {
    nebraska: 'http://www.revenue.nebraska.gov/question/sales.html';
};

module.exports = {
    getTaxRate,
    calculateTaxes,
    stateUrls
};

Первое, что вы считаете импортируемым и заявленным в модуле контроллеров, является постоянным, называемым SVC который коротко для «услуги». Этот объект Service служит многоразовой функциональностью для запроса веб-страницы и анализа результирующего HTML. Я пойду на глубину в разделе «Более глубокая» в разделе «Мало и Услуги по поводу того, что происходит за кулисами с этим объектом обслуживания», но на данный момент просто знайте, что он анализирует HTML для значимых битов, которые мы заинтересованы в основе (I., налоговые ставки).

Две функции, которые нас больше всего интересуют GetTaxrate и Калькулятетаки Отказ Обе функции передаются по запросу и ответу ( req и res ) объекты через Route.get (...) Методы в модуле маршрутов. GetTaxrate Функция доступа к stateName Параметр маршрута по объекту параметров объекта запроса.

Имя государства и его соответствующее целевое URL-адрес (в этом случае только Nebraska и его государственная веб-страница отображаются налогооблагаемой информации), передаются методу объекта сервиса Scrapetaxrates Отказ Функция обратного вызова передается в качестве третьего параметра для отфильтрования и ответа на городскую информацию, соответствующую CityName Параметр найден на пути маршрута.

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

Модели

Подобно контроллерам, модели не являются чем-то, что строго требуется для экспресс-приложения. Тем не менее, модели вполне удобны, когда мы хотим инкапсулировать данные (штат) и поведение (действия) в наших приложениях организованным образом.

В ваших моделях/index.js файл, скопируйте и вставьте следующий код:

'use strict'

class TaxRate {
    constructor(state, city, localRate, stateRate) {
        this.state = state;
        this.city = city;
        this.localRate = localRate;
        this.stateRate = stateRate;
    }

    calculateTax (subTotal) {
        const localTax = this.localRate * subTotal;
        const stateTax = this.stateRate * subTotal;
        const total = subTotal + localTax + stateTax;
        return {
            localTax,
            stateTax,
            total
        };
    }
}

module.exports = TaxRate;

Единственная модель (или более правильно указана: класс), что мы определимся в нашем приложении Налогов Отказ Налогов Содержит поля участников для хранения данных о состоянии, городской, местной налоге и ставке государственной налога. Это классные поля, которые составляют состояние объекта. Есть только один метод класса, CalculateTax (...) , который принимает в параметра, представляющий собой субтетальную сумму, передаваемую в маршрут /рассчитать/: stateName/: cityname/: сумма Путь и вернет объект, представляющий рассчитанные налоговые величины и окончательная общая сумма.

Сияние

Cheerio Является ли легкая учетная библиотека JavaScript, которая реализует ядро JQuery для доступа, выбора и запроса HTML в серверных приложениях. В нашем случае мы будем использовать Cheerio для анализа HTML в статической веб-странице, мы просим на веб-сайте правительства Nebraska, отображающую налоговую информацию.

Услуги

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

В ваших услугах/index.js скопируйте и вставьте следующий код:

'use strict';

const http = require('http');
const cheerio = require('cheerio');
const TaxRate = require('../models');

const scrapeTaxRates = (state, url, cb) => {
    http.get(url, (res) => {
        let html = '';
  
        res.on('data', chunk => {
            html += chunk;
        });
  
        res.on('end', () => {
            const parser = new Parser(state);
            const rates = parser.parse(html);
            cb(rates);
        });
    });
};

class Parser {
    constructor(state) {
        this.state = state;
    }

    parse(html) {
        switch(this.state.toLowerCase()) {
            case 'nebraska':
                return this.parseNebraska(html);
            default:
                return null;
        }
    }

    parseNebraska(html) {
        const $ = cheerio.load(html);
        let rates = [];
        $('tr').each((idx, el) => {
            const cells = $(el).children('td');
            if (cells.length === 5 && !$(el).attr('bgcolor')) {
                const rawData = {
                    city: $(cells[0]).first().text(),
                    cityRate: $(cells[1]).first().text(),
                    totalRate: $(cells[2]).first().text()
                };
                rawData.cityRate = parseFloat(rawData.cityRate.replace('%', ''))/100;
                rawData.totalRate = parseFloat(rawData.totalRate.substr(0, rawData.totalRate.indexOf('%')))/100;
                rawData.stateRate = rawData.totalRate - rawData.cityRate;
                rates.push(new TaxRate('Nebraska', rawData.city, rawData.cityRate, rawData.stateRate));
            }
        });
        return rates;
    }
}

module.exports = {
    scrapeTaxRates;
};

Первые три линии импортируют (через требуют () ) некоторые объекты уровня модуля http , Cheerio и Налогов Отказ Налогов Был описан в предыдущем разделе на модулях, поэтому мы не будем преодолевать допущенную мертвую лошадь и пройти его слишком много деталей, поэтому достаточно, чтобы он сказал, что он используется для хранения данных о ставке налога и рассчитывает налоги.

http Объект – это модуль узла, который используется для создания запросов с сервера на другой сетевой ресурс, который в нашем случае является веб-страницей налоговой ставки от правительства Небраски. Оставшееся – это Cheerio, который используется для анализа HTML с использованием знакомых API jQuery.

Модуль услуг обнаруживает только одну общедоступную функцию, называемую Scrapetaxrates , который принимает строку состояния, строку URL-адреса (для страницы состояния отображается налоговые ставки), а также функция обратного вызова для обработки налоговых ставок уникальными способами, указанными в Calling Client Code.

В теле Scrapetaxrates Функция получить Метод для http Объект вызывается для запроса веб-страницы в указанном URL. Функция обратного вызова передана на http.get (...) Метод обрабатывает обработку ответа. При обработке ответа строка HTML построена и сохраняется в переменной, называемой HTML Отказ Это делается в инкрементном моде, как данные Событие уволено, а буферизованный кусок данных возвращается из ответа.

После стрельбы конец Событие Заключена функция обратного вызова. Внутри этого обратного вызова Парсер Класс создается экземпляром, а метод анализа вызывается для анализа HTML и извлекать информацию, специфичную к структуре и расположению веб-страницы Nebraska. Данные с анализом загружаются в серию Налогов Объекты, хранящиеся в массиве и передавались в функцию обратного вызова для выполнения логики, указанной в вызовом клиентском коде (в нашем случае, в функциях контроллера, описанных ранее). Это на этом последнем этапе, что данные сериализуются и отправляются в качестве ответа на абонента API для отдыха.

Заключение

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

Например, ниже вы найдете скриншоты приложения, демонстрирующие налоги для города Омаха, а также расчет налогов для субтетала 1000 долларов. Для того, чтобы проверить это приложение CD в корневой каталог и введите $ Node Server.js в консоль. Вы увидите сообщение, которое говорит: «Узел приложение работает на порту 3500».

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