⚠️ Nota: La idea original de este proyecto surgió gracias al canal Soumil Shah, por lo que doy crédito y recomiendo ver su serie de vídeos sobre Elastic Search Aquí.
El repositorio con el resultado final puede ser consultado en Github.
Índice
- Post 1 - Introducción: Aquí
- Post 2 - Recolección de los datos: Aquí
- Post 3 - Limpieza y almacenamiento de los datos: Aquí
- Post 4 - Desarrollo de la API (🚧 Trabajando en ello...)
- Post 5 - Desarrollo del cliente Web (🚧 Trabajando en ello...)
Requisitos:
- Go (1.19.2 Opcional) y conocimientos básicos de Go.
Creación de las carpetas y archivos
Para el desarrollo de las diferentes partes del proyecto, crearemos 3 carpetas principales, frontend
, backend
y data
:
.
├── frontned
├── backend
└── data
Ahora, dentro de la carpeta de data, crearemos la carpeta scraping
y cleansing
, para la obtención y limpieza de los datos respectivamente:
data/
├── scraping
├── cleansing
Por ahora solo crearemos un nuevo módulo de Go para obtener los datos, esto dentro de la carpeta scraping/
:
cd data/scraping
go mod init github.com/username/reponame
Si el anterior paso fue ejecutado correctamente, debería haber un archivo go.mod
dentro de la carpeta scraping/
:
data/
├── scraping
│ ├── go.mod
├── cleansing
Obtención de los datos
En primer lugar, debemos descargar el paquete youtubescraper, para ello, estando dentro de la carpeta scraping/
ejecutamos:
go get github.com/PChaparro/go-youtube-scraper
Si no se mostró ningún error en la consola, dentro de la misma carpeta, creamos el archivo main.go
:
touch main.go
Dentro del nuevo archivo creado, podemos copiar el siguiente código para comprobar que la instalación haya sido correcta y el paquete esté funcionando:
package main
import (
"fmt"
// Importamos el paquete para hacer el scraping
youtubescraper "github.com/PChaparro/go-youtube-scraper"
)
func main() {
// Usamos el metodo GetVideosData con los siguientes argumentos
// El primer argumento es una key de la api de youtube, en este caso no lo vamos a usar
// El segundo argumento es el texto que queremos buscar en youtube
// El tercer argumento es el numero de videos que queremos obtener (100)
// El cuarto argumenteo es el limite de concurrencia para el funcionamiento del paquete
// El ultimo argumento es si queremos usar la api de youtube en lugar de web scraping
videos, err := youtubescraper.GetVideosData("", "Learn web development", 100, 64, false)
if err != nil {
fmt.Print("Error :(")
}
fmt.Println(len(videos.Videos))
}
El argumento del límite de concurrencia hace referencia al número máximo de go routines
que el paquete podrá utilizar para obtener los datos de los vídeos. Lo anterior puede verse como el número de vídeos que el paquete procesará al mismo tiempo. Más información.
Si todo sale bien, podemos ejecutar el archivo main.go
y al cabo de unos segundos (en mi caso 20 segundos aunque puede variar dependiendo de la conexión a internet) veremos un número en consola:
go run main.go
... Luego de unos segundos
100
El número mostrado hace referencia al número de datos obtenido por el paquete, puede ser exactamente el mismo que el número de datos solicitado o puede ser un poco menor.
Sabiendo que el paquete funcionó correctamente, es momento de obtener los más de 2000 datos para nuestro buscador, esta vez, utilizando una API key de Youtube para que el proceso sea mucho más rápido.
Primero creamos un archivo .env
en dentro de la carpeta scraping/
:
touch .env
Dentro del archivo creado, colocaremos la variable de entorno KEY
(aunque puede tener cualquier nombre) y su valor será nuestra API key de Youtube. Si no tienes una API key, te recomiendo ver este vídeo:
KEY=your api key
Una vez creado el archivo .env
con la variable KEY
que almacena nuestra API Key, es momento de hacer algunos cambios en el código (Leer los comentarios):
package main
import (
// Paquete para convertir los videos a bytes para guardarlos como json
"encoding/json"
"fmt"
// Paquete para crear el archivo .json final
"os"
// Paquete para medir el tiempo que demora la ejecucion
"time"
// Paquete para obtener los datos
youtubescraper "github.com/PChaparro/go-youtube-scraper"
// Interfaces / tipos del paquete para obtener los datos
ysi "github.com/PChaparro/go-youtube-scraper/interfaces"
// Paquete para leer la variable de entorno
"github.com/joho/godotenv"
)
func main() {
// Cargar las variables de entorno
err := godotenv.Load()
if err != nil {
fmt.Println("Error al cargar las variables de entorno.")
}
// Leer y verificar la variable de entorno
key := os.Getenv("KEY")
if key == "" {
fmt.Println("La variable de entorno está vacía")
} else {
// Búsquedas que queremos realizar
queue := []string{
"Learn web development",
}
// Array para guardar los vídeos
results := []ysi.Video{}
// Iterar cada una de las búsquedas definidas anteriormente
for _, query := range queue {
// Tomar el tiempo de inicio
start := time.Now()
// Obtener los vídeos de la búsqueda actual
videos, _ := youtubescraper.GetVideosData(key, query, 100, 64, true)
// Agregar los vídeos de la búsqueda actual al array de resultados
results = append(results, videos.Videos...)
// Imrprimir el tiempo que tomó
fmt.Printf("%s query took %v\n", query, time.Since(start))
}
// Crear los bytes que serán guardasos en formato json
json, err := json.Marshal(results)
if err != nil {
fmt.Printf("Error al convertir a bytes")
} else {
// Si no hay ningún error, guardamos el resultado como un .json
// El 0666 final son permisos de lectura y escritura para todos los usuarios
os.WriteFile("data.json", json, 0666)
}
}
}
Si no hay ningún error, luego de ejecutar el archivo veríamos un mensaje en la consola como el siguiente:
go run main.go
... Luego de unos segundos
Learn web development query took 4.953656575s
El mensaje, como el caso anterior, nos indica que los datos se obtubieron de manera satisfactoria, y deberíamos poder encontrar un archivo data.json
creado dentro de la carpeta scraping/
:
data/
├── scraping
│ ├── .env
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ ├── data.json
├── cleansing
Dentro del archivo data.json
podremos ver un array de objetos como el siguiente:
Si lo anterior es cierto, felicidades 🎉! Haz completado el paso de recolección satisfactoriamente, el único paso restante es agregar más búsquedas al array queue
, como en el siguiente ejemplo:
queue := []string{
"Learn web development",
"Top new games",
"Best world carnivals",
...
}
Luego de agregar más elementos (Ten en cuenta el límite de peticiones diarios de la API de Youtube, con 10 o 15 está más que bien), puedes ejecutar de nuevo el archivo main.go
para obtener los nuevos resultados.
Final
Con esto se concluye esta segunda parte en la que recolectamos nuestros datos utilizando un paquete de web scraping, te invito a continuar con la siguiente en la que limpiaremos nuestros datos y los almacenaremos en Open Search.
Referencias
Para consultar las referencias dirigirse a cada uno de los enlaces que aparencen dentro o al final de los diferentes párrafos.
Top comments (0)