Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Ruby

Создаем свой первый веб-скрэпер, часть 1

by
Length:LongLanguages:

Russian (Pусский) translation by blacktreelab (you can also view the original English article)

В мире Ruby есть два пакета, находящиеся в центре внимания веб-скрэпинга последние годы: это Nokogiri и Mechanize. Мы посвятим каждому из них по статье, а затем перейдем к практической части.

Темы

  • Вэб Скрэпинг?
  • Разрешение
  • Проблема
  • Nokogiri
  • Экстракция?
  • Страницы
  • API
  • Навигация по элементам

Вэб Скрэпинг?

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

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

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

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

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

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

Ну, а что насчет API? Хороший вопрос. Если у вас есть доступ к сервисам с API, то вам нет никакой необходимости писать собственный скрэпер. Данный подход нужен только для сайтов, которые не предлагают такие удобства. Без наличия API, это единственный способ автоматизировать экстракцию данных из веб страниц.

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

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

Разрешение

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

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

Проблема

Мне нужно сделать новый сайт для подкастов. Дизайн был так себе, и я терпеть не мог публиковать новые посты. О ужасный WYSIWYG! Немного предисловия. Около двух лет назад я создал первую версию своего сайта для подкастов. Моя идея была изучить фреймворк Sinatra и сделать что-нибудь облегченное. У меня появилось несколько проблем, так я переделывал по своему практически все.

После Rails, мне пришлось потрудиться, что, впрочем, пошло мне на пользу. Но мне пришлось пожалеть, что я не создал статичный сайт и не запустил его на GitHub через GitHub pages. Запуск и обслуживание эпизодов не содержало той простоты, к которой я стремился. На какое время, я перестал заниматься этой проблемой, и сосредоточился на материале для подкастов.

Прошлым летом я работал над сайтом на Middleman, который размещен на GitHub pages. Для второго сезона моего шоу нужен был свежий облик. Новый, упрощенный дизайн, Markdown для публикации эпизодов, и никаких проблем с Heroku - красота! Проблема была в том, что у меня было в наличии 139 эпизодов, которые надо было загрузить и конвертировать, чтобы можно было работать с Middleman.

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

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

Nokogiri

Даже если вы полный новичок в Ruby/Rails, велики шансы что вы уже слышали об этом пакете. Имя это часто на слуху, и хорошо запоминаемо. Не уверен, что многие знают что, nokogiri означает "пила" по-японски.

Вы поймете, что имя это очень подходит, как только узнаете, на что способен данный инструмент. Создатель этого пакета Aaron Patterson, который носит ник Tenderlove. Nokogiri преобразовывает документы XML и HTML в структуры данных - а именно, в структуру данных дерево. Инструмент этот быстрый с приятным интерфейсом. В общем, это довольно таки мощная библиотека, которая берет на себе решение многих проблем скрэпинга.

Nokogiri можно использовать не только для обработки HTML, но также и XML. Он дает вам возможности и XML path language и интерфейса CSS для обработки документов. XML path language, или, для краткости, XPath, является языком запросов.

Он позволяет выбирать элемент документа XML. Для новичков наверное лучше известны селекторы CSS. Как и с вашими собственными стилями, селекторы CSS намного упрощают работу с различными разделами страниц для экстракции. Вам только надо дать Nokogiri знать, что вас интересует на конкретной странице.

Страницы

Начинать работу надо с извлечения конкретной страницы. Мы уточняем какой конкретно документ нас интересует - XML или HTML, как например:

some_scraper.rb

Nokogiri:XML и Nokogiri:HTML могут работать как с IO объектами так и объектами строками. То что происходит выше вполне понятно. С помощью open-uri открывается и загружается страница, и затем ее структура (XML или HTML) загружается в новый документ Nokogiri. Новичкам не приходится часто работать с XML.

Поэтому я думаю, на лучше стоит сосредоточиться на обработке HTML. Почему open-uri? Этот модуль стандартной библиотеки Ruby позволяет нам открывать сайт без всяких проблем. Так как IO объект вполне понятен, мы легко можем воспользоваться open-uri.

API

Давайте применим это на практике в нашем мини-примере:

at_css

some_podcast_scraper.rb

В данном примере мы произвели все шаги веб скрэпинга, но только на меньше шкале. Мы определились с  URL и с сайтом для экстракции, и загрузили их в документ Nokogiri. Затем мы открыли страницу и выбрали определенный раздел.

Мне нужен был только заголовок эпизода. Метод at_css и селектор CSS для h2.post-title - это все, что мне было нужно для точки экстракции. Но этот метод позволяет отбирать только один элемент. Он выделяет весь селектор, и часто это не совсем то, что нам нужно. Поэтому мы выберем только внутреннюю часть данного элемента с помощью метода text. Для сравнения, вы можете рассмотреть результаты и заголовка и текста ниже.

Результат

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

Внимание!

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

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

css

Метод css выберет не только отдельный элемент, но и все элементы страницы, соответствующие критериям поиска. Четко и понятно!

some_scraper.rb

Результат

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

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

some_scraper.rb

Результат

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

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

Атрибуты

Что может быть полезным на данном этапе, так это извлечение элемента href для каждого отдельного эпизода. Нет ничего проще.

some_scraper.rb

Пожалуй, самое главное, на что стоит обратить внимание это [:href] и podcast_url. Если вы пометите элемент с помощью [:], вы можете просто извлечь атрибут из необходимого селектор. Я зашел немного дальше, но ниже вы можете видеть более ясно, как это работает.

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

Давайте взглянем не результат:

Результат

Аккуратно, не правда ли? Вы можете сделать тоже самое с элементом [:class] селектора.

Если элемент имеет более одного класса, вы получите список их всех.

Навигация по элементам

  • родительский элемент
  • дочерний элемент
  • предыдущий одноуровневый элемент
  • следующий одноуровневый элемент

Мы привыкли иметь дело со структурами дерева в CSS или даже в jQuery. И было бы неприятно, если бы Nokogiri не предлагал удобный API для перемещения внутри таких деревьев.

some_scraper.rb

Результат

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

Вы даже можете объединить их для более сложных перемещений. Вы можете усложнить процесс настолько, насколько пожелаете, но я бы порекомендовал слишком не усложнять процесс. Иначе он быстро превратится в громоздкий и мало понятный. Помните: не стоит усложнять без необходимости!

some_scraper.rb

Результат

Заключительные мысли

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

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

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.