Extracción de datos con web scraping para la investigación en ciencias sociales: aplicaciones prácticas
Dr. Agustín Nieto (INHUS-CONICET/UNMdP)
20 de febrero de 2025
Financian: Proyecto NON-CONSPIRA-HATE! (Ref. PID2021-123983OB-I00) y Grupo ESEIS/EPIT-2025.
Las recientes restricciones en el acceso a las APIs de redes sociales han afectado profundamente a la investigación digital y las ciencias sociales computacionales. Plataformas como Twitter y Facebook han reducido o eliminado el acceso gratuito a sus APIs, lo que obliga a los investigadores a encontrar nuevas formas de acceder a los datos. En este contexto, surge la “era post-API”, donde los estudios sociales se ven limitados por la disponibilidad de datos y los altos costos para obtenerlos.
Según Tromble (2021), poco. En sus palabras: “La relación subyacente entre los investigadores, las plataformas y los datos digitales sigue siendo en gran medida la misma. Las plataformas y sus API siempre han sido cajas negras propietarias, nunca pensadas para uso académico. Incluso cuando los investigadores podían extraer datos de forma aparentemente interminable, rara vez sabíamos qué tipo o calidad de datos teníamos a mano. Es más, la generosidad de la era API permitió a muchos investigadores realizar su trabajo con poco respeto por el rigor, la ética o el enfoque en el valor social que deberíamos esperar de la investigación académica. En otras palabras, nuestros procesos y resultados de investigación digital no siempre han ocupado un lugar destacado. En lugar de ver el año 2018 y a Cambridge Analytica como una profunda disyuntiva y pérdida, sugiero que los investigadores digitales deben adoptar una mirada más crítica sobre cómo nuestra comunidad recopiló y analizó datos cuando todavía parecían tan abundantes, y utilizar estas reflexiones para informar nuestros enfoques en el futuro.”
El web scraping, una técnica tradicionalmente utilizada para extraer datos directamente desde sitios web, ha ganado relevancia como solución alternativa frente a las restricciones de las APIs. Aunque históricamente subestimado en la investigación social, el scraping ha demostrado ser un recurso esencial para recolectar datos tanto en tiempo real como históricos de plataformas de redes sociales.
Con las APIs restringidas, el scraping ofrece a lxs investigadorxs una forma accesible y flexible para continuar obteniendo datos relevantes para el análisis social. Sin embargo, también presenta desafíos, tanto éticos como legales, en cuanto a la privacidad de lxs usuarixs y el cumplimiento de los términos de servicio de las plataformas.
Tjaden (2023) sostiene que “a medida que los grandes proveedores de datos digitales como Facebook o Twitter restringen cada vez más el acceso a sus datos para los investigadores, el web scraping cobrará mayor importancia en el futuro y merece su lugar en la caja de herramientas de los académicos de migración y movilidad.”
El principal desafío que plantea la era post-API es el acceso a los datos. Las APIs, que antes permitían a lxs investigadorxs obtener información estructurada y autorizada de las redes sociales, ahora exigen pagos considerables o han reducido sus funcionalidades gratuitas. Esto ha creado una barrera de entrada para los estudios de datos sociales a gran escala, particularmente para aquellos con recursos limitados.
En este nuevo contexto, el scraping se ha posicionado como una alternativa viable, pero no sin sus dificultades. La necesidad de cumplir con las normativas de privacidad y evitar el bloqueo por parte de las plataformas requiere de enfoques más sofisticados.
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
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
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.
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.
Las páginas web dinámicas basan su comportamiento y funcionalidad en dos tipos de programación: front-end y back-end. JavaScript es el lenguaje de programación que se usa para las instrucciones del lado del cliente. Estas instrucciones se ejecutan en el navegador. Mientras que las instrucciones que se ejecutan del lado del servidor son instrucciones escritas en lenguajes de programación como PHP y que son ejecutadas para crear lo que se ha solicitado en interacción con la página.
Una vez ejecutadas las instrucciones en el servidor, un nuevo HTTP response se envía al navegador para mostrar lo que se ha solicitado. El resultado final es el mismo que en un sitio web estático: una página HTML que el usuario ve desde el navegador.
Más allá de esta definición, no existe una frontera clara entre lo que es contenido estático y dinámico. Debido a la evolución actual de la web se podría decir que es todo el contenido es dinámico por la manera en que se crea. La proliferación de herramientas de publicación y de autoría de contenidos tales como los blogs convierten en dinámicos contenidos aparentemente estáticos.
read_html()
opera sobre el código fuente HTML descargado
del servidor. Esto funciona para la mayoría de los sitios web, pero
puede fallar si el sitio usa javascript para generar HTML.
read_html_live()
proporciona una interfaz alternativa que
ejecuta un navegador web activo (Chrome) en segundo plano. Esto le
permite acceder a elementos de la página HTML que se generan
dinámicamente mediante javascript e interactuar con la página en vivo
haciendo clic en botones o escribiendo formularios.
Detrás de escena, esta función utiliza el paquete chromote
, que requiere que tengas una copia de Google Chrome instalada en tu
máquina.
ChatGPT puede ser una herramienta muy útil en el proceso de web scraping al ayudarnos a analizar y comprender la estructura HTML de las páginas web. Su capacidad para examinar el código fuente y sugerir los selectores CSS o XPath más efectivos nos permite identificar rápidamente los elementos que necesitamos extraer, además de proporcionar orientación sobre la mejor manera de navegar por la estructura DOM de la página. Esta asistencia es particularmente útil cuando nos enfrentamos a páginas web complejas o dinámicas que requieren un análisis detallado de su estructura.
Además, ChatGPT puede ayudarnos a generar y optimizar código de web scraping y ofrecer soluciones para manejar casos específicos como la extracción de datos dinámicos, la implementación de delays apropiados para respetar los servidores, y la gestión de errores comunes. También puede proporcionar orientación sobre buenas prácticas y consideraciones éticas en el web scraping.