Colly para Go: guía completa de web scraping
1. ¿Qué es Colly y para qué sirve?
Colly es una librería potente y de alto rendimiento para web scraping (extracción de datos) en el lenguaje Go. Ofrece una interfaz limpia, asíncrona y fácilmente extensible para extraer información de sitios web. Colly está construido sobre los paquetes net/http y goquery (el equivalente a jQuery para Go), lo que permite a los desarrolladores usar la conocida sintaxis de selectores CSS para navegar por documentos HTML.
¿Para qué sirve esta librería? En el mundo actual, los datos son el nuevo petróleo. El web scraping automatiza la recopilación de información: monitoreo de precios de la competencia, recolección de noticias, análisis de métricas SEO, creación de bases de datos de productos y mucho más. Colly destaca frente a otras soluciones por su velocidad (arquitectura asíncrona con gorutinas), soporte integrado de caché, gestión automática de retardos (para respetar las políticas de los sitios) y un sistema flexible de callbacks.
La librería es ideal tanto para scripts pequeños como para grandes sistemas distribuidos de recolección de datos. Gracias al tipado estricto de Go y la ausencia de un runtime (a diferencia de Python/Node.js), las aplicaciones con Colly se compilan en un único archivo binario, lo que simplifica el despliegue y la escalabilidad.
2. Instalación
Para instalar Colly se usa el gestor de paquetes estándar de Go. Asegúrate de tener instalado Go versión 1.18 o superior.
go get -u github.com/gocolly/colly/v2
Después de ejecutar el comando, la librería se añadirá a tu archivo go.mod. También se recomienda instalar goquery para trabajar con HTML (se descargará automáticamente como dependencia):
go get -u github.com/PuerkitoBio/goquery
3. Inicio rápido: ejemplo mínimo
Creemos un scraper simple que muestre los títulos (etiquetas <h1>) de la página principal del sitio example.com.
package main
import (
"fmt"
"github.com/gocolly/colly/v2"
)
func main() {
// Creamos un nuevo collector
c := colly.NewCollector()
// Manejador para páginas visitadas
c.OnHTML("h1", func(e *colly.HTMLElement) {
fmt.Println("Título:", e.Text)
})
// Manejador de errores
c.OnError(func(r *colly.Response, err error) {
fmt.Println("Error:", err)
})
// Iniciamos el scraping
c.Visit("https://example.com")
}
Ejecuta el código con el comando go run main.go. Verás el título de la página. Esta es la base mínima desde la que empezar.
4. Métodos y funciones principales (mínimo 8)
Veamos los métodos clave de Colly que cubren el 90% de las tareas de web scraping.
4.1 colly.NewCollector()
Firma: func NewCollector(options ...func(*Collector)) *Collector
Qué hace: Crea una nueva instancia del collector, el objeto principal para gestionar el scraping. Acepta funciones opcionales de configuración.
// Creación con configuración
c := colly.NewCollector(
colly.AllowedDomains("example.com"), // Permitir solo example.com
colly.CacheDir("./cache"), // Cachear las peticiones
)
4.2 Collector.Visit()
Firma: func (c *Collector) Visit(URL string) error
Qué hace: Inicia una petición HTTP GET a la URL indicada. Es el punto de entrada para el scraping.
err := c.Visit("https://example.com")
if err != nil {
fmt.Println("Error al visitar:", err)
}
4.3 Collector.OnHTML()
Firma: func (c *Collector) OnHTML(selector string, f func(*HTMLElement))
Qué hace: Registra una función callback que se ejecuta cada vez que se encuentra un elemento HTML que coincide con el selector CSS especificado.
c.OnHTML("div.producto", func(e *colly.HTMLElement) {
nombre := e.ChildText("h2")
precio := e.ChildText("span.precio")
fmt.Printf("Producto: %s - Precio: %s\n", nombre, precio)
})
4.4 Collector.OnResponse()
Firma: func (c *Collector) OnResponse(f func(*Response))
Qué hace: Se ejecuta después de recibir una respuesta HTTP completa. Útil para verificar el estado o el contenido bruto.
c.OnResponse(func(r *colly.Response) {
fmt.Println("Código de estado:", r.StatusCode)
fmt.Println("Tamaño de respuesta:", len(r.Body))
})
4.5 Collector.OnError()
Firma: func (c *Collector) OnError(f func(*Response, error))
Qué hace: Manejador de errores que se ejecuta cuando ocurre un fallo en la petición o el procesamiento.
c.OnError(func(r *colly.Response, err error) {
fmt.Println("Error en la petición:", err)
})
4.6 Collector.OnRequest()
Firma: func (c *Collector) OnRequest(f func(*Request))
Qué hace: Se ejecuta justo antes de realizar una petición. Ideal para añadir headers, modificar la URL o registrar la actividad.
c.OnRequest(func(r *colly.Request) {
fmt.Println("Visitando:", r.URL.String())
r.Headers.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)")
})
4.7 Collector.AllowURLRevisit()
Firma: func (c *Collector) AllowURLRevisit()
Qué hace: Permite que una misma URL sea visitada múltiples veces. Por defecto, Colly evita visitar URLs duplicadas.
c.AllowURLRevisit() // Ahora se pueden revisitar URLs
4.8 Collector.Limit()
Firma: func (c *Collector) Limit(limit *LimitRule) error
Qué hace: Establece reglas de limitación para controlar la velocidad de las peticiones y evitar ser bloqueado.
err := c.Limit(&colly.LimitRule{
DomainGlob: "*",
Delay: 1 * time.Second, // Esperar 1 segundo entre peticiones
Parallelism: 2, // Máximo 2 peticiones en paralelo
})
4.9 Collector.Clone()
Firma: func (c *Collector) Clone() *Collector
Qué hace: Crea una copia independiente del collector con la misma configuración. Útil para tareas paralelas.
c2 := c.Clone() // Nuevo collector con la misma configuración
4.10 Collector.Wait()
Firma: func (c *Collector) Wait()
Qué hace: Bloquea la ejecución hasta que todas las peticiones pendientes hayan finalizado. Esencial para programas que deben esperar a que termine el scraping.
c.Visit("https://example.com")
c.Wait() // Espera a que termine todo
5. Ejemplo completo: extraer datos de una tienda online
Este ejemplo combina varios métodos para extraer nombres y precios de productos de una tienda ficticia.
package main
import (
"fmt"
"github.com/gocolly/colly/v2"
)
func main() {
c := colly.NewCollector(
colly.AllowedDomains("tiendaficticia.com"),
)
c.OnHTML("div.producto", func(e *colly.HTMLElement) {
nombre := e.ChildText("h2.nombre")
precio := e.ChildText("span.precio")
fmt.Printf("Producto: %s - Precio: %s\n", nombre, precio)
})
c.OnRequest(func(r *colly.Request) {
fmt.Println("Visitando:", r.URL)
})
c.Visit("https://tiendaficticia.com/productos")
c.Wait()
}
6. Consejos y buenas prácticas
- Respeta el archivo robots.txt: Usa
colly.AllowedDomains()y configura retardos conLimit()para no sobrecargar los servidores. - Usa caché: Activa el caché con
colly.CacheDir()para evitar peticiones repetidas durante el desarrollo. - Simula un navegador real: Configura un User-Agent adecuado en
OnRequest()para evitar bloqueos. - Maneja errores: Siempre implementa
OnError()para detectar fallos en las peticiones. - Prueba con selectores específicos: Usa selectores CSS precisos para evitar extraer datos no deseados.
También en la biblioteca
Generador de códigos QR en C# (.NET) con la librería QRCoder
Envío de Email en C# (.NET): biblioteca System.Net.Mail
DataStore para Kotlin: guía completa con ejemplos prácticos
Generación de PDF en JavaScript: librería pdf-lib
Generación de Swagger/OpenAPI para JavaScript (Node.js) — herramientas y bibliotecas