Web Scraping con R y RStudio
Una introducción
Dr. Agustín Nieto (INHUS-CONICET/UNMdP)
24 de junio de 2025
Centro de Estudios Andaluces
En esencia, una página web es solo un archivo HTML que se muestra en un navegador web. Cuando visita un sitio web, su navegador envía una solicitud al servidor web que aloja el sitio y el servidor responde devolviendo un archivo HTML junto con algunos otros archivos relacionados. Su navegador procesa este archivo HTML y se lo muestra como una página. En última instancia, tanto los sitios web estáticos como los dinámicos generan archivos HTML, pero lo que hace que un sitio web sea estático versus dinámico depende de cómo el servidor crea este archivo HTML antes de enviárselo.
Una página web estática es una página web que se entrega al navegador del usuario exactamente como está almacenada, en contraste con las páginas web dinámicas que son generadas por una aplicación web. En consecuencia, una página web estática muestra la misma información para todos lxs usuarixs. Las páginas web estáticas suelen ser documentos HTML almacenados como archivos en el sistema de archivos y puestos a disposición por el servidor web a través de HTTP. Sin embargo, las interpretaciones laxas del término podrían incluir páginas web almacenadas en una base de datos, e incluso podrían incluir páginas formateadas utilizando una plantilla y servidas a través de un servidor de aplicaciones, siempre que la página servida no cambie y se presente esencialmente como almacenada.
{rvest}
El paquete rvest
nos ayuda a extraer y recolectar datos de
páginas web estáticas y dinámicas (estas últimas con la ayuda de
RSelenium). Está diseñado facilitar las tareas comunes de raspado web.
rvest
está inspirado en paquetes como beautiful
soup y RoboBrowser de Python.
Si vamos a ‘raspar’ varias páginas web, es recomendable utilizar, junto
a rvest
, el paquete polite
. El paquete polite
asegura que se respeten los términos del documento
robots.txt
y que nuestras solicitudes no sobrecarguen el
sitio web que estamos ‘raspando’. El archivo robots.txt
indica a los rastreadores de los buscadores qué páginas o archivos del
sitio se pueden solicitar y cuáles no. Como ya dijimos, se utiliza para
evitar que las solicitudes que recibe el sitio lo sobrecarguen.
El paquete rvest
es parte de tidyverse
, un
ecosistema de paquetes diseñados con APIs comunes y una filosofía
compartida. Para más información véase tidyverse.org.
La función read_html()
es originaria del paquete
xml2
que trabaja con archivos XML y usa una interfaz
simple y consistente. El paquete xml2
fue diseñado en base
al paquete libxml2
del lenguaje C
. La función
read_html()
convierte un documento XML/HTML (o nodo o
conjunto de nodos) en una lista R equivalente.
Las funciones html_element()
y html_elements()
permiten extraer con facilidad fragmentos de documentos HTML mediante
los selectores XPath
y CSS
.
x |
Un documento, un conjunto de nodos o un solo nodo. |
css, xpath |
Nodos para seleccionar. Proporcione uno de |
Hay dos formas de recuperar texto de un elemento html:
html_text()
y html_text2()
. La función
html_text()
es una fina envoltura alrededor de la función
xml2::xml_text()
que devuelve solo el texto subyacente sin
procesar. Por su parte, html_text2()
simula cómo se ve el
texto en un navegador y utiliza un enfoque inspirado en la función
innerText()
de JavaScript. En términos generales, convierte
la etiqueta <br />
en \n
, agrega líneas
en blanco alrededor de las etiquetas <p>
y formatea
ligeramente los datos tabulares.
Vale aclarar que html_text2()
suele devolver lo que se
desea en la forma en que se desea, pero es mucho más lento que
html_text()
. Por esta razón es recomendable usar
html_text()
para raspados de mayor volumen.
html_attr()
obtiene un solo atributo;
html_attrs()
obtiene todos los atributos.
library(rvest)
minimal_html('<ul><li><a href="https://a.com" class="important">a</a></li></ul>') |>
html_elements("a") |> html_attr("href")
## [1] "https://a.com"
La función html_table
transforma una tabla html en un marco
de datos.
library(rvest)
minimal_html("<table><tr><th>Col A</th><th>Col B</th></tr>
<tr><td>1</td><td>x</td></tr><tr><td>4</td><td>y</td></tr>
<tr><td>10</td><td>z</td></tr></table>") |>
html_element("table") |> html_table()
## # A tibble: 3 × 2
## `Col A` `Col B`
## <int> <chr>
## 1 1 x
## 2 4 y
## 3 10 z
{Rcrawler}
es un paquete R para rastrear sitios web y
extraer datos estructurados que se pueden usar para una amplia gama de
aplicaciones útiles, como minería web, minería de texto, minería de
contenido web y minería de estructuras web. Entonces, ¿cuál es la
diferencia entre Rcrawler y rvest?: rvest extrae datos de una página
específica navegando a través de selectores. Rcrawler atraviesa y
analiza automáticamente todas las páginas web de un sitio web y extrae
todos los datos que necesita de ellos a la vez con un solo comando..
La clave para raspar de forma masiva el contenido específico de un sitio con páginas estáticas es la construcción de un listado (vector) de urls desde distintas páginas estáticas.
Una vez que logramos armar el listado podemos recorrer cada una de las páginas para extraer el contenido deseado.
El recorrido página por página lo podemos automatizar con un ciclo
for
. Pero antes de ver qué es un ciclo for
recordemos qué es una url.
URL significa (en castellano) Localizador de Recursos Uniforme. En concreto, los URLs son cadenas de caracteres con las que se asigna una dirección única a cada uno de los recursos de información disponibles en Internet. Existe un único URL para cada recurso de Internet. El URL de un recurso es su dirección en Internet, la cual permite que el navegador la encuentre. El formato general de un URL es: :esquema://máquina/directorio/archivo
for
El ciclo for es uno de los más utilizados en programación debido a que permite repetir varias instrucciones un cierto número de ocasiones (por ejemplo, 5 veces). Se emplea en el recorrido de vectores y otras estructuras de datos.
Características:
El paquete {purrr} mejora el conjunto de herramientas de programación funcional de R al proporcionar un conjunto completo y consistente de herramientas para trabajar con funciones y vectores. Este paquete tiene funciones que le permiten reemplazar muchos bucles for con código más breve y más fácil de leer.
map_df()
Las funciones map
transforman su entrada aplicando una
función a cada elemento de una lista o vector atómico y devolviendo un
objeto de la misma longitud que la entrada.
## [1] 1.000000 1.414214 1.732051 2.000000 2.236068 2.449490 2.645751 2.828427
## [9] 3.000000
Un truco para crear listas con miles de urls consiste en descubrir la estructura url de las páginas individuales. Un ejemplo son las páginas de periódicos y sus páginas de notas individuales: https://www.lacapitalmdp.com/notas-al-pie-de-la-pandemia-sin-perder-la-ternura-jamas/4656/
## [1] "https://www.lacapitalmdp.com/notas/1999"
## [2] "https://www.lacapitalmdp.com/notas/2000"
## [3] "https://www.lacapitalmdp.com/notas/2001"
## [4] "https://www.lacapitalmdp.com/notas/2002"
## [5] "https://www.lacapitalmdp.com/notas/2003"
## [6] "https://www.lacapitalmdp.com/notas/2004"
Este paquete contiene herramientas útiles para trabajar con HTTP organizado por verbos HTTP (GET(), POST(), etc). Las funciones de configuración facilitan el control de componentes de solicitud adicionales.