Colly es un framework de web scraping para Go que destaca por su capacidad para manejar múltiples protocolos de comunicación. Esta guía técnica explora cómo implementar recolección de datos sobre HTTP, HTTPS y WebSocket utilizando esta biblioteca.
Ventajas técnicas de Colly para scraping multiprotocolo
El ecosistema actual de aplicaciones web requiere interactuar con distintos protocolos. Colly aborda esta necesidad mediante:
- Procesamiento concurrente nativo aprovechando las goroutines de Go
- Arquitectura modular con sistema de middlewares y callbacks
- Compatibilidad integrada con HTTP, HTTPS y extensibilidad para WebSocket
- API fluida que minimiza el código boilerplate
Implementación de solicitudes HTTP y HTTPS
El manejo de protocolos HTTP se realiza internamente a través del módulo de transporte, configurable vía http.RoundTripper.
Solicitud HTTP básica
scraper := colly.NewCollector()
scraper.OnRequest(func(req *colly.Request) {
log.Printf("Iniciando petición a %s", req.URL)
})
if err := scraper.Visit("http://ejemplo.com"); err != nil {
log.Fatal(err)
}
Conexiones HTTPS seguras
El soporte TLS está habilitado por defecto. Para sitios con certificados problemáticos en entornos de desarrollo:
scraper := colly.NewCollector()
scraper.WithTransport(&http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
})
scraper.Visit("https://api.segura.com")
Características avanzadas de red
Colly incorpora mecanismos para optimizar las solicitudes HTTP:
- Control de tasa: Configuración mediante
colly.LimitRulepara regular frecuencia por dominio - Persistencia de sesiones: Gestión automática de cookies entre solicitudes
- Rotación de proxies: Integración con servicios proxy para distribuir origen de tráfico
- Almacenamiento temporal: Sistema de caché configurable para evitar redundancias
Integración de WebSocket
Aunque Colly no incluye soporte nativo para WebSocket, su arquitectura permite incorporar bibliotecas especializadas como gorilla/websocket dentro de los flujos de scraping.
Implementación de cliente WebSocket
import "github.com/gorilla/websocket"
scraper.OnHTML("[data-ws-endpoint]", func(elem *colly.HTMLElement) {
endpoint := elem.Attr("data-ws-endpoint")
conexion, _, err := websocket.DefaultDialer.Dial(endpoint, nil)
if err != nil {
log.Printf("Error de conexión WS: %v", err)
return
}
defer conexion.Close()
// Bucle de lectura de mensajes
for {
_, mensaje, err := conexion.ReadMessage()
if err != nil {
break
}
procesarMensaje(mensaje)
}
})
Estrategia de reconexión automática
func establecerConexionWSTolerante(url string) *websocket.Conn {
intentos := 0
for {
conexion, _, err := websocket.DefaultDialer.Dial(url, nil)
if err == nil {
return conexion
}
intentos++
espera := time.Duration(intentos) * 2 * time.Second
log.Printf("Reintento #%d en %v", intentos, espera)
time.Sleep(espera)
}
}
Casos de uso para WebSocket en scraping
- Monitoreo de cotizaciones financieras en tiempo real
- Captura de mensajes en plataformas de comunicación
- Recepción de alertas y eventos de sistemas distribuidos
Configuración inicial y mejores prácticas
Instalación del módulo
go get github.com/gocolly/colly/v2
Planitlla de configuración
func main() {
collector := colly.NewCollector(
colly.AllowedDomains("dominio.com"),
colly.MaxDepth(3),
colly.UserAgent("Mozilla/5.0 (compatible; Bot/1.0)"),
)
// Reglas de limitación por dominio
collector.Limit(&colly.LimitRule{
DomainGlob: "*dominio.com",
Parallelism: 4,
Delay: 500 * time.Millisecond,
})
collector.OnRequest(func(r *colly.Request) {
log.Printf("Accediendo: %s", r.URL)
})
collector.OnScraped(func(r *colly.Response) {
log.Printf("Completado: %s [%d bytes]", r.Request.URL, len(r.Body))
})
collector.Visit("https://dominio.com")
}
Optimización de rendimiento
- Ajuste de concurrencia: Configurar
Parallelismsegún capacidad del servidor destino - Tiempo de espera aleatorio: Implementar
RandomDelaypara simular comportamiento humano - Gestión de caché: Especificar
CacheDirpara almacenar respuestas temporalmente - Profundidad controlaad: Limitar
MaxDepthpara evitar recursión infinita
Resolución de problemas comunes
Error de handshake TLS
collector := colly.NewCollector()
collector.WithTransport(&http.Transport{
TLSHandshakeTimeout: 10 * time.Second,
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
},
})
Timeout en conexiones
collector := colly.NewCollector()
collector.SetRequestTimeout(30 * time.Second)
Selección de protocolo según escenario
| Tipo de contenido | Protocolo recomendado | Justificación |
|---|---|---|
| Páginas estáticas | HTTP/HTTPS | Suficiente para contenido no dinámico |
| Datos actualizados periódicamente | HTTP con polling | Balance entre simplicidad y actualidad |
| Flujos de datos en tiempo real | WebSocket | Latencia mínima y conexión persistente |