В этом руководстве я расскажу вам об основах создания парсера с помощью Node.js и AWS Lambda. Мой скрепер будет ежедневно проверять, есть ли в Ослином заповеднике новые объявления о вакансиях, и пришлет мне SMS, если они появятся.

Перед тем как начать, вы должны знать:

  • Node.js и современный JavaScript
  • НПМ
  • Объектная модель документа
  • Базовая командная строка Linux
  • Базовый уход за ослами 🦄

Если вы никогда раньше не использовали Amazon Web Services, прочтите о Lambda здесь, зарегистрируйтесь в AWS, а затем ознакомьтесь с этой статьей, которая проведет вас через создание вашей первой функции Lambda. Принцип AWS заключается в том, что все части вашего приложения от хранилища до вычислительной мощности предоставляются Amazon и размещаются в облачной среде (то есть на компьютерах Amazon), что позволяет создавать автоматически масштабируемые бессерверные приложения. Вам не нужно беспокоиться о создании серверов и управлении ими, поскольку Amazon сделает все это за вас. Лямбда-функция - это просто функция, которая находится в облаке, может запускаться, когда это необходимо, и запускается событиями или вызовами API.

Мы будем использовать бессерверный фреймворк для создания нашей лямбда-функции. Ничего страшного, если вы им раньше не пользовались. Я объясню это по ходу дела! Позже мы также будем использовать другую функцию AWS, DynamoDB, для хранения данных с одного дня на другой. Наконец, мы интегрируемся с Nexmo, чтобы отправлять текстовые сообщения с нашими ежедневными обновлениями.

Почему скребок?

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

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

Шаг 1. Бессерверная установка

Взгляните на Краткое руководство по бессерверной среде и убедитесь, что вы выполнили предварительные требования. Бессерверная версия избавит от необходимости настраивать нашу среду AWS и позволит нам разрабатывать и тестировать локально, пока мы, наконец, не будем готовы развернуть все в облаке.

Давайте создадим новый бессерверный проект:

$ serverless create --template aws-nodejs --path donkeyjob
$ cd donkeyjob

Проект инициализируется файлом serverless.yml. YAML - это язык, часто используемый для файлов конфигурации, и именно этот файл содержит все параметры конфигурации AWS. Мы можем избавиться от всех комментариев и пока обойтись следующим:

service: donkeyjob
provider:
  name: aws
  runtime: nodejs6.10
functions:
  getdonkeyjobs:
    handler: handler.getdonkeyjobs

Поскольку мы сказали, что хотим иметь функцию с именем getdonkeyjobs, мы собираемся экспортировать функцию с этим именем из handler.js. Это функция, которую мы в конечном итоге развернем в AWS и будем запускать каждый день, чтобы получать списки вакансий.

В handler.js давайте создадим эту базовую функцию. Лямбда-функции принимают событие, контекст и обратный вызов. А сейчас давайте просто добавим шаблон. Остальную часть файла можно удалить.

И давайте протестируем его локально (обратите внимание, что мы пока не будем ничего развертывать в AWS)…

$ serverless invoke local --function getdonkeyjobs

И мы должны увидеть наш ответ «Привет, мир».

Шаг 2. Соскребите, соскоблите, соскоблите!

Давайте расширим функциональность парсинга. Моя цель - сделать запрос на страницу вакансий в Donkey Sanctuary и проанализировать HTML, чтобы сгенерировать массив заданий в формате:

Мы используем axios для запроса содержимого страницы, а затем передаем строку HTML в функцию синтаксического анализа, которая может быть протестирована. Внутри функции синтаксического анализа мы используем библиотеку cheerio для синтаксического анализа HTML и получения желаемой информации. Cheerio во многом похож на jQuery, но идеально подходит для использования на сервере, потому что вы можете передать ему строку HTML (то есть ответ, который вы получаете на запрос GET для страницы), и он создаст объектную модель документа, которую он может перемещать и манипулировать. Moment - удобная библиотека для работы с датами, позволяющая легко создавать стандартный формат строки ISO.

Чтобы использовать cheerio, нам нужно знать, как точно перемещаться по DOM и как выбирать элементы, которые нам нужны. Для этого вам нужно потратить некоторое время на изучение структуры HTML страницы, которую вы очищаете, с помощью инструментов разработчика в вашем браузере, и вам нужно помнить, что если структура этого HTML изменится в будущем, ваш парсер может стать бесполезным.

Теперь, если мы протестируем нашу функцию, мы должны увидеть наш массив заданий:

$ serverless invoke local --function getdonkeyjobs

Шаг 3. Настройте DynamoDB

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

Нам нужно сохранять наши данные от одного дня к другому, чтобы иметь возможность выяснить, есть ли новые рабочие места или нет. Мы не можем сделать это только с помощью одной лямбда-функции, которая позволяет сохранять только временные данные. Однако для базы данных это идеальная работа! И, конечно же, у AWS есть своя собственная база данных, которую мы можем использовать - DynamoDB. Я выбрал DynamoDB, потому что он нереляционный и простой (иш).

Сначала нам нужно настроить DynamoDB как ресурс AWS и дать нашей функции Lamdba разрешение на взаимодействие с ним. Теперь serverless.yml выглядит так:

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

Итак, бежим:

$ serverless deploy

При этом наше приложение развертывается в AWS и создаются ресурсы, запрошенные нами в файле конфигурации.

Шаг 4. Взаимодействие с DynamoDB

Теперь мы действительно можем начать использовать нашу базу данных. Для этого нам нужно установить и использовать пакет под названием aws-sdk (AWS Software Development Kit), который упрощает взаимодействие с DynamoDB. Вы можете просмотреть эти документы с примерами того, как создавать, читать, обновлять и удалять с помощью AWS SDK.

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

  • Получить вчерашние задания из базы данных (вначале их не было) с помощью метода Dynamo.scan

NB. Мы будем хранить в базе данных только один элемент за раз - вчерашние задания. Нам никогда не нужно хранить больше этого. Мы будем хранить этот элемент в следующем формате:

{
   jobs: [ {job: 'Donkey Feeder',
            closing: 'Fri Jul 21 2017 00:00:00 GMT+0100',
            location: 'Leeds, UK'},
           {job: 'Chef',
            closing: 'Fri Jul 21 2017 00:00:00 GMT+0100',
            location: 'Sheffield, UK'}
         ],
   listingId: 'Fri Jul 21 2017 14:25:35 GMT+0100 (BST)'
}
  • Сравните, чтобы увидеть разницу между вчерашними и сегодняшними заданиями, используя удобные методы lodash.
  • Мы удаляем вчерашние задания из базы данных с помощью метода Dynamo.delete.
  • Вместо этого мы сохраняем новые задания с помощью метода Dynamo.put.
  • Мы называем обратный звонок с новыми вакансиями

Мы можем протестировать нашу функцию локально, запустив

$ serverless invoke local --function getdonkeyjobs

И мы должны увидеть, что наш обратный вызов вызывается с массивом всех заданий, перечисленных в The Donkey Sanctuary сегодня, потому что, насколько нам известно, все они «новые». Со вчерашнего дня в нашей базе данных не было вакансий.

Если вы сейчас перейдете в консоль AWS, перейдите в DynamoDB, найдите свою таблицу donkeyjobs и посмотрите на элементы, вы должны увидеть сегодняшние данные, сохраненные там.

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

Шаг 5. Отправьте текст с помощью Nexmo

Теперь у нас есть список новых вакансий, давайте отправим SMS нашим пользователям, информируя их обо всех интересных вакансиях, на которые они могут претендовать!

Сначала зарегистрируйтесь в Nexmo. Он дает вам 2 доллара бесплатно, чтобы поиграть, чего достаточно. После того, как вы зарегистрируетесь, вы должны оказаться на панели инструментов, которая даст вам ключ и секрет. Они понадобятся вам для отправки текстового сообщения от Nexmo.

Мы можем использовать пакет nexmo npm для очень простой обработки запроса на отправку текста. Установите его и перенесите в свой handler.js файл. Перед вызовом последнего обратного вызова в нашем getdonkeyjobs обработчике мы можем отправить любое текстовое сообщение, которое захотим:

Чтобы проверить это, нам нужно очистить таблицу DynamoDB, чтобы Lambda действительно действительно считала, что есть новые задания (мы можем сделать это из консоли AWS, как показано ниже), а затем мы можем запустить наша функция снова локально.

И если повезет, мы должны были получить текстовое сообщение!

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

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

И теперь мы, наконец, закончили, мы можем в последний раз развернуть все наше приложение на AWS:

$ serverless deploy

Шаг 6. Настройте Lambda для ежедневного запуска

После того, как мы развернем функцию, мы можем протестировать ее, чтобы убедиться, что все работает:

И мы также можем выбрать автоматический запуск функции один раз в день. Мы можем выбрать «Добавить триггер», выбрать «CloudWatch Events» из списка, а затем заполнить необходимые поля. Мы можем использовать выражение расписания скорость (1 день), чтобы запускать его ежедневно.

Вот и все!

🦄 🦄 🦄 🦄 🦄 🦄 🦄

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

Полный код доступен здесь: https://github.com/harrietty/AWS-donkeyjob-scraper

Харриет - глава сообщества Northcoders