Scraping with rvest and RSelenium

Filip Rodik; Ana Janković

2018-04-04

Scraping with rvest and RSelenium

Filip Rodik, Ana Janković

HUB385, 2018-04-04

Teme

Scraping (sveden na 3 bulleta)

  1. Navigiraj na stranicu (učitaj HTML)
  2. Parsiraj podatke
  3. Počisti pročitane podatke

U slučaju da postoji paging

  1. Inicijalizacija
  2. Iteriraj po stranicama
    • navigiraj
    • parsiraj
    • počisti
    • dodaj u glavnu kolekciju

Scraping - Korisni alati

rvest

Primjeri:

  1. Izravno čitanje HTML table elementa
    • html_table()
  2. Parsiranje HTML kompleksne strukture + Paging
    • hijerarhija elemenata
    • atributi
    • “dinamički” URL
library(rvest)
# data cleaning
library(magrittr)
library(plyr)
library(dplyr)

rvest - navigacija

Čitanje HTML-a

# definiraj url
url <- "http://www.index.hr/arhiva/vijesti/2018/1/1"
# procitaj stranicu
arhiva_html <- read_html(url)
# print class
class(arhiva_html)
## [1] "xml_document" "xml_node"

rvest - navigacija paging

index.hr/arhiva/vijesti/2018/1/1

# definiraj staticni dio URL-a
url_root <- "http://www.index.hr/arhiva/vijesti/"
# definiraj pocetni datum
datum <- as.Date("2018-01-01")
# format(datum, "%Y/%m/%d")
datum_string <- paste(
    format(datum,"%Y"),
    as.numeric(format(datum, "%m")),
    as.numeric(format(datum, "%d")),
    sep = "/"
)
# napravi puni URL
url <- paste0(url_root, datum_string) 
url # print
## [1] "http://www.index.hr/arhiva/vijesti/2018/1/1"

rvest - simple

html_table() funkcija

di_url <- "http://registar-imovina.gov.hr/default.aspx?action=nekretnine&page=1&posiljatelj=&vrsta_nek=6&vrsta_vla=&pbr=&zup="

parsiraj.stranicu <- function(url){
    # pokupi html
    stranica <- read_html(url, encoding = "UTF-8")
    # dohvati tablicu
    rows <- stranica %>%
        html_node(".tblView") %>% 
        html_table()
    # pretvori sve kolone u string
    rows <- rows %>%
        mutate_all(as.character)
    # vrati tablicu kao data.frame
    rows
}

rvest - parsiranje 1

<a href="/vijesti/clanak/detalji-tragedije-u-rijeci-kad-je-prvi-poceo-zapomagati-mislio-sam-da-se-sali/1016862.aspx" class="arhivaBox" title="Detalji tragedije u Rijeci: &quot;Kad je prvi počeo zapomagati, mislio sam da se šali&quot;">
   <p class="naslov">Detalji tragedije u Rijeci: &quot;Kad je prvi počeo zapomagati, mislio sam da se šali&quot;</p>
   <p class="podnaslov">1.1.2018. 21:59:10 / Vijesti</p>
   <p>NA tradicionalnom novogodišnjem kupanju na riječkim Pećinama dogodila strašna tragedija, a svjedoci su ispričali kako je to izgledalo.</p>
</a>

<a href="/vijesti/clanak/pogledajte-novogodisnje-poruke-znanstvenika-index-laba/1016801.aspx" class="arhivaBox" title="Pogledajte novogodišnje poruke znanstvenika Index laba">
   <p class="naslov">Pogledajte novogodišnje poruke znanstvenika Index laba</p>
   <p class="podnaslov">1.1.2018. 21:55:19 / Vijesti</p>
   <p>VRHUNSKI hrvatski znanstvenici koji pišu za Index lab čitateljima su uputili svoje prigodne poruke.</p>
</a>

rvest - parsiranje 2

# procitaj stranicu
arhiva_html <- read_html(url)
# procitaj trenutnu stranicu kao data.frame
trenutne_vijesti <- arhiva_html %>%
    html_nodes(".arhivaBox") %>% # trazi class
    ldply(obradi.node) # parsiraj svaki node funkcijom
url naslov podnaslov opis
/vijesti/clanak/detalji-tragedije-u-rijeci-kad-je-prvi-poceo-zapomagati-mislio-sam-da-se-sali/1016862.aspx Detalji tragedije u Rijeci: “Kad je prvi počeo zapomagati, mislio sam da se šali” 1.1.2018. 21:59:10 / Vijesti NA tradicionalnom novogodišnjem kupanju na riječkim Pećinama dogodila strašna tragedija, a svjedoci su ispričali kako je to izgledalo.
/vijesti/clanak/pogledajte-novogodisnje-poruke-znanstvenika-index-laba/1016801.aspx Pogledajte novogodišnje poruke znanstvenika Index laba 1.1.2018. 21:55:19 / Vijesti VRHUNSKI hrvatski znanstvenici koji pišu za Index lab čitateljima su uputili svoje prigodne poruke.

rvest - parsiranje 3

obradi.node <- function(node){
    data.frame(
        url = node %>% 
                html_attr("href") 
        naslov = node %>% 
                    html_node(".naslov") %>% 
                    html_text()
        podnaslov = node %>% 
                        html_node(".podnaslov") %>% 
                        html_text()
        opis = node %>% 
                html_children() %>% 
                extract(3) %>% 
                html_text() 
    )
}

rvest - čišćenje

trenutne_vijesti <- trenutne_vijesti %>% # razbij podnaslov na dvije kolone
    mutate(
        vrijeme = gsub("/.*", "", podnaslov) %>% # uzmi sve prije '/'
                    trimws() %>% # trim whitespace
                    strptime("%d.%m.%Y. %H:%M:%S") %>% # pretvori u datetime
                    as.POSIXct(), # cast as.POSIXct
        kategorija = gsub(".*/", "", podnaslov) %>% # uzmi sve nakon '/'
                        trimws() # trim whitespace
    ) %>% 
    select(-podnaslov) # makni staru kolonu
url naslov opis vrijeme kategorija
/vijesti/clanak/detalji-tragedije-u-rijeci-kad-je-prvi-poceo-zapomagati-mislio-sam-da-se-sali/1016862.aspx Detalji tragedije u Rijeci: “Kad je prvi počeo zapomagati, mislio sam da se šali” NA tradicionalnom novogodišnjem kupanju na riječkim Pećinama dogodila strašna tragedija, a svjedoci su ispričali kako je to izgledalo. 2018-01-01 21:59:10 Vijesti
/vijesti/clanak/pogledajte-novogodisnje-poruke-znanstvenika-index-laba/1016801.aspx Pogledajte novogodišnje poruke znanstvenika Index laba VRHUNSKI hrvatski znanstvenici koji pišu za Index lab čitateljima su uputili svoje prigodne poruke. 2018-01-01 21:55:19 Vijesti

RSelenium

RSelenium - instalacija

Selenium Standalone Server

Browser drivers

Više detalja na seleniumhq.org

RSelenium - pokretanje

cmd

>java -jar selenium-server-standalone-x.xx.x.jar [-port xxxx]

Default port = 4444

library(RSelenium)
# ! start Selenium server first !
# connect to browser
remDr <- remoteDriver(browser = "chrome", port=4444)
# open browser
remDr$open()
# starting url
home_url <- "http://edoc.sabor.hr/Fonogrami.aspx"
# navigate page
remDr$navigate(home_url)

RSelenium - parsiranje

# get element by class
remDr$findElements(using = "class", value = "dxgvDataRow_SaborPurpleTheme")
# get element by css
remDr$findElement(using = 'css', value = '.dxp-current')

# read attribute value 
webElem$getElementAttribute(attrName = "href") 
# read multiple text values # tds = list of webElements
sapply(unlist(tds), function(x) x$getElementText()) 

RSelenium - send keys and clicks

# click Next page # btnNext = webEelement
btnNext$clickElement()
# wait for reload (!)
Sys.sleep(4)

# send keystrokes
remDr$navigate("http://www.google.com/ncr")
webElem <- remDr$findElement(using = "css", "[name = 'q']")
webElem$sendKeysToElement(list("R Cran", key = "enter"))

RSelenium - iframe 1

remDr <- remoteDriver(browser = "chrome", port=4567)
# open browser
remDr$open()
url<-"https://eojn.nn.hr/Oglasnik/"

input_br<-"f3"
input_od<-"1.1.2017"
input_do<-"31.3.2017"
input_vrsta<-c("Izvođenje radova", "Pružanje usluga", "Isporuka roba")

# hederi # imao sam ih pri ruci
remDr$setTimeout(type = "implicit", milliseconds = 5000)
remDr$setTimeout(type = "page load", milliseconds = 5000)

remDr$navigate(url)
webElem<-remDr$findElements(using = "css selector", value="#TrazilicaCtl1_uiJednostavnaTrazilica")
webElement<-webElem[[1]]

R Selenium - iframe 2

Kada su web elementi do kojih želimo doći postavljeni unutar iframe-a, ukratko - potrebno je “ući u iframe” pa tek onda napraviti ono što se želi.

#ovdje dohvatamo neki odgovarajući web element
webElem<-remDr$findElements(using = "css selector", value="#TrazilicaCtl1_uiJednostavnaTrazilica")
#rezultirajući objekt je bio lista, u kojoj je webelement samo 
## prvi element liste (otuda i ovaj odabir samo prvog elementa)
webElement<-webElem[[1]] 
webElement$clickElement()
# ovim prethodnim smo došli na stranicu koja se otvorila i gdje je cijeli dio, 
## u biti "obrazac"+"tablica" unutar iframe-a.

# biramo web element koji je iframe
webElem<-remDr$findElements("css", "iframe")
# naredbom switchtoiframe mu kažemo da na toj stranici koju 
## smo otvorili prebaci se unutar iframe-a
remDr$switchToFrame(webElem[[1]]) 

R Selenium - iframe 3

Kada smo unutar iframe-a onda možemo unositi što nam treba u iframe tj. popunjavati parametre koji nam trebaju da dobijemo tržilicom ono što nas interesira; odnosno sada sve naredbe što šaljemo, i elementi koje biramo su unutar ovog iframe-a.

#Primjer:
#prethodno su sačuvani određeni parametri koji nas interesiraju:

input_br<-"f3"
input_od<-"1.1.2017"
input_do<-"31.3.2017"
input_vrsta<-c("Izvođenje radova", "Pružanje usluga", "Isporuka roba")

# ovim želim npr. unijeti da br. dokumenta mora sadržati f3 (u mom slučaju su to bile one javne nabave 
## kod kojih je postupak uspješno okončan i odabran je pružatelj usluge i/ili izvođač radova); 

# datum od i datum do te vrsta ugovora. Ovo inače nije potrebno ali radi specifičnosti kako 
## je posložena stranica oglasnika javnih nabava ovo je korišteno kao filter kako bi mogli dohvatiti sve dokumente.

RSelenium - sending keys, clicks, doubleclicking itd. u iframe

# dohvat određenih polja u koja se želi staviti vrijednost po kojoj će se filtrirati tablica koja se treba dobiti
broj_objave<-remDr$findElements(using = "css selector", value = "#uiFilter_Txt_OznakaDokumenta") 
broj_objave<-broj_objave[[1]]
broj_objave$sendKeysToElement(list(input_br))
# dohvat određenih polja u koja se želi staviti vrijednost po kojoj će se filtrirati tablica koja se treba dobiti
vrsta_ugovora<-remDr$findElements(using = "css selector", value = "#uiFilter_Txt_TipNabave")
vrsta_ugovora<-vrsta_ugovora[[1]]
# ovdje se salje vrsta ugovora tj. da mora sadržati input "izvođenje radova"
vrsta_ugovora$sendKeysToElement(list(input_vrsta[1])) 

Ovo je u konkretnom slučaju bilo nužno da bi se “filtrirala” tablica (pojašnjenje vezano za stranicu EOJN)

RSelenium - sending keys, clicks, doubleclicking itd. u iframe (nastavak)

I sad dalje isto se ide odabirom datuma, itd.

datum_objave_od<-remDr$findElements(using = "css selector", value="#uiFilter_Calendar_DatumObjave_textBox")
datum_objave_od<-datum_objave_od[[1]]
datum_objave_od$sendKeysToElement(list(input_od))
strelica<-remDr$findElements(using = "css selector", value = "#uiFilter_Toggle_DatumObjave_EndValue")
strelica<-strelica[[1]]
strelica$clickElement()
datum_objave_do<-remDr$findElements(using = "css selector", value="#uiFilter_Calendar_DatumObjave_EndValue_textBox")
datum_objave_do<-datum_objave_do[[1]]
datum_objave_do$sendKeysToElement(list(input_do))
Sys.sleep(3)

RSelenium - sending keys, clicks, doubleclicking itd. u iframe (nastavak)

I na kraju tražimo prema zadanim parametrima:

trazi<-remDr$findElements(using = "css selector", value=".PreglediTraziButton")
trazi<-trazi[[1]]
trazi$clickElement()

RSelenium - sending keys, clicks, doubleclicking itd. u iframe (nastavak)

#kad sam došla do tablice malo teže se išlo pa sam morala ići na css selector
tablica<-remDr$findElements(using="css selector", value = ".font-bold-grey")
tablica<-tablica[[1]]
detalji1<-detalji$findElements(using = "css selector", value = ".DetailsBtn")
detalji1<-detalji1[[1]]
detalji1$doubleclick()
dokument<-remDr$findElements(using = "css selector", value = "#uiDokumentPodaci_uiDocumentCtl_uiOpenDocumentHtml")
dokument<-dokument[[1]]
dokument$clickElement()

povratak<-remDr$findElements(using = "css selector", value="#uiDokumentPodaci_uiOdustani")
povratak<-povratak[[1]]
povratak$clickElement()

Plan:

Za olakšati si kasnije namjera mi je složiti to u funkciju……to be continued….