0Pricing
R Academy · 강의

테이블과 링크 스크래핑

HTML 테이블을 데이터 프레임으로 구문 분석하고 페이지의 모든 하이퍼링크를 수집합니다.

테이블과 링크 스크래핑은(는) CoddyKit의 무료 R Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 R Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. R Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

웹 페이지의 HTML 표

HTML 표(<table>)는 이미 구조를 갖추고 있으므로 스크래핑하기에 가장 편리한 대상입니다. rvest의 html_table()은 표를 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)

페이지의 모든 링크 스크래핑하기

링크는 href 속성을 가진 앵커(<a>) 태그입니다. html_elements(page, 'a')로 모든 앵커를 가져온 다음, URL에는 html_attr('href')를, 링크 텍스트에는 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을 절대 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)

html_table()의 fill 매개변수

HTML 표에는 때때로 없는 셀이 있거나 행 구조가 일정하지 않습니다. html_table()의 fill=TRUE 매개변수는 오류를 발생시키는 대신 없는 값을 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')

빠른 확인

rvest를 사용한 HTML 표와 링크 스크래핑에 대한 이해도를 확인해 보세요.

복습: 표와 링크

핵심 요점: html_table()은 HTML 표를 데이터 프레임으로 자동 변환하며, 구조가 일정하지 않은 표에는 fill=TRUE를 사용합니다. 링크의 경우 html_elements('a')로 모든 앵커를 가져오고, html_text2()로 텍스트를, html_attr('href')로 URL을 가져옵니다. 상대 URL은 xml2::url_absolute()로 절대 URL로 변환하세요. 패턴을 사용하여 원치 않는 링크를 필터링하세요. 표의 텍스트와 포함된 링크 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 AI 튜터), CoddyKit PRO로 업그레이드하면 R Academy 강의 전체를 잠금 해제할 수 있습니다. R Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“테이블과 링크 스크래핑”에서 뭘 배우나요?

HTML 테이블을 데이터 프레임으로 구문 분석하고 페이지의 모든 하이퍼링크를 수집합니다. 브라우저에서 직접 실행하는 실습 코드로 R Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

R Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 R Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“테이블과 링크 스크래핑” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 R Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 R Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. HTML 구조와 CSS 선택자
  2. html_element()와 html_text() 기초
  3. 테이블과 링크 스크래핑
  4. 페이지 매김과 여러 페이지 처리
← R Academy(으)로 돌아가기