Как собирать данные с веб-страниц при помощи R, the RVest and pipeR Way

HowTo Инструменты Перевод

Мы публикуем перевод урока Алекса Бреслера (Alex Bresler) с пошаговой инструкцией по скрейпингу данных с помощью R.

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

Вооружись ff

Для того чтобы принять участие в этом приключении, вам понадобится иметь в арсенале серьезное оружие. Cначала проверьте, установлено ли у вас R (программное обеспечение для статистических вычислений) и RStudio  (среда разработки программного обеспечения для языка программирования R). Затем, если у вас еще нет Firefox или Chrome, выберите одного из этих боевых скакунов. И наконец, установите замечательный виджет SelectorGadget. Запустите R , прохрустите пальцами: на этом подготовка закончилась. Пришла пора играть.

Время веселья ff2

Теперь, когда мы готовы, нужно определиться, что именно мы хотим исследовать. Так как я огромный фанат Nets Brooklyn и до сих пор на седьмом небе от того, как мы недавно порвали New York Knickerbockers, то решил исследовать базы данных команды NBA с сайта Basketball Reference.

Побродив по ссылкам на главной странице, мы все-таки нашли то, что искали: таблицу результатов за все сезоны. Посмотрим на сезон 2013-2014. По правде говоря, выглядит просто как куча таблиц. Но для извлечения данных это прекрасная новость. Давайте попробуем вытащить данные из таблицы с командной статистикой. Для этого возьмем виджет Selector, спустимся на конец таблицы и выделим ее так, чтобы по краям появилось оранжевое обрамление. Должно появиться окно с надписью #team.

Это CSS Selector для таблицы. Теперь мы уже знаем, что нужно, чтобы перенести эти данные в R. Перемещаемся назад в RStudio, создаем новый скрипт-файл R, – настало время извлечь данные.

Готовься, целься, пли ff3

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

Следующий пункт: в R появилась новая модная примочка, которую используют все крутые ребята, она называется piping (конвейер данных) и используется с символами %>% или %>>%. Можете воспринимать их как слово THEN (следовательно). Мне же больше нравится %>>% из потрясающего пакета pipeR. Наконец, если увидите #, знайте, что это комментарий, и предшествующая строка кода программой не выполняется. Простите, пожалуйста, за эту неразбериху. Надеюсь, вы поймете большинство моих комментариев.

Загрузите необходимые программные пакеты

Начнем скрейпинг

Шаг первый. Давайте поместим таблицу в R. Так как мы хотим сопоставить ее с другими таблицами, необходимо отключить заголовки и посмотреть, сможем ли мы найти строку с именами столбцов. На сайте Basketball-References все таблицы со статистикой начинаются с колонки под названием Rk (что значит rank).

Как мы видим, заголовки находятся в первой строке [в некоторых случаях во второй]. Давайте извлечем данные из этой строки и переместим их в вектор, содержащий строковые элементы. Затем мы используем этот вектор, чтобы задать названия в нашем дата-фрейме. вектор в R – это один из типов данных. Его специфика в том, что все его элементы должны быть одного формата (например, только строковые значения, или только числовые, или только булевы).

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

Ехууу, данные уже в R

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

Мы сделали это! Посмотрите, теперь у нас есть чистый блок данных

nets-fan

Сохраните файл в CSV {а вообще – на ваше усмотрение}

Это было легко. Давайте покончим со всем этим и переведем наш код в функцию

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

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

Итак, мы уже знаем, как вытянуть данные из таблицы, и URL у нас тоже есть. Теперь нужно извлечь ID команды, который можно получить со страницы с этим URL точно так же, как мы скрейпили данные для таблицы, только теперь мы будем искать XML-тэги с // и гиперссылки. Этот процесс также требует некоторой зачистки данных.

Теперь нам нужно добавить в блок данных сезон и имя таблицы: команда, противник и прочие данные по каждому сезону. Если посмотреть информацию за все года, окажется, что там есть много вещей, которые можно использовать. Функция должна позволять найти данные из любой таблицы. Наконец, нам нужна возможность делать временные отметки, если мы хотим отслеживать изменения в данных за текущий сезон или получать чистые данные из Sports References автоматически.

Итак, вот она наша функция getBREFTeamStatTable

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


getBREFTeamStatTable() -> team2015
team2015 %>>% kable('html', table.attr='id="team2015"')

 giphy

Подведем итоги

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

Алекс Бреслер