R Language
Web schrapen en parseren
Zoeken…
Opmerkingen
Schrapen verwijst naar het gebruik van een computer om de code van een webpagina op te halen. Zodra de code is verkregen, moet deze in een nuttige vorm worden ontleed voor verder gebruik in R.
Base R heeft niet veel van de tools die nodig zijn voor deze processen, dus schrapen en parseren gebeurt meestal met pakketten. Sommige pakketten zijn het meest nuttig voor schrapen ( RSelenium
, httr
, curl
, RCurl
), sommige voor parseren ( XML
, xml2
), en sommige voor beide ( rvest
).
Een verwant proces is het schrapen van een web-API, die in tegenstelling tot een webpagina gegevens retourneert die bedoeld zijn als machinaal leesbaar. Veel van dezelfde pakketten worden voor beide gebruikt.
Wettigheid
Sommige websites hebben er bezwaar tegen dat ze worden geschraapt, hetzij vanwege toegenomen serverbelasting of bezorgdheid over het eigendom van gegevens. Als een website het schrapen ervan verbiedt, is het illegaal om te schrapen.
Basic schrapen met rvest
rvest
is een pakket voor rvest
en parsing door Hadley Wickham geïnspireerd door Python's Beautiful Soup . Het maakt gebruik van de libxml2
bindingen van Hadley's xml2
pakket voor HTML-parsing.
Als onderdeel van de tidyverse, rvest
wordt doorgesluisd . Het gebruikt
-
xml2::read_html
om de HTML van een webpagina te schrapen, - die vervolgens kan worden
html_node
met de functieshtml_node
enhtml_nodes
met behulp van CSS- of XPath-selectors, en - ontleed naar R-objecten met functies zoals
html_text
enhtml_table
.
Om de tabel met mijlpalen van de Wikipedia-pagina op R te schrapen, ziet de code eruit
library(rvest)
url <- 'https://en.wikipedia.org/wiki/R_(programming_language)'
# scrape HTML from website
url %>% read_html() %>%
# select HTML tag with class="wikitable"
html_node(css = '.wikitable') %>%
# parse table into data.frame
html_table() %>%
# trim for printing
dplyr::mutate(Description = substr(Description, 1, 70))
## Release Date Description
## 1 0.16 This is the last alpha version developed primarily by Ihaka
## 2 0.49 1997-04-23 This is the oldest source release which is currently availab
## 3 0.60 1997-12-05 R becomes an official part of the GNU Project. The code is h
## 4 0.65.1 1999-10-07 First versions of update.packages and install.packages funct
## 5 1.0 2000-02-29 Considered by its developers stable enough for production us
## 6 1.4 2001-12-19 S4 methods are introduced and the first version for Mac OS X
## 7 2.0 2004-10-04 Introduced lazy loading, which enables fast loading of data
## 8 2.1 2005-04-18 Support for UTF-8 encoding, and the beginnings of internatio
## 9 2.11 2010-04-22 Support for Windows 64 bit systems.
## 10 2.13 2011-04-14 Adding a new compiler function that allows speeding up funct
## 11 2.14 2011-10-31 Added mandatory namespaces for packages. Added a new paralle
## 12 2.15 2012-03-30 New load balancing functions. Improved serialization speed f
## 13 3.0 2013-04-03 Support for numeric index values 231 and larger on 64 bit sy
Hoewel dit een data.frame retourneert, moet u er rekening mee houden dat, zoals typisch is voor geschraapte gegevens, er nog meer gegevens moeten worden opgeschoond: hier, datums opmaken, NA
's invoegen, enzovoort.
Merk op dat gegevens in een minder consistent rechthoekig formaat looping of andere verdere munging nodig hebben om succesvol te parseren. Als de website gebruik maakt van jQuery of andere middelen om inhoud in te voegen, is read_html
mogelijk onvoldoende om te schrapen en kan een robuustere schraper zoals RSelenium
nodig zijn.
Rvest gebruiken wanneer inloggen vereist is
Ik heb vaak problemen met het verwijderen van een web, namelijk het invoeren van een gebruikersnaam en wachtwoord om in te loggen op een website.
In dit voorbeeld dat ik heb gemaakt om mijn geposte antwoorden te volgen om de overloop te stapelen. De algemene stroom is om in te loggen, naar een webpagina te gaan, informatie te verzamelen, een dataframe toe te voegen en vervolgens naar de volgende pagina te gaan.
library(rvest)
#Address of the login webpage
login<-"https://stackoverflow.com/users/login?ssrc=head&returnurl=http%3a%2f%2fstackoverflow.com%2f"
#create a web session with the desired login address
pgsession<-html_session(login)
pgform<-html_form(pgsession)[[2]] #in this case the submit is the 2nd form
filled_form<-set_values(pgform, email="*****", password="*****")
submit_form(pgsession, filled_form)
#pre allocate the final results dataframe.
results<-data.frame()
#loop through all of the pages with the desired info
for (i in 1:5)
{
#base address of the pages to extract information from
url<-"http://stackoverflow.com/users/**********?tab=answers&sort=activity&page="
url<-paste0(url, i)
page<-jump_to(pgsession, url)
#collect info on the question votes and question title
summary<-html_nodes(page, "div .answer-summary")
question<-matrix(html_text(html_nodes(summary, "div"), trim=TRUE), ncol=2, byrow = TRUE)
#find date answered, hyperlink and whether it was accepted
dateans<-html_node(summary, "span") %>% html_attr("title")
hyperlink<-html_node(summary, "div a") %>% html_attr("href")
accepted<-html_node(summary, "div") %>% html_attr("class")
#create temp results then bind to final results
rtemp<-cbind(question, dateans, accepted, hyperlink)
results<-rbind(results, rtemp)
}
#Dataframe Clean-up
names(results)<-c("Votes", "Answer", "Date", "Accepted", "HyperLink")
results$Votes<-as.integer(as.character(results$Votes))
results$Accepted<-ifelse(results$Accepted=="answer-votes default", 0, 1)
De lus is in dit geval beperkt tot slechts 5 pagina's, deze moet worden aangepast aan uw toepassing. Ik heb de gebruikersspecifieke waarden vervangen door ******, hopelijk biedt dit enige richtlijnen voor je probleem.