```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
if (!require('tidyverse')) install.packages("tidyverse") # wrangling
if (!require('RSelenium')) install.packages("RSelenium") # we know it, we love it
if (!require('wdman')) install.packages("wdman") # selenium server config
if (!require('rvest')) install.packages("rvest") # retrieve HTML objects 
if (!require('httr2')) install.packages("httr2") # start a browser session
if (!require('httpcache')) install.packages("httpcache") # clears cache
if (!require('openxlsx')) install.packages("openxlsx") # excel creation and manipulation 
if (!require('usethis')) install.packages("usethis") # open environment files (for secret API keys)
#edit_r_environ()
```


# Dynamische Webseiten

Automatisierung funktioniert gut mit *rvest*, solange die Webseiten, die wir scrapen möchten, statisch sind. Was bedeutet das? Letzte Woche konnten wir auf den Inhalt von Webseiten zugreifen, ohne sie tatsächlich zu öffnen. Wir konnten so alle Links identifizieren, die einem bestimmten Muster folgten (in der letzten Woche war das: <page=>).

## Das Europäische Parlament

Das ist nicht immer der Fall. Stellen wir uns vor, wir sind durch mit den Pressemeldungen der UN und möchten Daten vom Europäischen Parlament sammeln.

```{r}
browseURL("https://www.europarl.europa.eu/news/de")
```

Was klar wird, ist, dass es keinen Punkt gibt, der die Anzahl der Seiten enthält, sondern einfach einen <Mehr laden>-Button Zudem ändert sich der Link nicht, wenn wir auf den Button klicken. Wenn wir *rvest* verwenden würden, könnten wir nie alle Links bekommen, sondern nur die ersten paar.

Daher müssen wir einer anderen Strategie folgen. Wir müssen tatsächlich einen Browser öffnen und auf den "Mehr laden"-Button klicken. Aber da wir das nicht alles von Hand machen möchten, benötigen wir das Entwickler-Tool namens *RSelenium*.

### 1. Die Konfiguration des Browsers

*RSelenium* wurde entworfen, um Webseiten zu testen. Wir verwenden es für einen leicht anderen Zweck. Um es zu verwenden, müssen wir über eine Java-Installation verfügen.
Lasst uns zunächst einen neuen Browser erstellen (er sollte sich automatisch öffnen).

```{r}
# Setup (Konfigurationseinstellungen)
rd <- rsDriver(browser = "firefox",
               chromever = NULL, 
               port = sample(1:65535, 1), # eine Portnummer kann nur einmal verwendet werden, daher sollten wir immer eine zufällige Nummer wählen, um Fehler zu vermeiden
               verbose = FALSE)  

# Browser festlegen
browser <- rd$client
```


### 2. Navigation zur Ziel-URL

Der Browser hat sich geöffnet. 
Nun navigieren wir zur EuroParl-URL navigieren. Machen wir einen Screenshot davon, um uns zu vergewissern, dass alles wie gewünscht klappt.
 
```{r}
url <- "https://www.europarl.europa.eu/news/de"

# Zu einer URL navigieren
browser$navigate(url)

# Einen Screenshot machen
browser$screenshot(TRUE)
```


### 3. Klicken von Buttons

Nun poppt unter anderem ein Cookie-Fenster auf. 

Um mit dem Browser zu interagieren, müssen wir lernen, wie man auf Buttons klickt. Das ist nicht schwer, RSelenium hat die Funktion *clickElement()*. Aber zuerst müssen wir wissen, worauf wir klicken müssen. Dafür können wir wieder das Selector Gadget verwenden, um das interessierende Objekt zu identifizieren. Lasst uns die Cookies so ablehnen.

```{r}
cookies <- browser$findElement(using = 'css selector', value='.epjs_agree:nth-child(1) span') # Zustimmung/Ablehnung zu Cookies
cookies$clickElement() # und klick
```

So jetzt können wir tatsächlich tun, was wir geplant hatten. Klickt auf den <Mehr laden>-Button, um alle Links zu sammeln.

***Your Turn***
Versucht es einmal selbst (es folgt der gleichen Logik wie beim Cookies-Button oben).
```{r}


```









*Lösung*
```{r}
more <- browser$findElement(using = 'css selector', value="#continuesLoading_button .ep_name") 
more$clickElement()
```


### 4. Wiederholen eines Vorgangs

Das hat schon einmal funktioniert, aber wir müssen den Schritt natürlich mehrfach daswiederholen. Wie oft wir den Schritt wiederholen, hängt an uns.
```{r}
n_times <- 5
n <- 0
repeat {
  more$clickElement()
  n <- n+1
  Sys.sleep(1) # Delay um eine Sekunde, um das vollständige Laden der Seite zu ermöglichen (der Button muss wieder unten aufpoppen)
  if(n >= n_times){
    break
  }
}
```


### 5. Extraktion von Informationen

Wenn wir genug auf <Mehr laden> geklickt haben, beginnen wir, auf die Elemente auf der Seite zuzugreifen. Wir können *rvest* immer noch nicht verwenden, da wir direkt auf den HTML-Code im Browser, den wir in RSelenium() geöffnet haben, zugreifen müssen.
RSelenium hat aber ähnliche Funktionen wie rvest.

```{r}
urls_euparl <- browser$findElements(using = 'css selector', value='.ep_title > a') 
urls_euparl2 <- c()
for(i in 1:length(urls_euparl)){
      urls_euparl2[i] <- urls_euparl[[i]]$getElementAttribute('href')[[1]]
}
```

Jetzt, da wir diese Links haben, können wir tatsächlich zu *rvest* zurückkehren und auf weitere Daten (auf den Unterseiten für die einzelnen Pressemeldungen) zugreifen, ohne eine virtuelle Umgebung zu öffnen.

***Your Turn:*** 
Greift auf den Titel, Text und das Datum der Pressemitteilungen zu.

```{r}

```











***Lösung***
So kann es beispielsweise mit einer Funktion gehen. 
```{r}
start <- Sys.time()
scrape_euparl <- function(urls){
  results <- c()
  html <- read_html(urls)   

  date <- html %>% html_elements("time") %>% html_attr("datetime") %>% str_extract("\\d{4}-\\d{2}-\\d{2}")
  headline <- html %>% html_elements("h1") %>% html_text()
  text <- html %>% html_elements("p") %>% html_text() %>% paste0(collapse=" ")
  
  contents <- cbind(date, headline, text)
  results <- rbind(results, contents)
}

results_euparl <- sapply(urls_euparl2, scrape_euparl)
end <- Sys.time()
end-start

df_euparl <- do.call(rbind, results_euparl) %>% data.frame()
```

...und so mit einem for-Loop()

```{r}
start <- Sys.time()

df_euparl <- data.frame(date=NA, headline=NA, text=NA)
for(i in 1:5){
  html <- read_html(urls_euparl2[i])

  date <- html %>% html_elements("time") %>% html_attr("datetime") %>% str_extract("\\d{4}-\\d{2}-\\d{2}")
  headline <- html %>% html_elements("h1") %>% html_text()
  text <- html %>% html_elements("p") %>% html_text() %>% paste0(collapse=" ")
  
  contents <- cbind(date, headline, text)
  df_euparl <- rbind(df_euparl, contents)
}

end <- Sys.time()
end-start
```


Auf einigen Seiten ist es nicht möglich, einfach auf *rvest* umzusteigen. Auf diesen Seiten müssen wir alle Daten über RSelenium scrapen. 
So würde das beispielsweise für die ersten fünf Seiten in unserer Anwendung ausschauen.

```{r}
for(i in 1:5){
  browser$navigate(urls_euparl2[i])
  date <- browser$findElements("css selector", value="time") 
  date <- date[[1]]$getElementText() %>% as.character()
  headline <- browser$findElements("css selector", value="h1") 
  headline <- headline[[1]]$getElementText() %>% as.character()
  text <- browser$findElements("css selector", value="p")
  text <- text[[1]]$getElementText() %>% as.character()
  
  contents <- cbind(date, headline, text)
  df_euparl <- rbind(df_euparl, contents)
}
```


#### 6. Noch eine hilfreiche Anwendung

Wir können mit RSelenium nicht nur auf Objekte klicken, sondern auch Formulare ausfüllen, bspw., etwas auf Webseiten zu suchen.

```{r}
browser$navigate(url)
search <- browser$findElement(using = 'css selector', value="#search-field")
search$clearElement
search$sendKeysToElement(list("economy",key="enter"))
```



#### Alternativer Browser

Leider ist das RSelenium-Package oftmals veraltet. So sehr, dass ihr euch überlegen solltet, auf Python umzusteigen, falls ihr öfters dynamische Webseiten scraped. 
Momentan funktioniert RSelenium in R (soweit mir bekannt) nur stabil mit Firefox und phantomjs - einem unsichtbaren Browser. 

Hier ist die Konfiguration von phantomjs, falls ihr kein Firefox habt.
```{r}
port <- sample(1:65000, 1)
port_pjs <- phantomjs(port = port)
browser_pjs <- remoteDriver(browserName = "phantomjs", port = port)
browser_pjs$open()
browser_pjs$navigate(urls_euparl2[[1]])

browser_pjs$screenshot(TRUE)
```