class: inverse, middle, center background-image: url("data:image/png;base64,#Imagenes/MochoBlanco.jpg") background-size: cover .right[ <img src="data:image/png;base64,#Imagenes/logor.png" width="30%" style="display: block; margin: auto 0 auto auto;" /> ] ## Taller - Introducción al Webscraping con R ### Primeros pasos utilizando R **Víctor Caquilpan** victor.caquilpan@gmail.com ✉️ 08 de Noviembre de 2021 <style> body { text-align: justify} </style> --- ## Contenido * Introducción al Webscraping * Aspectos generales de las páginas Web * Raspado de datos en páginas estáticas * Raspado de datos en páginas dinámicas -- ## ¿ Qué se requiere? * Conocimiento básico de R y RStudio * Instalación de última versión de [Google Chrome](https://www.google.com/intl/es/chrome/) * En [este repositorio Github](https://github.com/victorcaquilpan/TallerWebScrapingUAI) se encuentra el material de la clase --- class: inverse, center, middle background-image: url("data:image/png;base64,#Imagenes/MochoBlanco.jpg") background-size: cover ## Introducción al Webscraping --- ## ¿Cómo podemos obtener datos de la Web? Existe una gran cantidad de recursos para obtener datos de la Web, los cuales tienen distintos propósitos como también dificultades asociadas a su uso. A modo general, podemos mencionar: * Descarga directa de archivos * Uso de servicios API * Webscraping (uso de **rvest** y **RSelenium**) -- .pull-left[ <img src="data:image/png;base64,#Imagenes/rvest.png" width="150px" style="display: block; margin: auto;" /> ] .pull-right[ <img src="data:image/png;base64,#Imagenes/Selenium.png" width="150px" style="display: block; margin: auto;" /> ] --- ## ¿Para qué el Webscraping? Webscraping o "raspado web" es un conjunto de técnicas que permiten la extracción de información disponible en sitios Web. De esta forma, nosotros podemos: * Obtener información que no la podemos obtener de otra forma (base de datos, planillas MS Excel) * Automatizar procesos que típicamente los puede realizar un usuario humano * Obtener contenido específico y disponerlo en un formato estructurado <img src="data:image/png;base64,#Imagenes/ScrapingIntro2.jpg" width="480px" style="display: block; margin: auto;" /> --- ## Algunas consideraciones El raspado Web puede ser ilegal o no ético. Depende qué, cómo y el por qué nosotros estamos realizando el proceso de obtención de información. * Por ejemplo, nosotros podríamos obtener información que es de carácter privado * También, si el proceso se realiza de manera invasiva podemos colapsar el servidor que levanta ciertas páginas Web * Si utilizamos información que tiene copyright sin respetar los respectivos derechos <img src="data:image/png;base64,#Imagenes/meme0.jpg" width="450px" style="display: block; margin: auto;" /> --- class: inverse, center, middle background-image: url("data:image/png;base64,#Imagenes/MochoBlanco.jpg") background-size: cover ## Aspectos generales de las páginas Web --- ## Antecedentes básicos de HTML Los sitios Web constan de varios elementos, algunos los cuales no son directamente visibles por los usuarios. * HTML es un lenguaje que describe el contenido y estructura de una página Web * HTML utiliza etiquetas (tags), existiendo una gran cantidad de [opciones](https://www.w3schools.com/TAGS/default.ASP) disponibles. Aquí podemos ver un [ejemplo básico](http://dataquestio.github.io/web-scraping-pages/simple.html) de una página Web. <img src="data:image/png;base64,#Imagenes/EstructuraHTML.jpg" width="80%" style="display: block; margin: auto;" /> --- ## Antecedentes básicos de HTML Una página Web es posible representarla a través de una estructura de árbol, en donde además es muy frecuente encontrar elementos anidados. .pull-left[ .center[**Código HTML**] ```r <html> <head> <title> Título </title> </head> <body> <h1> Es un título </h1> <p> Es un párrafo </p> <p> Otro párrafo </p> <div> <h2> Subtítulo </h2> </div> </body> </html> ``` ] .pull-right[ .center[**Estructura de árbol**] <br> <br> <img src="data:image/png;base64,#Imagenes/DiagramaArbolR.jpg" width="90%" style="display: block; margin: auto;" /> --- ] --- ## Elementos HTML Podemos ir probando cómo funcionan las distintas etiquetas HTML. .pull-left[ .center[**Código HTML**] ```r <html> <head> <title> Título </title> </head> <body> <h1> Es un título </h1> <p> Es un párrafo </p> <p> Otro párrafo </p> <h2> Título 2do nivel </h2> <div> <h2> Otro subtítulo </h2> <p> Otro párrafo más</p> </div> </body> </html> ``` ] .pull-right[ <html> <head> <title> Título </title> </head> <body> <h1> Es un título</h1> <p> Es un párrafo </p> <p> Otro párrafo </p> <h2> Título 2do nivel </h2> <div> <h2> Otro subtítulo </h2> <p> Otro párrafo más</p> </div> </body> </html> ] --- ## Elementos HTML Podemos ir probando cómo funcionan las distintas etiquetas HTML. ```r <h2> Este es un título.</h2> ``` <h2> Este es un título.</h2> -- ```r <p> Este es un párrafo.</p> ``` <p> Este es un párrafo.</p> -- ```r <ul> <li>materia</li> <li>artículos</li> <li>informes</li> </ul> ``` <ul> <li>materia</li> <li>artículos</li> <li>informes</li> </ul> --- ## Elementos HTML Podemos ver que algunos elementos pueden tener atributos. ```r <p id = "miparrafo">Este es un párrafo con un parámetro id.</p> ``` <p id = "miparrafo">Este es un párrafo con un parámetro id.</p> -- ```r <p class = "secundarios"> Este párrafo tiene una clase.</p> ``` <p class = "secundarios"> Este párrafo tiene una clase.</p> -- * Tanto **id** como **class** son atributos que permiten identificar elementos -- * Ambos pueden tomar un nombre arbitrario -- * Un mismo **class** puede asociarse a varios elementos, mientras que un **id** solo puede estar vinculado a un único elemento --- ## Elementos HTML Podemos ver que algunos elementos pueden tener atributos. ```r <p>En este <a href="https://www.bcn.cl/portal/">enlace </a> puedes acceder a la página de la BCN.</p> ``` <p>En este <a href="https://www.bcn.cl/portal/">enlace</a> puedes acceder a la página de la BCN.</p> -- ```r <p> Veamos el mismo <a title = "Redireccionar a una página" href="https://www.bcn.cl/portal/">enlace </a> con otro atributo. </p> ``` <p> Veamos el mismo <a title = "Redireccionar a una página" href="https://www.bcn.cl/portal/">enlace</a> con otro atributo. </p> -- ```r <p> Veamos el mismo <a class = "noticia" title = "Redireccionar a una página" href="https://www.bcn.cl/portal/">enlace </a> con tres atributos. </p> ``` <p> Veamos el mismo <a class = "noticia" title = "Redireccionar a una página" href="https://www.bcn.cl/portal/">enlace</a> con tres atributos. </p> --- ## Antecedentes básicos de CSS CSS es un lenguaje que provee información acerca del **estilo** de los objetos dentro de una página Web (color, posición, tamaño y fuente de letras, etc.). CSS funciona en conjunto con HTML y **puede estar dentro o fuera de él**. Para este último caso utilizaremos **reglas CSS**. .pull-left[ .center[**Código HTML**] ```r <html> <head> <title> Título </title> </head> <body> <h1> Es un título </h1> <p> Es un párrafo </p> <p> Otro párrafo </p> <h2> Título 2do nivel </h2> <div> <h2> Otro subtítulo </h2> <p> Otro párrafo más</p> </div> </body> </html> ``` ] .pull-right[ <html> <head> <title> Título </title> </head> <body> <h1 style = "color:black"> Es un título</h1> <p> Es un párrafo </p> <p> Otro párrafo </p> <h2> Título 2do nivel </h2> <div> <h2> Otro subtítulo </h2> <p> Otro párrafo más</p> </div> </body> </html> ] --- ## Antecedentes básicos de CSS CSS es un lenguaje que provee información acerca del **estilo** de los objetos dentro de una página web (color, posición, tamaño y fuente de letras, etc.). CSS funciona en conjunto con HTML y **puede estar dentro o fuera de él**. Para este último caso utilizaremos **reglas CSS**. .pull-left[ .center[**Código HTML + CSS**] ```r <html> <head> <title> Título </title> </head> <body> <h1 style = "color:blue"> Es un título</h1> <p style = "color:red"> Es un párrafo </p> <p style = "color:red"> Otro párrafo </p> <h2 style = "color:green"> Título 2do nivel </h2> <div> <h2 style = "color:green"> Otro subtítulo </h2> <p style = "color:orange"> Otro párrafo más</p> </div> </body> </html> ``` ] .pull-right[ <html> <head> <title> Título </title> </head> <body> <h1 style = "color:blue"> Es un título </h1> <p style = "color:red"> Es un párrafo </p> <p style = "color:red"> Otro párrafo </p> <h2 style = "color:green"> Título 2do nivel </h2> <div> <h2 style = "color:green"> Otro subtítulo </h2> <p style = "color:orange"> Otro párrafo más</p> </div> </body> </html> ] --- ## Regla CSS .pull-left[ La estructura de una regla CSS considera las siguientes partes: ] .pull-right[ ```r p {color: blue; font-family: Avenir} ``` ] --- ## Regla CSS .pull-left[ La estructura de una regla CSS considera las siguientes partes: * Selector CSS ] .pull-right[ ```r *p {color: blue; font-family: Avenir} ``` ] --- ## Regla CSS .pull-left[ La estructura de una regla CSS considera las siguientes partes: * Selector CSS * Propiedad ] .pull-right[ ```r p *{color: blue; * font-family: Avenir} ``` ] --- ## Regla CSS .pull-left[ La estructura de una regla CSS considera las siguientes partes: * Selector CSS * Propiedad * Valor ] .pull-right[ ```r p {color: * blue; font-family: * Avenir} ``` ] --- ## Regla CSS .pull-left[ La estructura de una regla CSS considera las siguientes partes: * Selector CSS * Propiedad * Valor Un *selector CSS* permite identificar elementos utilizando **etiquetas**, **clases**, **ids** y otros atributos. Hay varias formas de seleccionar un elemento: - Para seleccionar etiquetas, nombre de etiqueta ] .pull-right[ ```r p {color: blue; font-family: Avenir} ``` <br> <br> .center[**Ejemplo**] ```r *h1 {color: blue} .intro {color: red} .sub {color: green} #especial {color: orange} ``` ] --- ## Regla CSS .pull-left[ La estructura de una regla CSS considera las siguientes partes: * Selector CSS * Propiedad * Valor Un *selector CSS* permite identificar elementos utilizando **etiquetas**, **clases**, **ids** y otros atributos. Hay varias formas de seleccionar un elemento: - Para seleccionar etiquetas, nombre de etiqueta - Para clases, anteponer un punto ] .pull-right[ ```r p {color: blue; font-family: Avenir} ``` <br> <br> .center[**Ejemplo**] ```r h1 {color: blue} *.intro {color: red} *.sub {color: green} #especial {color: orange} ``` ] --- ## Regla CSS .pull-left[ La estructura de una regla CSS considera las siguientes partes: * Selector CSS * Propiedad * Valor Un *selector CSS* permite identificar elementos utilizando **etiquetas**, **clases**, **ids** y otros atributos. Hay varias formas de seleccionar un elemento: - Para seleccionar etiquetas, nombre de etiqueta - Para clases, anteponer un punto - Para ids, anteponer un # ] .pull-right[ ```r p {color: blue; font-family: Avenir} ``` <br> <br> .center[**Ejemplo**] ```r h1 {color: blue} .intro {color: red} .sub {color: green} *#especial {color: orange} ``` ] --- ## Regla CSS .pull-left[ La estructura de una regla CSS considera las siguientes partes: * Selector CSS * Propiedad * Valor Un *selector CSS* permite identificar elementos utilizando **etiquetas**, **clases**, **ids** y otros atributos. Hay varias formas de seleccionar un elemento: - Para seleccionar etiquetas, nombre de etiqueta - Para clases, anteponer un punto - Para ids, anteponer un # - Combinaciones y otras... ] .pull-right[ ```r p {color: blue; font-family: Avenir} ``` <br> <br> .center[**Ejemplo**] ```r h1 {color: blue} .intro {color: red} .sub {color: green} #especial {color: orange} ``` ] --- ## Antecedentes básicos de CSS CSS es un lenguaje que provee información acerca del **estilo** de los objetos dentro de una página web (color, posición, tamaño y fuente de letras, etc.). CSS funciona en conjunto con HTML y **puede estar dentro o fuera de él**. Para este último caso utilizaremos **reglas CSS**. .pull-left[ .center[**Código HTML**] ```r <html> <head> <title> Título </title> </head> <body> <h1> Es un título</h1> <p class = "intro"> Es un párrafo </p> <p class = "intro"> Otro párrafo </p> <h2 class = "sub"> Título 2do nivel </h2> <div> <h2 class = "sub"> Otro subtítulo </h2> <p id = "especial"> Otro párrafo más</p> </div> </body> </html> ``` ] .pull-right[ .center[**Código CSS**] ```r h1 {color: blue} .intro {color: red} .sub {color: green} #especial {color: orange} ``` ] --- ## Antecedentes básicos de CSS CSS es un lenguaje que provee información acerca del **estilo** de los objetos dentro de una página web (color, posición, tamaño y fuente de letras, etc.). CSS funciona en conjunto con HTML y **puede estar dentro o fuera de él**. Para este último caso utilizaremos **reglas CSS**. .pull-left[ .center[**Código HTML**] ```r <html> <head> <title> Título </title> </head> <body> <h1> Es un título</h1> <p class = "intro"> Es un párrafo </p> <p class = "intro"> Otro párrafo </p> <h2 class = "sub"> Título 2do nivel </h2> <div> <h2 class = "sub"> Otro subtítulo </h2> <p id = "especial"> Otro párrafo más</p> </div> </body> </html> ``` ] .pull-right[ <html> <head> <title> Título </title> </head> <body> <h1 style = "color:blue"> Es un título </h1> <p style = "color:red"> Es un párrafo </p> <p style = "color:red"> Otro párrafo </p> <h2 style = "color:green"> Título 2do nivel </h2> <div> <h2 style = "color:green"> Otro subtítulo </h2> <p style = "color:orange"> Otro párrafo más</p> </div> </body> </html> ] --- ## En simples palabras... Un [selector CSS](https://developer.mozilla.org/es/docs/Web/CSS/CSS_Selectors) permite localizar elementos dentro de un documento HTML. Además de ser útiles para definir el estilo de elementos, también son convenientes **para extraer información de ellos**. Hoy en día todos los navegadores permiten extraer la ubicación de un elemento a través de selectores CSS (en general con la tecla **F12**). Existen también aplicaciones que nos facilitan este trabajo tales como [SelectorGadget](https://selectorgadget.com/). <img src="data:image/png;base64,#Imagenes/SelectorGadget.jpg" width="40%" style="display: block; margin: auto;" /> .center[**¡Agreguemos la extensión!**] --- class: center, middle Para revisar lo visto hasta el momento, vayamos a una página de [Wikipedia](https://es.wikipedia.org/wiki/Wikipedia:Portada) y analicemos su estructura. ...en resumen, podemos identificar elementos usando la sintaxis de una regla CSS, lo se puede hacer a mano, y si alguien se anima puede tomar este [pequeño curso](https://flukeout.github.io/) para aprender a usar selectores CSS. --- class: inverse, center, middle background-image: url("data:image/png;base64,#Imagenes/MochoBlanco.jpg") background-size: cover ## Raspado a páginas estáticas --- ## Páginas estáticas Corresponden a sitios en los cuales siempre se obtiene la misma información independiente de la interacción del usuario. - La librería `rvest` permite la lectura de información de una manera sencilla - Es parte del universo `tidyverse`, por lo que puede combinarse con otras librerías tales como `dplyr` - Contiene una amplia documentación (ver referencias al final) --- ## Ejemplo en página de la Biblioteca del Congreso Nacional (BCN) Vamos a ver un caso en particular. La BCN dispone de una gran cantidad de información en línea que puede ser de interés para diferentes usuarios. Analicemos este [enlace](https://www.bcn.cl/siit/reportescomunales/comunas_v.html?anno=2021&idcom=11201). Para inspeccionar el contenido HTML es necesario hacer *click* derecho dentro de la página y seleccionar **Inspeccionar**. <img src="data:image/png;base64,#Imagenes/BCNAysen.jpg" width="100%" style="display: block; margin: auto;" /> --- ## Uso de `rvest` La principal función es `read_html()`, la cual permite leer una página, devolviendo un objeto XML (código fuente). -- ```r # Cargamos libreria rvest library(rvest) # Seleccionamos una URL url <- "https://www.bcn.cl/portal/" # Leemos la URL con rvest read_html(url) ``` ``` ## {html_document} ## <html lang="es"> ## [1] <head>\n<meta http-equiv="Content-Type" content="text/html; charset=UTF-8 ... ## [2] <body>\r\n\r\n<app-root></app-root><!-- Global site tag (gtag.js) - Googl ... ``` --- ## Uso de `rvest` Permite extraer información utilizando una simple nomenclatura. A través de la selección de una parte de una página, es posible extraer algún dato puntual. Algunas de las funciones más útiles: * `read_html()`: Lee una URL (una página) y devuelve un objeto XML (código fuente) * `html_element()`: Selecciona una parte del contenido del objeto XML. Para esto puede utilizarse lo que se obtiene con SelectorGadget * `html_text()`: Devuelve el texto asociado a la parte seleccionada * `html_table()`: Al seleccionar una tabla HTML, esta es posible transformarla directamente a un dataframe --- class: inverse, center, middle background-image: url("data:image/png;base64,#Imagenes/MochoBlanco.jpg") background-size: cover ## Veamos las capacidades de `rvest` en R Script **1 - rvest - Funciones Base.R** --- ## Uso de `rvest` Resumiendo lo visto en R podemos extraer un elemento en particular que nos puede ser de interés. ```r # Cargamos libreria rvest library(rvest) # Seleccionamos una URL url <- "https://www.bcn.cl/siit/reportescomunales/comunas_v.html?anno=2021&idcom=11201" # Leemos con rvest, pero ahora obtenemos solo el valor de superficie de la comuna read_html(url) %>% html_element(css = "tr:nth-child(1) .font-weight-bold+ td") %>% html_text() ``` ``` ## [1] "29796.4 km2" ``` ```r # Ahora vamos a obtener el gentilicio read_html(url) %>% html_element(css = "tr:nth-child(2) .font-weight-bold+ td") %>% html_text() ``` ``` ## [1] "Aysenino/a" ``` --- ## Uso de `rvest` Es importante diferenciar que nosotros podemos extraer un elemento o una serie de elementos. ```r # Utilicemos html_element con varios elementos seleccionados read_html(url) %>% * html_element(css = ".font-weight-bold+ td") %>% html_text() ``` ``` ## [1] "29796.4 km2" ``` ```r # Ahora provemos con html_elements read_html(url) %>% * html_elements(css = ".font-weight-bold+ td") %>% html_text() ``` ``` ## [1] "29796.4 km2" ## [2] "Aysenino/a" ## [3] "Julio Esteban Confucio Uribe Alvarado (desde 2021-06-28) - Martínez Gallardo Luis (hasta 2021-06-27)" ## [4] "6" ## [5] "Región Aysén del G. Carlos Ibáñez del Campo\n Provincia de Aysén\n Distrito 27 - 14° Circunscripción" ## [6] "Ver listado" ``` --- ## Uso de `rvest` También podemos extraer directamente una tabla. ```r # Podemos pasar una tabla directamente a un dataframe con html_table tabla <- read_html(url) %>% html_element(css = "#contenido > section.tabla > div > div > div.col-md-8 > table") %>% html_table() # Vemos la tabla resultante tabla ``` ``` ## # A tibble: 6 x 2 ## X1 X2 ## <chr> <chr> ## 1 Superficie "29796.4 km2" ## 2 Gentilicio "Aysenino/a" ## 3 Alcalde "Julio Esteban Confucio Uribe Alvarado (desde 2021-06-28) - ~ ## 4 Nº de concejales "6" ## 5 Pertenece a "Región Aysén del G. Carlos Ibáñez del Campo\n ~ ## 6 Normas que la r~ "Ver listado" ``` --- ## Uso de `rvest` Resumen de las funciones más útiles de la librería `rvest`: |Función |Descripción | |:---------------|:|----------------------------------------------------------------------------------------------------------------:| |read_html() |Lee una URL (una página) y devuelve un objeto XML (código fuente) | |html_element() |Selecciona una parte del contenido del objeto XML. Para esto puede utilizarse lo que se obtiene con SelectorGadget | |html_text() |Devuelve el texto asociado a la parte seleccionada | |html_text2() |Remueve los espacios sobrantes y saltos de línea | |html_table() |Al seleccionar una tabla HTML, esta es posible transformarla directamente a un dataframe | |html_attrs() |Devuelve los atributos del elemento seleccionado | |html_attr() |Devuelve un atributo en especifico del elemento seleccionado | |html_name() |Devuelve el nombre del elemento seleccionado | |html_children() |Devuelve los elementos hijos/anidados | --- class: inverse, center, middle background-image: url("data:image/png;base64,#Imagenes/MochoBlanco.jpg") background-size: cover ## Raspado a páginas dinámicas --- ## Páginas dinámicas Muchas páginas requieren de la interacción del usuario para obtener la información requerida (selección de campos, relleno de formularios, ingreso de sesión, etc.), por lo que se vuelve un poco más complejo la extracción de información. Cuando ya se necesita una mayor interacción con el sitio a analizar, es posible utilizar la librería **RSelenium**, la cual permite simular la interacción de un usuario humano dentro una página Web. - `RSelenium` permite realizar variadas operaciones (ingreso de datos, clicks, selección de opciones, movimiento entre ventanas) - La librería utiliza una sintaxís un poco distinta a lo que estamos acostumbrados a ver en R - También está extendidamente documentada --- ## Uso de `RSelenium` En primer lugar, se requiere iniciar un servidor Selenium el que permite operar un navegador Web a través de instrucciones desde R. .pull-left[ * Iniciamos el servidor * Utilizamos un puerto (por defecto es 4567) * Señalamos el navegador a utilizar * La version del driver ] .pull-right[ ```r # Cargamos la librería library(RSelenium) # Iniciamos servidor rsDriver(port = 4567L, browser = "chrome", chromever = "latest") ``` ] -- ```r # Cargamos la librería library(RSelenium) # Podemos chequear versiones disponibles binman::list_versions("chromedriver") ``` ``` ## $win32 ## [1] "83.0.4103.39" "84.0.4147.30" "85.0.4183.38" "85.0.4183.83" ## [5] "85.0.4183.87" "86.0.4240.22" "88.0.4324.27" "88.0.4324.96" ## [9] "89.0.4389.23" "90.0.4430.24" "91.0.4472.101" "91.0.4472.19" ## [13] "92.0.4515.107" "93.0.4577.15" "93.0.4577.63" "94.0.4606.41" ## [17] "94.0.4606.61" "95.0.4638.10" "95.0.4638.17" "95.0.4638.54" ## [21] "96.0.4664.18" ``` --- ## Uso de `RSelenium` En primer lugar, se requiere iniciar un servidor Selenium el que permite operar un navegador Web a través de instrucciones desde R. .pull-left[ * Iniciamos el servidor * Utilizamos un puerto (por defecto es 4567) * Señalamos el navegador a utilizar * La version del driver ] .pull-right[ ```r # Cargamos la librería library(RSelenium) # Iniciamos servidor rsDriver(port = 4567L, browser = "chrome", * chromever = "94.0.4606.41") ``` ] ```r # Cargamos la librería library(RSelenium) # Podemos chequear versiones disponibles. binman::list_versions("chromedriver") ``` ``` ## $win32 ## [1] "83.0.4103.39" "84.0.4147.30" "85.0.4183.38" "85.0.4183.83" ## [5] "85.0.4183.87" "86.0.4240.22" "88.0.4324.27" "88.0.4324.96" ## [9] "89.0.4389.23" "90.0.4430.24" "91.0.4472.101" "91.0.4472.19" ## [13] "92.0.4515.107" "93.0.4577.15" "93.0.4577.63" "94.0.4606.41" ## [17] "94.0.4606.61" "95.0.4638.10" "95.0.4638.17" "95.0.4638.54" ## [21] "96.0.4664.18" ``` --- ## Uso de `RSelenium` Una vez que iniciamos el servidor, se abre un navegador, el cual podremos utilizar a través de R. Vamos a probar las funciones más básicas. .pull-left[ ```r # Iniciamos servidor driver <- rsDriver(port = 4567L, browser = "chrome", chromever = "94.0.4606.41") # Separamos el cliente/servidor navegador <- driver$client servidor <- driver$server # Vamos a la página de Google url <-"https://www.google.com/" # Ingresamos a la pagina navegador$navigate(url = url) # Realizamos el proceso de extracción de datos # Cerramos navegador y servidor (¡MUY IMPORTANTE!) navegador$close() system(paste0("Taskkill /F /T" ," /PID ", driver$server$process$get_pid())) ``` ] .pull-right[ <img src="data:image/png;base64,#Imagenes/Google.jpg" width="500px" style="display: block; margin: auto;" /> ] --- class: inverse, center, middle background-image: url("data:image/png;base64,#Imagenes/MochoBlanco.jpg") background-size: cover ## Ahora veamos lo que podemos hacer con `RSelenium` en R Script **4 - RSelenium - Funciones Base.R** --- ## Uso de `RSelenium` Recapitulando lo que vimos en R, luego que ingresamos a una página Web, podemos utilizar algunas funciones básicas. ```r # Podemos identificar elementos con CSS selector buscador <- navegador$findElement(using = "css",value = "body > div.L3eUgb > div.o3j99.ikrT4e.om7nvf > form > div:nth-child(1) > div.A8SBwf > div.RNNXgb > div > div.a4bIc > input") ``` Podemos aplicar varias funciones sobre el elemento. ```r # Podemos destacarlo buscador$highlightElement() # Podemos extraer información de sus atributos buscador$getElementAttribute(attrName = "name") buscador$getElementAttribute(attrName = "title") # Podemos ingresar datos buscador$sendKeysToElement(list("RStudio",key = "enter")) ``` --- ## Uso de `RSelenium` También podremos ver direferencias entre funciones similares. ```r # Podemos ir a uno de los resultados *resultados <- navegador$findElement(using = "css",value = ".ellip , .tjvcx") # Podemos obtener el texto de un elemento con getElementText resultados$getElementText() # Con getElementText podemos acceder a todos los elementos *resultados <- navegador$findElements(using = "css",value = ".ellip , .tjvcx") # Podemos ver el texto de cada resultado de la lista resultados[[1]]$getElementText() resultados[[2]]$getElementText() resultados[[3]]$getElementText() resultados[[4]]$getElementText() ``` --- ## Resumen de métodos en `RSelenium` Los principales métodos a nivel de navegador **[navegador$...]** corresponden a: |Método |Descripción | |:------------------------|:|---------------------------------------------------------:| |navigate() |Permite ir a una determinada página | |getCurrentUrl() |Devuelve el nombre de la página actual | |getTitle() |Devuelve el título de la página actual | |goForward() |Se dirige a la página siguiente | |goBack() |Vuelve a la página anterior | |getPageSource()[[1]] |Devuelve el código fuente de la página actual | |findElement() |Encuentra un elemento dentro de la página actual | |findElements() |Encuentra varios elementos dentro de la página actual | |maxWindowSize() |Maximiza el tamaño del navegador | |close() |Cierra el navegador | --- ## Resumen de métodos en `RSelenium` Por otro lado, a nivel de elemento **[elemento$...]** tenemos: |Método |Descripción | |:------------------------|:|---------------------------------------------------------:| |getElementAttribute() |Devuelve el valor asociado a un atributo determinado | |getElementText() |Devuelve el texto asociado a un elemento | |sendKeysToElement() |Envia un texto a un elemento determinado | |highlightElement() |El elemento se destaca en amarillo | |clickElement() |Envia un click a un elemento determinado | |clearElement() |Limpia el texto en un elemento determinado | Tener presente que también podemos combinar **RSelenium** con **rvest** para extraer algún contenido en particular. --- ## Diferentes formas de buscar un elemento Cómo hemos logrado apreciar, existen diversas formas de encontrar un elemento dentro de una página Web. Tengamos en cuenta el siguiente ejemplo: ```r <p id = "tomate" class = "primario" name = "dato"> texto1</p> <p id = "palta" class = "secundario" name = "prediccion"> texto2</p> ``` -- Esto en una página Web simplemente se vería cómo: .center.bg-washed-green.b--dark-green.ba.bw2.br3.shadow-5.ph4.mt5[ texto1 texto2 ] --- ## Diferentes formas de buscar un elemento Cómo hemos logrado apreciar, existen diversas formas de encontrar un elemento dentro de una página Web. Tengamos en cuenta el siguiente ejemplo: ```r <p id = "tomate" class = "primario" name = "dato"> texto1</p> *<p id = "palta" class = "secundario" name = "prediccion"> texto2</p> ``` Ahora imaginemos que queremos obtener identificar el segundo elemento. Podemos hacerlo mediante: -- ```r # Utilizando nomenclatura css navegador$findElement(using ="css", value ="#palta") # Solo con id navegador$findElement(using ="id", value ="palta") # Solo con name navegador$findElement(using ="name", value ="prediccion") # Podríamos utilizar class navegador$findElement(using ="class", value ="secundario") # También utilizando Xpath navegador$findelement(using ="xpath", value ='//*[(@id = "palta")]') ``` --- class: center, middle Un error común es que se nos cierre la página que estamos explorando (por diversas razones). Al momento de volver a iniciar la instancia con **`rsDriver`**, puede que tengamos un problema con el puerto a utilizar, sin embargo pueden probar otro puerto (**un número cercano a 4567**). --- ## `rvest` vs `RSelenium` En resumen, ya conocemos estas dos librerías de R, las cuales se pueden utilizar para diferentes escenarios. .pull-left[ .center[**rvest**] - Permite trabajar con el código fuente (sólo se carga una vez) - Acceder a información en un nodo específico - Muy fácil de utilizar y muy rápido ] .pull-right[ .center[**RSelenium**] - Crea una instancia de un navegador autónomo (hay una conexión permanente con la página) - Permite enviar instrucciones desde R - Ingresar datos de usuario, seleccionar opciones - Su uso conlleva un poco más de dificultad ] --- ## Sintetizando lo aprendido Considerando lo visto hasta el momento en el Taller, podemos resumir lo aprendido en los siguientes puntos: - Podemos obtener información almacenada en diferentes tipos: texto, tablas, imágenes, archivos, etc. - Lo más relevante es entender la lógica de cada página a raspar. Con esto en mente, podemos estructurar nuestro código para obtener la información requerida - Al momento de raspar un sitio Web, podemos acceder a un determinado elemento a través de: - SelectorGadget - Inspector de elementos de nuestro navegador - Conocimiento de selectores CSS --- ## Limitaciones al momento de raspar una página Web .center[ <img src="data:image/png;base64,#Imagenes/meme2.jpg" width="700px" /> ] --- ## Limitaciones al momento de raspar una página Web Dado que existen aplicaciones que se prestan para fines maliciosos o que por otro lado pueden afectar el rendimiento de un sitio Web, los desarrolladores de sitios Web implementan diferentes medidas para prevenir la consulta másiva a través de estas aplicaciones. * Uso solo a través de un usuario determinado * Uso de formularios o desafíos (por ejemplo captchas) * Constanstes modificaciones en páginas Web <img src="data:image/png;base64,#Imagenes/Recaptcha.jpg" width="500px" style="display: block; margin: auto;" /> --- ## Consideraciones éticas Volviendo a este tema, no hay un consenso universal respecto a qué es permitido o no al momento de raspar una página, no obstante podemos seguir algunas **buenas prácticas**: - Si hay disponible una API, utilizarla para evitar raspar toda una página - Consultar datos a una tasa de tiempo razonable (incluir un *delay*) - Sólo retener información que me es necesaria y que no puedo conseguir por otros medios - Respetar otros términos establecidos en sitios Web - Respetar derechos de autor .right[**James Densmore (2017), Data Liftoff**] --- class: inverse, center, middle background-image: url("data:image/png;base64,#Imagenes/MochoBlanco.jpg") background-size: cover ## Referencias --- ## Referencias (muy buenas, veanlas) - Automated Web Scraping with R. https://resulumit.com/teaching/scrp_workshop.html - Harvesting the web with rvest. https://rvest.tidyverse.org/articles/harvesting-the-web.html - RSelenium Basics. https://cran.r-project.org/web/packages/RSelenium/vignettes/basics.html - How to drive a Web browser with R (and RSelenium). https://www.computerworld.com/article/2971265/how-to-drive-a-web-browser-with-r-and-rselenium.html - Polite Github Repository. https://github.com/dmi3kno/polite - Ethics in Web Scraping. https://towardsdatascience.com/ethics-in-web-scraping-b96b18136f01 - $100 to $1000 per hour Web Scraping with Python.https://medium.com/@dennisyd/100-to-1000-hours-with-python-pandas-and-selenium-9cf5c40b46d2 --- class: inverse, center, middle background-image: url("data:image/png;base64,#Imagenes/MochoBlanco.jpg") background-size: cover ## Gracias por su participación Cualquier pregunta, pueden contactarme a mi correo: **victor.caquilpan@gmail.com** 😄