Paso 1 y 2. Localizo las conferencias y creo un código que las descargue a mi directorio local

Paso 1.1: Cargar las Librerías Necesarias

library(rvest)
library(magrittr)

En este primer chunk, cargamos las librerías rvest y magrittr.

rvest: permite realizar web scraping en R, ayudando a leer y extraer datos de páginas web. magrittr: facilita el uso de operadores como %>% para hacer código más legible y fácil de seguir.

Paso 1.2: Definir la Función crear_urls

crear_urls <- function(fecha_inicio, fecha_final) {
  # Convertir las fechas de inicio y final a Date
  fecha_inicio <- as.Date(fecha_inicio)
  fecha_final <- as.Date(fecha_final)
  
  # Crear secuencia de fechas entre fecha_inicio y fecha_final
  fechas <- seq(fecha_inicio, fecha_final, by = "day")
  
  # Aplicar la función generar_url a cada fecha
  urls <- sapply(fechas, generar_url)
  
  return(urls)
}

En este chunk, definimos la función crear_urls, la cual genera una lista de URLs para cada fecha en el rango especificado:

  1. Convertir fechas a formato Date: Convierte las fechas de inicio y final en objetos de tipo Date.
  2. Crear secuencia de fechas: Genera una secuencia de días desde la fecha de inicio hasta la fecha final.
  3. Aplicar la función generar_url (definida en el siguiente paso) a cada fecha y retorna las URLs generadas.

Paso 1.3: Definir la Función generar_url para Formatear las Fechas

generar_url <- function(fecha) {
  # Cambiar configuración regional a español
  Sys.setlocale("LC_TIME", "es_ES.UTF-8")
  
  # Formatear el día sin cero inicial
  dia <- as.numeric(format(fecha, "%d"))
  mes <- tolower(format(fecha, "%B"))
  anio <- format(fecha, "%Y")
  fecha_formato <- paste(dia, "de", mes, "de", anio, sep = "-")
  
  # Crear la URL con la fecha formateada
  paste0("https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-", 
         fecha_formato)
}

Aquí definimos la función generar_url, que se encarga de transformar una fecha en una URL específica:

  1. Formatear la fecha:
  • dia: se extrae el día sin el cero inicial para los días 1 al 9.
  • mes: se convierte el mes a minúsculas.
  • anio: extrae el año completo.
  1. Concatenar la fecha: Combina dia, mes y anio en el formato requerido.
  2. Crear la URL: Inserta la fecha formateada en la estructura de la URL base.

Paso 1.4: Generar URLs a partir de un Rango de Fechas

# Generar URLs entre el 1 de octubre y el 31 de octubre de 2024
urls <- crear_urls("2024-10-01", "2024-10-31")
print(urls)
##  [1] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-1-de-octubre-de-2024" 
##  [2] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-2-de-octubre-de-2024" 
##  [3] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-3-de-octubre-de-2024" 
##  [4] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-4-de-octubre-de-2024" 
##  [5] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-5-de-octubre-de-2024" 
##  [6] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-6-de-octubre-de-2024" 
##  [7] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-7-de-octubre-de-2024" 
##  [8] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-8-de-octubre-de-2024" 
##  [9] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-9-de-octubre-de-2024" 
## [10] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-10-de-octubre-de-2024"
## [11] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-11-de-octubre-de-2024"
## [12] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-12-de-octubre-de-2024"
## [13] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-13-de-octubre-de-2024"
## [14] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-14-de-octubre-de-2024"
## [15] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-15-de-octubre-de-2024"
## [16] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-16-de-octubre-de-2024"
## [17] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-17-de-octubre-de-2024"
## [18] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-18-de-octubre-de-2024"
## [19] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-19-de-octubre-de-2024"
## [20] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-20-de-octubre-de-2024"
## [21] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-21-de-octubre-de-2024"
## [22] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-22-de-octubre-de-2024"
## [23] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-23-de-octubre-de-2024"
## [24] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-24-de-octubre-de-2024"
## [25] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-25-de-octubre-de-2024"
## [26] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-26-de-octubre-de-2024"
## [27] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-27-de-octubre-de-2024"
## [28] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-28-de-octubre-de-2024"
## [29] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-29-de-octubre-de-2024"
## [30] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-30-de-octubre-de-2024"
## [31] "https://www.gob.mx/presidencia/articulos/version-estenografica-conferencia-de-prensa-de-la-presidenta-claudia-sheinbaum-pardo-del-31-de-octubre-de-2024"

En este último chunk, utilizamos la función crear_urls:

  • Definimos un rango de fechas, en este caso, desde el 1 de octubre hasta el 31 de octubre de 2024.
  • Ejecutamos la función crear_urls, que utiliza la secuencia de fechas y la función generar_url para construir las URLs.
  • Imprimimos la lista de URLs generadas para verificar el resultado.

Paso 2.1: Definir la Función scrape_y_guarda

En este paso, definimos la función scrape_y_guarda que realiza el web scraping para extraer el contenido de cada conferencia desde las URLs generadas y guardarlo en un archivo de texto (.txt).

scrape_y_guarda <- function(url) {
  # Extraer la fecha desde la URL
  fecha <- sub(".*del-([0-9]+-de-[a-z]+-de-[0-9]+).*", "\\1", url)
  
  # Intentar leer la página HTML
  pagina <- tryCatch(read_html(url), error = function(e) NULL)
  if (!is.null(pagina)) {
    # Extraer el texto usando el selector adecuado (ajustar según el HTML específico)
    texto <- pagina %>%
      # html_nodes(".contenido-conferencia") %>%  # <-- ajustar con el selector CSS adecuado
      html_text()
    
    # Verificar que el texto no contenga "Error 404" o "La ruta no existe"
    if (!grepl("Sitio en mantenimiento", texto, ignore.case = TRUE)) {
      # Guardar el texto en un archivo .txt
      nombre_archivo <- paste0("conferencia_", gsub(" ", "_", fecha), ".txt")
      writeLines(texto, nombre_archivo)
    } else {
      cat(paste("El contenido de la conferencia para la fecha", fecha, "no está disponible.\n"))
    }
  } else {
    cat(paste("No se pudo acceder a la página para la fecha:", fecha, "\n"))
  }
}
  1. Extraer la Fecha:

La línea fecha <- sub(“.del-([0-9]+-de-[a-z]+-de-[0-9]+).”, “\1”, url) extrae la fecha desde la URL usando una expresión regular. Esto permite crear el nombre del archivo con la fecha específica de cada conferencia.

  1. Leer la Página HTML:

pagina <- tryCatch(read_html(url), error = function(e) NULL) intenta leer el contenido de la página web. Si hay algún error (por ejemplo, la página no está disponible), la función devuelve NULL.

  1. Extraer el Texto de la Conferencia:

Si la página se lee correctamente, usamos texto <- pagina %>% html_text() para extraer el texto. Ajuste del Selector CSS: Aquí debes reemplazar html_nodes(“.contenido-conferencia”) con el selector CSS que corresponda al contenido de la conferencia en la página web.

  1. Verificar Contenido Válido:

La línea if (!grepl(“Sitio en mantenimiento”, texto, ignore.case = TRUE)) asegura que el contenido descargado no sea una página de error. Si el contenido está disponible, pasamos al siguiente paso.

  1. Guardar el Texto en un Archivo:

Si el contenido es válido, se guarda en un archivo .txt usando writeLines(texto, nombre_archivo). El archivo se nombra en función de la fecha extraída de la URL.

  1. Manejo de Errores:

Si la página está en mantenimiento o la URL no es accesible, se muestra un mensaje indicando que el contenido no está disponible.

Paso 2.2: Aplicar la Función a Cada URL

Ahora que la función scrape_y_guarda está lista, podemos aplicarla a cada URL de la lista usando lapply para automatizar el proceso.

# Aplicar la función a cada URL en la lista
lapply(urls, scrape_y_guarda)
## El contenido de la conferencia para la fecha 1-de-octubre-de-2024 no está disponible.
## El contenido de la conferencia para la fecha 2-de-octubre-de-2024 no está disponible.
## El contenido de la conferencia para la fecha 5-de-octubre-de-2024 no está disponible.
## El contenido de la conferencia para la fecha 6-de-octubre-de-2024 no está disponible.
## El contenido de la conferencia para la fecha 12-de-octubre-de-2024 no está disponible.
## El contenido de la conferencia para la fecha 13-de-octubre-de-2024 no está disponible.
## El contenido de la conferencia para la fecha 19-de-octubre-de-2024 no está disponible.
## El contenido de la conferencia para la fecha 20-de-octubre-de-2024 no está disponible.
## El contenido de la conferencia para la fecha 27-de-octubre-de-2024 no está disponible.
## El contenido de la conferencia para la fecha 28-de-octubre-de-2024 no está disponible.
## [[1]]
## NULL
## 
## [[2]]
## NULL
## 
## [[3]]
## NULL
## 
## [[4]]
## NULL
## 
## [[5]]
## NULL
## 
## [[6]]
## NULL
## 
## [[7]]
## NULL
## 
## [[8]]
## NULL
## 
## [[9]]
## NULL
## 
## [[10]]
## NULL
## 
## [[11]]
## NULL
## 
## [[12]]
## NULL
## 
## [[13]]
## NULL
## 
## [[14]]
## NULL
## 
## [[15]]
## NULL
## 
## [[16]]
## NULL
## 
## [[17]]
## NULL
## 
## [[18]]
## NULL
## 
## [[19]]
## NULL
## 
## [[20]]
## NULL
## 
## [[21]]
## NULL
## 
## [[22]]
## NULL
## 
## [[23]]
## NULL
## 
## [[24]]
## NULL
## 
## [[25]]
## NULL
## 
## [[26]]
## NULL
## 
## [[27]]
## NULL
## 
## [[28]]
## NULL
## 
## [[29]]
## NULL
## 
## [[30]]
## NULL
## 
## [[31]]
## NULL

lapply(urls, scrape_y_guarda): Este código aplica la función scrape_y_guarda a cada elemento de la lista urls. Para cada URL, se ejecuta el proceso de extracción y guardado explicado anteriormente.

Paso 2.3: Cargar Archivos para Análisis

Una vez que todos los archivos .txt se han guardado, podemos cargarlos para realizar análisis adicionales.

# Cargar archivos descargados para análisis
archivos <- list.files(pattern = "*.txt")

list.files(pattern = “*.txt”): Esta línea lista todos los archivos .txt en el directorio de trabajo actual. La lista de archivos se guarda en archivos, que puede usarse para cualquier procesamiento o análisis posterior.

Paso 3. Analizo el texto proveniente de los archivos generados

Cargar y Limpiar el Texto: En este paso, leeremos el contenido de cada archivo .txt generado previamente, lo limpiaremos y prepararemos para el análisis.

library(tm)
## Loading required package: NLP
# Función para leer y limpiar el contenido de los archivos
limpiar_texto <- function(archivo) {
  texto <- readLines(archivo, warn = FALSE) # Leer el archivo
  texto <- paste(texto, collapse = " ") # Combinar todas las líneas en un solo texto
  
  # Convertir a minúsculas y limpiar el texto de URLs, etiquetas HTML, puntuación, y espacios extra
  texto <- tolower(texto)
  texto <- gsub("http\\S+|www\\.\\S+", "", texto) # Remover URLs
  texto <- gsub("<.*?>", "", texto) # Remover etiquetas HTML
  texto <- gsub("[[:punct:]]", "", texto) # Remover puntuación
  texto <- gsub("\\d+", "", texto) # Remover números
  texto <- gsub("\\s+", " ", texto) # Eliminar espacios extra
  
  return(texto)
}

# Leer y limpiar el texto de cada archivo
archivos <- list.files(pattern = "*.txt") # Listar los archivos generados
textos_limpios <- lapply(archivos, limpiar_texto) # Aplicar la limpieza a cada archivo

# Crear un Corpus para el análisis de texto
corpus <- Corpus(VectorSource(textos_limpios))
dtm <- DocumentTermMatrix(corpus) # Crear matriz de términos

Definir limpiar_texto: Esta función lee el archivo y realiza varias operaciones de limpieza.

Aplicar Limpieza: lapply(archivos, limpiar_texto) aplica la función a cada archivo en archivos, generando una lista de textos limpios.

Crear Corpus y Matriz de Términos: Usamos Corpus y DocumentTermMatrix del paquete tm para crear un corpus y una matriz de términos que nos permitirá analizar las palabras más frecuentes.

Paso 4. Genero la nube de palabras y puedo visualizar los primeros hallazgos

4.1 Análisis de Términos:

Sumamos la frecuencia de cada término en el corpus para identificar las palabras más comunes.

# Calcular la frecuencia total de cada término
conteo_total <- colSums(as.matrix(dtm))
terminos_comunes <- sort(conteo_total, decreasing = TRUE)

# Visualizar los términos más frecuentes
print(head(terminos_comunes, 10)) # Muestra las 10 palabras más comunes
##        que        los        las        del       para        por        con 
##       9829       3361       2652       2494       2483       2397       2309 
##        una presidenta    también 
##       2081       1836       1232

4.2 Crear Nube de Palabras:

Usamos el paquete wordcloud para visualizar las palabras más frecuentes en una nube de palabras.

library(wordcloud)
## Loading required package: RColorBrewer
library(wordcloud2)

# Crear la nube de palabras
wordcloud(names(terminos_comunes), terminos_comunes, min.freq = 50, max.words = 100, random.order = FALSE)

  • Frecuencia de Términos: colSums(as.matrix(dtm)) calcula la frecuencia total de cada término en el corpus.
  • Ordenar Términos: sort(conteo_total, decreasing = TRUE) ordena los términos de mayor a menor frecuencia.
  • Generar Nube de Palabras: wordcloud crea una nube de palabras visualizando las palabras más frecuentes. Aquí, min.freq establece la frecuencia mínima para incluir una palabra, y max.words limita el número total de palabras en la nube.
  • Visualizar Términos Frecuentes: print(head(terminos_comunes, 10)) muestra los 10 términos más comunes para tener una idea de las palabras clave antes de la visualización completa.

Como podemos ver nuestra nube tiene muchas palabras que son demasiado comunes y generan ruido en nuestro análisis. Estas palabras incluyen artículos, preposiciones y pronombres, entre otros, que aparecen frecuentemente pero que no agregan mucho significado en el contexto del análisis. Eliminar stopwords es un paso común en el preprocesamiento de texto. Así que tenemos antes de generar nuestro dtm es conveniente eliminar este tipo de palabras.

# Eliminar stopwords de nuestro corpus
corpus2 <- tm_map(corpus, removeWords, stopwords("es"))  # Usar "es" para stopwords en español
## Warning in tm_map.SimpleCorpus(corpus, removeWords, stopwords("es")):
## transformation drops documents

Ahora repitamos el análisis anteriormente realizado y comparemos nuestros términos y nube de palabras

#creamos el nuevo DTM
dtm2 <- DocumentTermMatrix(corpus2)

# Sumar las columnas para obtener el conteo total de cada término
conteo_total2 <- colSums(as.matrix(dtm2))

# Ordenar y mostrar los términos más comunes
terminos_comunes2 <- sort(conteo_total2, decreasing = TRUE)
head(terminos_comunes2, 50)  # Mostrar los 50 términos más comunes
##      presidenta         claudia       sheinbaum        entonces           pardo 
##            1836            1110            1110            1077            1016 
##             var           vamos          méxico            pues        gobierno 
##             945             884             870             740             589 
##       dimension           poder             ver           bueno             mil 
##             525             516             504             464             464 
##             ser           parte            caso            cómo           ahora 
##             444             440             435             434             423 
##            tema           hacer        nacional            aquí        pregunta 
##             420             413             403             395             395 
##         mujeres           todas      importante         gracias         reforma 
##             384             383             373             371             368 
##        function             hoy       seguridad        judicial            país 
##             357             355             355             344             342 
##           decir             ahí            null            días             dos 
##             340             338             336             335             329 
##          pueblo      presidente             van        pagetype         octubre 
##             326             325             325             315             308 
##          además gagobtrackerset           usted        programa             día 
##             301             294             294             280             275
# Crear la nube de palabras
wordcloud(names(terminos_comunes2), terminos_comunes2, min.freq = 50, max.words = 100, random.order = FALSE)

Si hay palabras específicas que deseas eliminar de tu análisis, puedes crear una lista de estas palabras y usar removeWords para quitarlas del corpus, de manera similar a como eliminaste las stopwords. Este paso debería realizarse después de haber eliminado las stopwords y antes de crear la Document-Term Matrix (DTM).

# Eliminar palabras específicas
palabras_eliminar <- c("null", "pardo", "vamos", "pues", "var", "function", "pagetype", "entonces", "gtagset", "gaset", "importante", "pregunta", "además", "cómo", "van", "tema", "gracias", "días", "decir", "octubre", "gagobtrackerset", "interlocutor", "interlocutora", "organizationname", "estenográfica", "contentgroup", "presidenta", "claudia", "sheinbaum", "méxico", "gobierno")
corpus3 <- tm_map(corpus2, removeWords, palabras_eliminar)
## Warning in tm_map.SimpleCorpus(corpus2, removeWords, palabras_eliminar):
## transformation drops documents
# Crear la nueva DTM
dtm3 <- DocumentTermMatrix(corpus3)

# Sumar las columnas para obtener el conteo total de cada término
conteo_total3 <- colSums(as.matrix(dtm3))

# Ordenar y mostrar los términos más comunes
terminos_comunes3 <- sort(conteo_total3, decreasing = TRUE)
head(terminos_comunes3, 50)  # Mostrar los 50 términos más comunes
##    dimension        poder          ver        bueno          mil          ser 
##          525          516          504          464          464          444 
##        parte         caso        ahora        hacer     nacional         aquí 
##          440          435          423          413          403          395 
##      mujeres        todas      reforma          hoy    seguridad     judicial 
##          384          383          368          355          355          344 
##         país          ahí          dos       pueblo   presidente        usted 
##          342          338          329          326          325          294 
##     programa          día         ayer      general constitución   secretaría 
##          280          275          271          271          267          267 
##       manera        salud         años  información         hace     personas 
##          260          260          257          256          253          251 
##       unidos          así      después          ley       muchas  conferencia 
##          250          248          246          238          237          230 
##       prensa         dice        lópez       ciento        tener       buenos 
##          229          228          228          226          226          223 
##    bienestar      obrador 
##          218          216
# Convertir los términos y sus frecuencias a un data frame
terminos_df3 <- data.frame(
  word = names(terminos_comunes3),
  freq = as.numeric(terminos_comunes3)
)

# Crear la nube de palabras con wordcloud2
wordcloud2(terminos_df3, size = 0.5, color = "random-light", backgroundColor = "black")