May 15: rvest

Запись занятия

Запись занятия, которое было 15 мая, можно найти здесь:

Все записи организованы в плейлист


HTML интро

Web-сервер

При попытке открыть какую-нибудь html-страницу (сайт) происходит запрос к web-серверу, на котором размещена эта страница. Если не возникает ошибок, то сервер возвращает сообщение с кодом страницы (html + javascript). Соответственно, когда браузер получает сообщение, он обрабатывает и выполняет код, “отрисовывает страницу” для пользователя. Инструменты скрапинга (rvest, в частности), аналогично запрашивают web-сервер, однако результат не отрисовывают, а хранят в виде объекта в памяти.


Структура html-страницы

Все страницы сайтов — это текст, форматированный с помощью языка разметки html. Это значит, что все элементы страницы — тексты, картинки, гиперссылки, заголовки и проч. имеют свою метку, иначе говоря, тэг. Тэги — ключевые слова, обернутые в угловые скобки <tag_name>. Тэги всегда представлены в паре: открывающий (<tag_name>) и закрывающий тэги (</tag_name>). Между ними как раз и размещается материал страницы — текст, картинка и проч.

Стандартная html-страница имеет вид иерархического дерева тэгов, где корневой тэг — html. Ниже дан простейший пример кода страницы, в которой есть заголовок и список. Список формируется из общего тэга <ol></ol> (ordered list) и элементов списка внутри тэга, каждый в собственной паре тэгов <li></li>.

У тэгов есть атрибуты — как правило, это либо дополнительная информация (адрес гиперссылки, адрес картинки), либо класс, который используется в таблицах стилей, чтобы к разным тегам применять разные визуальные эффекты. Например, чтобы текст во всех тэгах с классом my_class1 был синим, а с классом my_class2 — зеленым. Атрибуты тэгов пишутся сразу после названия открывающего тэга, в угловых скобках: <div class="my_class1"></div>.

Пример кода страницы:

<!DOCTYPE HTML>
<html>
  <body>
    <h2>Правда о лосях в html-тегах</h2>
    
    <h3>это пример параграфа</h3>
    <p style="color:red;">
      Здесь мы расскажем вам всю правду, какую знаем о лосях
    </p>    
    
    <h3>это пример списка</h3>
    <ol>
      <li>Лось — животное хитрое</li>
      <li>...и коварное!</li>
    </ol>
    
    <h3>это пример внутритекстовой гиперссылки</h3>
    <a href="http://upravitelev.gitlab.io/mar191s">какой-то левый сайт</a>
    
    <h3>это пример тега с классом</h3>
    <p class='my_class'>дальше будет дичь</p>
    
    <h3>это пример таблицы</h3>
    <div class="table">
      <table>
        <tr><th>cell</th><th>colour</th></tr>
        <tr><td>1st</td><td>white</td></tr>
        <tr><td>2nd</td><td>red</td></tr>
        <tr><td>3rd</td><td>black</td></tr>
        <tr><td>4th</td><td>green</td></tr>
      </table>
    </div>    
  </body>
</html>

Вот так выглядит эта страница в том виде, как её присылает веб-сервер:

<pre><body><h2>Правда о лосях в html-тегах</h2><h3>это пример параграфа</h3><p style="color:red;">Здесь мы расскажем вам всю правду, какую знаем о лосях</p><h3>это пример списка</h3><ol><li>Лось — животное хитрое</li><li>...и коварное!</li></ol><h3>это пример внутритекстовой гиперссылки</h3><a href="http://upravitelev.gitlab.io/mar191s">какой-то левый сайт</a><h3>это пример тега с классом</h3><p class='my_class'>дальше будет дичь</p><h3>это пример таблицы</h3><div class="table"><table><tr><th>cell</th><th>colour</th></tr><tr><td>1st</td><td>white</td></tr><tr><td>2nd</td><td>red</td></tr><tr><td>3rd</td><td>black</td></tr><tr><td>4th</td><td>green</td></tr></table></div></body></pre>
Вот так выглядит эта страница в браузере:

Правда о лосях в html-тегах

это пример параграфа

Здесь мы расскажем вам всю правду, какую знаем о лосях

это пример списка

  1. Лось — животное хитрое
  2. ...и коварное!

это пример внутритекстовой гиперссылки

какой-то левый сайт

это пример тега с классом

дальше будет дичь

это пример таблицы

cell colour
1st white
2nd red
3rd black
4th green


rvest

Общая последовательность

Последовательность действий при скрапинге данных с помощью rvest такова:

  • с помощью функции read_html() в рабочее окружение импортируется заданая страница (web-адрес) или XML-документ

  • визуально по структуре или визуально в средствах web-разработчика (в частности, SelectorGadget и нативные инструменты браузеров для web-разрботчиков), а так же функциями html_children(), html_attrs() анализируется структура дерева элементов документа (тэгов и атрибутов)

  • с помощью функций html_element() и html_elements() указывается, какой элемент (элементы) структуры необходимо выбрать

  • из выбранного элемента с помощью функций html_text(), html_table и html_attr() извлекаются значения

  • при необходмости во время сбора данных с html-страниц процесс масштабируется на прочие схожие разделы сайта или осуществляется в регулярном формате (краулинг)


Импорт страницы

Установка и подключение пакета стандартные. На *nix/MacOS-системах могут потребоваться дополнительные библиотеки. Для импорта таблицы требуется read_html(), при импорте может быть необходимо указать кодировку.

## install.packages('rvest')
library(rvest)

## импорт страницы
url <- read_html('./data/elk.html', encoding = 'UTF-8')


Выбор узлов и их значений

Для того, чтобы извлечь значение из какого-то тэга, необходимо указать путь к этому тэгу в дереве тэгов страницы. Выбор тэгов осуществляется с помощью функции html_element(), где первым аргументом указывают импортированную страницу, а в аргументе xpath - путь к тэгу на языке XPath.

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

  • html_text() если в тэге хранится текстовое значение. По сути, используется всегда, когда в тэге не табличка и не картинка.
# извлекаем текстовое значение - заголовок
html_element(url, xpath = '//h2') %>%
  html_text()
## [1] "Правда о лосях в html-тегах"
  • html_table() если в тэге хранится таблица ( ).
    # извлекаем таблицу
    html_element(url, xpath = '//table') %>%
      html_table()
    ## # A tibble: 4 × 2
    ##   cell  colour
    ##   <chr> <chr> 
    ## 1 1st   white 
    ## 2 2nd   red   
    ## 3 3rd   black 
    ## 4 4th   green
    • html_attr('attr_name') - используется для случаев, когда надо извлечь атрибут тэга. Атрибуты тэга можно узнать, применив к выделенному с помощью html_element() тэгу функцию html_attrs().
    # смотрим атрибуты тэга <a>
    html_element(url, xpath = '//a') %>%
      html_attrs()
    ##                                                     href 
    ## "https://ru.wikipedia.org/wiki/%D0%9B%D0%BE%D1%81%D0%B8"
    # извлекаем значение атрибута href
    html_element(url, xpath = '//a') %>%
      html_attr('href')
    ## [1] "https://ru.wikipedia.org/wiki/%D0%9B%D0%BE%D1%81%D0%B8"
    # извлекаем не атрибут, а значение тэга, 
    # то есть, каким текстом видит эту ссылку пользователь
    html_element(url, xpath = '//a') %>%
      html_text()
    ## [1] "ссылка на вики"


    Навигация по дереву тегов

    Ключевые элементы языка XPath:

    • %tag_name% — название тэга %tag_name%

    • / — Иcпользуется для указания прямого пути к элементу от корневого/родительского тега. Если весь xpath-путь начинается с /, то это абсолютный путь от корня дерева. Вот так можно выбрать тэг (ноду, узел) заголовка страницы.

    # длинный путь, от корня через все поколения родителей к тэгу h2
    html_element(url, xpath = '/html/body/h2') %>%
      html_text()
    ## [1] "Правда о лосях в html-тегах"
    • // — Выбирает теги независимо от места их расположения, при этом может использоваться как в начале пути, так и в середине:
    # короткий путь, "пропусти все до первого тэга h2"
    html_element(url, xpath = '//h2') %>%
      html_text()
    ## [1] "Правда о лосях в html-тегах"
    • @ — выбор атрибута узла. Если необходимо использовать атрибут тэга в пути, то атрибут указывается как @attr_name. Если указать путь к атрибуту тэга с использованием @, то можно не использовать функцию html_attr(), а обойтись общей html_text():
    html_element(url, xpath = '//a/@href') %>%
      html_text()
    ## [1] "https://ru.wikipedia.org/wiki/%D0%9B%D0%BE%D1%81%D0%B8"
    • [x] — фильтрация тэга с помощью номера места в списке тэгов-сиблингов (на одном уровне в иерархии) или по наличию какого-либо атрибута. В целом, очень похоже на фильтрацию таблиц по номеру строки или логическому условию.
    ### выбираем по номеру тэга в списке 
    # первый заголовок h3
    html_element(url, xpath = '//h3[1]') %>%
      html_text()
    ## [1] "это пример параграфа"
    # третий заголовок h3
    html_element(url, xpath = '//h3[3]') %>%
      html_text()
    ## [1] "это пример тега с классом"
    ### выбираем по содержанию определенного атрибута
    # выбираем значение тэга <p>, у которого есть атрибут класса class="my_class"
    html_element(url, xpath = '//p[@class="my_class"]') %>%
      html_text()
    ## [1] "дальше будет дичь"
    • * — знак подстановки, “на этом месте может быть что угодно” — используется, когда надо пропустить какой-то длинный кусок дерева тэгов или точно неизвестно, какой тэг или атрибут используется:
    # не знаем тэг, знаем атрибут класс, вместо тэга пишем *
    html_element(url, xpath = '//*[@class="my_class"]') %>%
      html_text()
    ## [1] "дальше будет дичь"
    # знаем тэг, но не знаем, какой атрибут со значением "my_class"
    html_element(url, xpath = '//p[@*="my_class"]') %>%
      html_text()
    ## [1] "дальше будет дичь"


    Дополнительные материалы

    • Один из лучших справочников и туториалов по HTML. Есть примеры написания и использования тэгов. Тэги описаны по функционалу, есть список тэгов

    • Справочник и туториалы, как и w3s, но с некоторыми изменениями/дополнениями и на русском языке.

    • Короткое введение в XPath. Сайт выглядит страшненько, да и примеры все на xml (хотя разница с html минимальна). Скорее для тех, кто хочет глубже разобраться в особенностях XPath, так как содержит много излишне детальной информации.


    Домашнее задание

    • Установите и подключите пакет rvest. Импортируйте страницу https://cran.r-project.org/web/packages/rvest/index.html. Страницу можно импортировать, можно сохранить на диск (горячие клавиши для сохранения - ctrl + s). Для того, чтобы посмотреть дерево тэгов, можно страницу открыть в инструментах разработчика (клавиша F12 в большинстве браузеров и там раскрывать узлы тегов, либо правый клик мышкой и что-нибудь в меню типа “инструменты разработчика / inspect object”). Также можно сохранить страницу и открыть просто в каком-нибудь блокноте.

    • Используя полный путь XPath, выведите на печать заголовок страницы (тэг h2)

    • Используя сокращенный XPath-путь, выведите на печать заголовок страницы (rvest:…), тег h2 единственный на всей странице.

    • Выведите на печать h4-заголовок второго блока (Reverse dependencies:).

    • Выведите на печать блок информации о пакете (от Version: 0.3.5 до Downlods:). Можно сократить вывод до трех строк. Это первый тэг table на странице.

    "Автоматизированный сбор больших данных в экономико-социологических исследованиях" was written by Ph.A.Upravitelev. It was last built on 2022-02-04.

    This book was built by the bookdown R package.