0Pricing
R Academy · Урок

Скрейпинг таблиц и ссылок

Разбирайте таблицы HTML в таблицы данных и собирайте все гиперссылки на странице.

«Скрейпинг таблиц и ссылок» — бесплатный урок R Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения R Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс R Academy содержит 4 уроков всего.

HTML-таблицы на веб-страницах

HTML-таблицы (<table>) — наиболее удобные цели для скрейпинга, поскольку они уже имеют структуру. Функция html_table() из rvest напрямую преобразует их в таблицы данных R, автоматически обрабатывая заголовки.

library(rvest)
html <- read_html('
  <table>
    <thead><tr><th>Country</th><th>GDP</th><th>Pop</th></tr></thead>
    <tbody>
      <tr><td>USA</td><td>25T</td><td>330M</td></tr>
      <tr><td>China</td><td>18T</td><td>1400M</td></tr>
    </tbody>
  </table>
')
# html_table converts to data frame
tbl <- html_table(html_element(html, 'table'))
class(tbl)      # 'data.frame'
names(tbl)      # c('Country', 'GDP', 'Pop')
nrow(tbl)       # 2
print(tbl)

html_table() для всей страницы

Если на странице несколько таблиц, используйте html_elements() (множественное число), чтобы получить все таблицы, а затем примените html_table() к полученному набору узлов, чтобы вернуть список таблиц данных. Выберите нужную таблицу по индексу.

library(rvest)
html <- read_html('
  <table id="t1"><tr><th>A</th></tr><tr><td>1</td></tr></table>
  <table id="t2"><tr><th>X</th><th>Y</th></tr>
    <tr><td>10</td><td>20</td></tr></table>
')
# Get ALL tables as a list of data frames
tables <- html_table(html_elements(html, 'table'))
length(tables)  # 2

# First table
tables[[1]]

# Second table
tables[[2]]

# Select a specific table by its id
table2 <- html_table(html_element(html, '#t2'))
print(table2)

Очистка данных таблицы

В таблицах, собранных с веб-сайтов, часто встречаются неаккуратные заголовки, объединённые ячейки или лишние пробелы. Используйте janitor::clean_names() для заголовков, а стандартные операции dplyr/stringr — для очистки значений ячеек.

library(rvest)
html <- read_html('
  <table>
    <tr><th>Product Name</th><th>Price (USD)</th><th>In Stock?</th></tr>
    <tr><td>  Widget A  </td><td>$12.50</td><td>Yes</td></tr>
    <tr><td>Gadget B</td><td>$7.99</td><td>No</td></tr>
  </table>
')
df <- html_table(html_element(html, 'table'))

# Clean column names
names(df) <- c('product', 'price', 'in_stock')

# Strip whitespace and dollar signs
df$product  <- trimws(df$product)
df$price    <- as.numeric(gsub('[$]', '', df$price))
df$in_stock <- df$in_stock == 'Yes'
print(df)

Сбор всех ссылок на странице

Ссылки — это теги-якоря (<a>) с атрибутами href. Используйте html_elements(page, 'a'), чтобы получить все якоря, затем html_attr('href') — для URL, а html_text2() — для текста ссылок.

library(rvest)
html <- read_html('
  <div>
    <a href="/about">About Us</a>
    <a href="/products">Products</a>
    <a href="https://partner.com" rel="external">Partner</a>
    <a>No href link</a>
  </div>
')
# Get all anchor elements
anchors <- html_elements(html, 'a')

# Extract text and href
link_text <- html_text2(anchors)
link_href <- html_attr(anchors, 'href')

data.frame(text = link_text, href = link_href)
# Note: last row has NA href

Фильтрация значимых ссылок

На настоящих страницах навигационные ссылки, ссылки в нижнем колонтитуле и внутренние якоря перемешаны со ссылками, которые Вам действительно нужны. Удалите NA, якоря (#) и ссылки javascript:, а затем примените сопоставление с шаблоном, чтобы оставить только нужные URL.

library(rvest)
html <- read_html('
  <div>
    <a href="/article/1">Article One</a>
    <a href="/article/2">Article Two</a>
    <a href="#top">Back to top</a>
    <a href="javascript:void(0)">JS link</a>
    <a href="/article/3">Article Three</a>
  </div>
')
anchors <- html_elements(html, 'a')
hrefs <- html_attr(anchors, 'href')
texts <- html_text2(anchors)

# Keep only article links
article_idx <- grepl('^/article/', hrefs) & !is.na(hrefs)
article_links <- data.frame(
  text = texts[article_idx],
  href = hrefs[article_idx]
)
print(article_links)

От относительных URL к абсолютным

Извлечённые значения href часто являются относительными путями, например /page. Преобразуйте их в абсолютные URL, добавив базовый URL. Функция xml2::url_absolute() корректно выполняет это преобразование.

library(rvest)
base_url <- 'https://books.toscrape.com'

html <- read_html('
  <ul>
    <li><a href="/catalogue/book1">Book One</a></li>
    <li><a href="/catalogue/book2">Book Two</a></li>
    <li><a href="https://external.com/book">External</a></li>
  </ul>
')
hrefs <- html_attr(html_elements(html, 'a'), 'href')

# xml2::url_absolute resolves relative + keeps absolute
abs_urls <- xml2::url_absolute(hrefs, base = base_url)
abs_urls
# 'https://books.toscrape.com/catalogue/book1'
# 'https://books.toscrape.com/catalogue/book2'
# 'https://external.com/book'  <- kept as-is

Целевой сбор ссылок

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

library(rvest)
html <- read_html('
  <nav class="breadcrumb">
    <a href="/">Home</a> > <a href="/books">Books</a>
  </nav>
  <ul class="products">
    <li><a href="/books/1" class="prod-link">Clean Code</a></li>
    <li><a href="/books/2" class="prod-link">Refactoring</a></li>
  </ul>
  <footer>
    <a href="/privacy">Privacy</a>
  </footer>
')
# Target ONLY product links (not nav or footer)
prod_links <- html_elements(html, 'ul.products a.prod-link')
data.frame(
  title = html_text2(prod_links),
  url   = html_attr(prod_links, 'href')
)

Объединение данных таблиц и ссылок

Нередко ячейки таблицы содержат ссылки. Объединяйте html_table() для получения текстовых значений и целевой вызов html_attr() для встроенных ссылок, чтобы создать более информативную таблицу данных.

library(rvest)
html <- read_html('
  <table class="results">
    <tr><th>Book</th><th>Author</th></tr>
    <tr>
      <td><a href="/b/1">Clean Code</a></td>
      <td>Robert Martin</td>
    </tr>
    <tr>
      <td><a href="/b/2">Refactoring</a></td>
      <td>Martin Fowler</td>
    </tr>
  </table>
')
# Get text from table
df <- html_table(html_element(html, 'table'))

# Get links embedded in first column
links <- html_attr(html_elements(html, 'table td a'), 'href')
df$url <- links
print(df)

Параметр fill функции html_table()

В HTML-таблицах иногда встречаются отсутствующие ячейки или строки с нерегулярной структурой. Параметр fill=TRUE функции html_table() заполняет отсутствующие значения значением NA вместо создания ошибки.

library(rvest)
html <- read_html('
  <table>
    <tr><th>Name</th><th>Score</th><th>Grade</th></tr>
    <tr><td>Alice</td><td>95</td><td>A</td></tr>
    <tr><td>Bob</td><td>80</td></tr>
  </table>
')
# Without fill=TRUE this may error on uneven rows
df <- html_table(html_element(html, 'table'), fill = TRUE)
print(df)
# Name  Score Grade
# Alice    95     A
# Bob      80  <NA>

# fill=TRUE is safe even when rows are uniform
is.na(df[2, 'Grade'])  # TRUE

Извлечение источников изображений

Изображения используют атрибуты src (а иногда data-src для отложенной загрузки). Тот же подход с html_attr() позволяет извлекать URL изображений для скачивания или каталогизации.

library(rvest)
html <- read_html('
  <div class="gallery">
    <img src="/img/photo1.jpg" alt="Sunset">
    <img src="/img/photo2.jpg" alt="Mountains">
    <img data-src="/img/lazy.jpg" class="lazy" alt="Lake">
  </div>
')
# Regular images
images <- html_elements(html, 'img')
srcs  <- html_attr(images, 'src')
alts  <- html_attr(images, 'alt')

data.frame(alt = alts, src = srcs)
# For lazy-loaded images check data-src
lazy_src <- html_attr(html_element(html, '.lazy'), 'data-src')
lazy_src  # '/img/lazy.jpg'

Сохранение собранных данных

После сбора таблиц и ссылок в таблицу данных сохраните результаты с помощью write.csv() или readr::write_csv(). Всегда добавляйте отметку времени или исходный URL, чтобы сохранять сведения о происхождении данных.

library(rvest)
html <- read_html('
  <table>
    <tr><th>Product</th><th>Price</th></tr>
    <tr><td>Widget</td><td>9.99</td></tr>
    <tr><td>Gadget</td><td>14.50</td></tr>
  </table>
')
df <- html_table(html_element(html, 'table'))

# Add metadata
df$scraped_at <- Sys.time()
df$source_url <- 'https://example.com/products'

# Save to CSV
# write.csv(df, 'products.csv', row.names = FALSE)
print(df)
cat('Data ready for analysis or storage')

Быстрая проверка

Проверьте, насколько хорошо Вы понимаете сбор HTML-таблиц и ссылок с помощью rvest.

Итоги: таблицы и ссылки

Главное: html_table() автоматически преобразует HTML-таблицы в таблицы данных; используйте fill=TRUE для таблиц с нерегулярной структурой. Для ссылок получите все якоря с помощью html_elements('a'), текст — с помощью html_text2(), а URL — с помощью html_attr('href'). Преобразуйте относительные URL в абсолютные с помощью xml2::url_absolute(). Фильтруйте ненужные ссылки по шаблону. Объединяйте текст таблицы и URL встроенных ссылок, чтобы получить более информативные наборы данных.

library(rvest)
# Table scraping pattern:
# tables <- html_table(html_elements(page, 'table'))
# df <- tables[[1]]

# Link scraping pattern:
# links <- html_elements(page, 'a[href]')
# data.frame(
#   text = html_text2(links),
#   url  = xml2::url_absolute(
#            html_attr(links, 'href'),
#            base = base_url
#          )
# )

# Combine: scrape table text AND embedded link URLs
cat('Tables + links = most of what the web offers')

Часто задаваемые вопросы

Урок «Скрейпинг таблиц и ссылок» бесплатный?

Да — полный текст урока «Скрейпинг таблиц и ссылок» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс R Academy, подпишись на CoddyKit PRO. Курс R Academy содержит 4 уроков всего.

Чему я научусь в уроке «Скрейпинг таблиц и ссылок»?

Разбирайте таблицы HTML в таблицы данных и собирайте все гиперссылки на странице. Ты практикуешь R Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать R Academy?

Предыдущий опыт не требуется. R Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Скрейпинг таблиц и ссылок»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке R Academy?

Да. Каждый урок R Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Структура HTML и селекторы CSS
  2. Основы html_element() и html_text()
  3. Скрейпинг таблиц и ссылок
  4. Обработка разбивки на страницы и нескольких страниц
← Назад к R Academy