Obsługa paginacji i wielu stron
Przechodź przez stronicowane wyniki i łącz pobrane dane w jeden zbiór danych.
Obsługa paginacji i wielu stron to bezpłatna lekcja R Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej R Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs R Academy zawiera 4 lekcji w sumie.
Zrozumienie paginacji
Wiele stron internetowych dzieli zawartość na kilka stron. Paginacja oparta na adresie URL dodaje numer strony do adresu URL (np. ?page=2 lub /page/2/). Rozpoznaj ten wzorzec, aby programowo konstruować adresy URL.
library(rvest)
# Common URL pagination patterns:
# Pattern 1: query parameter
# https://site.com/products?page=1
# https://site.com/products?page=2
# Pattern 2: path segment
# https://site.com/products/page/1/
# https://site.com/products/page/2/
# Build URLs for pages 1 to 5
base_url <- 'https://books.toscrape.com/catalogue/page-'
page_urls <- paste0(base_url, 1:5, '.html')
page_urls
# [1] 'https://books.toscrape.com/catalogue/page-1.html'
# [2] 'https://books.toscrape.com/catalogue/page-2.html' ...Budowanie wzorców adresów URL za pomocą sprintf
Zarówno sprintf(), jak i paste0() służą do budowania ciągów adresów URL, ale sprintf() zapewnia większą kontrolę nad dopełnianiem zerami i formatowaniem. Użyj tej funkcji, która lepiej pasuje do struktury adresów URL danej strony.
# Various URL building approaches
# paste0 for simple concatenation
pages <- 1:5
urls_v1 <- paste0('https://site.com/list?p=', pages)
urls_v1[1] # 'https://site.com/list?p=1'
# sprintf for formatted strings
urls_v2 <- sprintf('https://site.com/page/%02d/', pages)
urls_v2[1] # 'https://site.com/page/01/'
# With multiple parameters
urls_v3 <- sprintf('https://site.com/items?page=%d&size=20', pages)
urls_v3[3] # 'https://site.com/items?page=3&size=20'
# glue package alternative
# glue('https://site.com/page/{pages}')Pobieranie wielu stron za pomocą map()
purrr::map() stosuje funkcję scrapującą do wektora adresów URL i zwraca listę wyników. Połącz ją z dplyr::bind_rows(), aby scalić wyniki w jedną ramkę danych.
library(rvest)
library(purrr)
# Define a function to scrape one page
scrape_page <- function(url) {
# In real code: page <- read_html(url)
# Here we simulate with local HTML
page <- read_html(sprintf(
'<ul><li class="item">Item %d-A</li><li class="item">Item %d-B</li></ul>',
url, url
))
data.frame(
title = html_text2(html_elements(page, '.item')),
page = url
)
}
# Apply over pages 1 and 2 (simulated with numbers)
results <- map(1:2, scrape_page)
do.call(rbind, results)Uprzejmy scraping: Sys.sleep()
Wysyłanie szybkich, kolejnych żądań do serwera jest nieuprzejme i może wywołać ograniczenie częstotliwości żądań lub blokadę adresu IP. Dodaj Sys.sleep() między żądaniami, aby szanować serwer. Opóźnienie wynoszące 1–2 sekundy jest zazwyczaj wystarczające.
library(rvest)
# Polite scraping with delays between requests
scrape_with_delay <- function(urls, delay = 1.5) {
results <- vector('list', length(urls))
for (i in seq_along(urls)) {
cat(sprintf('Scraping page %d of %d\n', i, length(urls)))
# results[[i]] <- read_html(urls[[i]])
Sys.sleep(delay) # Wait before next request
}
results
}
# Also: randomize delay to appear more human-like
random_delay <- function(min = 1, max = 3) {
Sys.sleep(runif(1, min = min, max = max))
}
random_delay()
cat('Always be polite to servers you scrape')Ustawianie User-Agent
Przedstaw swój scraper w uprzejmy sposób, ustawiając opisowy nagłówek User-Agent. Serwery używają go do identyfikowania botów. Dobry User-Agent zawiera imię i nazwisko oraz dane kontaktowe, aby właściciele stron mogli się z Tobą skontaktować.
library(rvest)
# Default user agent reveals R/rvest
# Better: set a descriptive, honest UA
ua <- paste0(
'MyResearchBot/1.0 ',
'(Academic research; ',
'contact: researcher@university.edu)'
)
# With httr/httr2 for UA control:
# library(httr2)
# response <- request(url) |>
# req_headers('User-Agent' = ua) |>
# req_perform()
# html <- read_html(resp_body_string(response))
# Or use polite package for full compliance:
# library(polite)
# session <- bow('https://example.com', user_agent = ua)
cat('Honest UA: better for everyone')Przestrzeganie robots.txt
robots.txt informuje crawlery, które ścieżki są niedostępne. Pakiet robotstxt pozwala programowo sprawdzić, czy dany adres URL można pobrać, zanim rozpoczniesz scraping.
library(rvest)
# library(robotstxt) # uncomment to use
# Check if scraping is allowed:
# rtxt <- robotstxt(domain = 'books.toscrape.com')
# rtxt$check(paths = '/catalogue/', bot = '*')
# TRUE means allowed
# Robots.txt typically looks like:
# User-agent: *
# Disallow: /admin/
# Disallow: /private/
# Allow: /catalogue/
# Crawl-delay: 2
# The polite package combines UA + robots.txt + delays:
# library(polite)
# session <- bow('https://books.toscrape.com')
# page <- scrape(session)
cat('Always check robots.txt before large-scale scraping')Podążanie za odnośnikami paginacji
Zamiast zgadywać adresy URL, podążaj za rzeczywistym odnośnikiem „Dalej” na każdej stronie. html_attr(html_element(page, 'a.next'), 'href') dynamicznie wyszukuje odnośnik do następnej strony — także w przypadku niesekwencyjnych wzorców paginacji.
library(rvest)
# Pattern: follow 'next' links dynamically
scrape_all_pages <- function(start_url, max_pages = 10) {
all_data <- list()
url <- start_url
i <- 1
while (!is.null(url) && i <= max_pages) {
# page <- read_html(url)
# data <- extract_data(page)
# all_data[[i]] <- data
# next_link <- html_attr(html_element(page, 'li.next a'), 'href')
# url <- if (!is.na(next_link)) xml2::url_absolute(next_link, url)
# else NULL
cat(sprintf('Would scrape page %d: %s\n', i, url))
url <- NULL # Stop in this demo
i <- i + 1
}
do.call(rbind, all_data)
}
scrape_all_pages('https://books.toscrape.com')session_follow_link() z rvest
Funkcja session() z rvest tworzy stanową sesję przeglądania, która zachowuje pliki cookie i historię. session_follow_link() przechodzi do odnośnika — jest to przydatne w przypadku stron wymagających logowania lub zachowania stanu między stronami.
library(rvest)
# Stateful session with rvest
# s <- session('https://example.com/login')
# s <- session_submit(s,
# html_form(read_html(s))[[1]],
# list(username='me', password='pw')
# )
# After login, navigate:
# page2 <- session_follow_link(s, 'Products')
# page3 <- session_back(page2) # go back
# session_history(page2) # show history
# For simple cases, follow href directly:
# href <- html_attr(html_element(page, 'a.next'), 'href')
# next_page <- session_jump_to(s, href)
cat('session() maintains cookies across requests')Wykrywanie ostatniej strony
Wiedz, kiedy zakończyć działanie: sprawdź, czy istnieje przycisk „Dalej”, czy liczba elementów na bieżącej stronie jest mniejsza od oczekiwanej albo czy numer strony przekracza znaną łączną liczbę stron. Obsługuj sytuacje brzegowe w kontrolowany sposób.
library(rvest)
# Strategy 1: Check if 'Next' link exists
has_next <- function(page) {
next_link <- html_element(page, 'li.next a')
!is.na(html_attr(next_link, 'href'))
}
# Strategy 2: Compare item count to expected page size
page_size <- 20
check_done <- function(items_on_page) {
items_on_page < page_size
}
# Strategy 3: Read total from pagination text
# e.g., 'Page 1 of 50' -> extract 50
extract_total_pages <- function(page) {
text <- html_text2(html_element(page, '.current'))
as.integer(gsub('.*of (\\d+).*', '\\1', text))
}
cat('Always plan your stopping condition')Obsługa błędów scrapingu
Błędy sieci, przekroczenia limitu czasu i błędy 404 będą się zdarzać. Umieść żądania w tryCatch(), aby poprawnie obsługiwać awarie, i rejestruj strony, dla których wystąpił błąd, żeby móc spróbować ponownie później.
library(rvest)
safe_scrape <- function(url) {
tryCatch({
# page <- read_html(url)
# data <- extract_data(page)
# return(data)
cat(sprintf('Scraping: %s\n', url))
data.frame(url = url, status = 'ok')
}, error = function(e) {
cat(sprintf('FAILED: %s -> %s\n', url, e$message))
data.frame(url = url, status = 'error')
})
}
urls <- c('https://example.com/page/1',
'https://example.com/page/2')
results <- lapply(urls, safe_scrape)
do.call(rbind, results)Buforowanie pobranych stron
Zapisuj pobrany kod HTML na dysku przed parsowaniem. Dzięki temu, jeśli parsowanie się nie powiedzie, nie musisz pobierać danych ponownie. Kolejne odczyty odbywają się z dysku, a nie z sieci — jest to uprzejme wobec serwera i przyspiesza pracę podczas tworzenia aplikacji.
library(rvest)
scrape_cached <- function(url, cache_dir = 'cache') {
dir.create(cache_dir, showWarnings = FALSE)
# Create a filename from URL hash
fname <- file.path(cache_dir,
paste0(digest::digest(url), '.html'))
if (file.exists(fname)) {
cat('Loading from cache\n')
return(read_html(fname))
}
cat('Downloading...\n')
# page <- read_html(url)
# xml2::write_html(page, fname)
# return(page)
cat('Cached to:', fname, '\n')
}
# Without digest: use URLencode or gsub
url <- 'https://example.com/page/1'
fname <- gsub('[^a-z0-9]', '_', tolower(url))
cat(fname)Szybki test
Sprawdź, czy rozumiesz zasady uprzejmego i niezawodnego scrapingu obejmującego wiele stron.
Podsumowanie: paginacja i uprzejmy scraping
Najważniejsze informacje: Buduj adresy URL stron za pomocą paste0() lub sprintf(). Używaj purrr::map(), aby stosować scraping do wielu adresów URL. Zawsze dodawaj Sys.sleep() między żądaniami. Sprawdzaj plik robots.txt za pomocą pakietu robotstxt. Dynamicznie podążaj za odnośnikami „Dalej” za pomocą html_attr() lub session_follow_link(). Wykrywaj ostatnią stronę, sprawdzając brak odnośnika „Dalej”. Umieszczaj żądania w tryCatch(), aby zwiększyć odporność na błędy. Podczas tworzenia aplikacji buforuj kod HTML na dysku.
# Multi-page scraping template:
# urls <- paste0(base, 1:n_pages)
# results <- purrr::map(urls, function(url) {
# Sys.sleep(runif(1, 1, 2)) # polite delay
# page <- read_html(url)
# extract_data(page) # your parser
# })
# df <- dplyr::bind_rows(results)
# Key principles:
# 1. Respect robots.txt
# 2. Add delays (Sys.sleep)
# 3. Set honest User-Agent
# 4. Cache HTML during development
# 5. Handle errors with tryCatch
cat('Polite scraping = sustainable scraping')Ucz się R dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 43
- Lekcje
- 159
Często zadawane pytania
Czy lekcja „Obsługa paginacji i wielu stron” jest bezpłatna?
Tak — pełny tekst „Obsługa paginacji i wielu stron” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu R Academy, przejdź na CoddyKit PRO. Kurs R Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Obsługa paginacji i wielu stron”?
Przechodź przez stronicowane wyniki i łącz pobrane dane w jeden zbiór danych. Ćwiczysz R Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć R Academy?
Nie wymagamy żadnego doświadczenia. R Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Obsługa paginacji i wielu stron”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji R Academy?
Tak. Każda lekcja R Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Struktura HTML i selektory CSS
- Podstawy html_element() i html_text()
- Scraping tabel i linków
- Obsługa paginacji i wielu stron