Cómo extraer datos de la Web con Golang 2025

raspar datos de la web con go

El web scraping es una potente técnica para extraer datos de sitios web, y Golang (Go) es un lenguaje excelente para esta tarea. Conocido por su rendimiento y eficiencia, Go puede manejar el web scraping con facilidad. Entonces, ¿cómo extraer datos de la web con Golang? Esta guía te guiará a través del proceso de scraping de páginas web utilizando Golang, cubriendo técnicas y consejos relacionados.

¿Es bueno Golang para extraer datos de la Web?

Antes de aprender más sobre el scraping de datos de la web con Golang, es importante entender por qué elegir Golang para el scraping web y qué ventajas ofrece.

Golang es una buena opción para el web scraping debido a su alto rendimiento, su eficiente modelo de concurrencia y su robusta librería estándar. Gracias a su capacidad para gestionar varias peticiones simultáneamente mediante goroutines y a sus paquetes integrados para peticiones HTTP y análisis sintáctico de HTML, Go puede realizar el scraping de grandes volúmenes de datos de forma eficaz. Su sencillez y su capacidad de gestión de errores agilizan aún más el proceso de desarrollo, mientras que las bibliotecas de terceros, como Colly y Goquery, ofrecen funciones adicionales. Aunque es menos habitual que Python para el web scraping, las ventajas de Go lo convierten en una opción atractiva para quienes estén familiarizados con el lenguaje.

Configuración básica para scrapear datos web con Golang

El scraping de datos de la web con Go (Golang) implica hacer peticiones HTTP para recuperar páginas web y luego analizar el contenido HTML para extraer la información deseada. A continuación se muestra una guía paso a paso para raspar datos de la web usando Go:

    1. Configuración del entorno

      En primer lugar, asegúrese de que Go se ha instalado en su sistema. Tampoco puede descargarlo de la sitio web oficial.

      golang
    2. Instalación de los paquetes necesarios

      Se necesitan algunos paquetes para ayudar con las peticiones HTTP y el análisis sintáctico de HTML. Los paquetes más populares son net/http para peticiones HTTP y goquery para analizar HTML.

      Obtener paquete específico ejecutando como:

      ir a github.com/PuerkitoBio/goquery

      Escribir el rascador

      Aquí hay un sencillo para demostrar cómo raspar los datos de un sitio web utilizando Golang:

      paquete principal
      
      importar (
          "fmt"
          "log"
          "net/http"
      
          "github.com/PuerkitoBio/goquery"
      )
      
      func main() {
          // URL del sitio web a consultar
          url := "https://example.com"
      
          // Realiza una petición HTTP GET
          res, err := http.Get(url)
          if err != nil {
              log.Fatal(err)
          }
          defer res.Body.Close()
      
          // Comprueba el código de estado de la respuesta
          if res.StatusCode != 200 {
              log.Fatalf("Fallo en la obtención de datos: %d %s", res.StatusCode, res.Status)
          }
      
          // Parsear el HTML
          doc, err := goquery.NewDocumentFromReader(res.Body)
          if err != nil {
              log.Fatal(err)
          }
      
          // Buscar e imprimir los datos
          doc.Find("h1").Each(func(index int, item *goquery.Selection) {
              heading := item.Text()
              fmt.Println(encabezado)
          })
      }

      Realizar solicitudes HTTP:

      http.Get(url) realiza una solicitud HTTP GET a la URL especificada.
      res.Body.Close() asegura que el cuerpo de la respuesta se cierra después de la lectura.

      Análisis de HTML:

      goquery.NewDocumentFromReader(res.Body) analiza la respuesta HTML y devuelve un objeto goquery.Document.

      Extracción de datos:

      doc.Find("h1").Each() encuentra todos los elementos h1 en el HTML e itera sobre ellos.
      item.Text() extrae el contenido de texto de cada elemento h1.

    3. Funcionamiento del rascador

      Guarda el código anterior en un archivo, por ejemplo, main.go, y ejecútalo utilizando:

      go ejecuta main.go

Consideraciones adicionales

Manejo de Errores: Siempre maneje los errores apropiadamente para asegurar que su scraper no se bloquee inesperadamente.

Respetando robots.txt: Comprueba el archivo robots.txt del sitio web para asegurarte de que tienes permiso para hacer scraping.

Limitación de velocidad: Implemente la limitación de velocidad para evitar abrumar al servidor con peticiones.

Usuario-Agente: Establezca un encabezado User-Agent personalizado para identificar su scraper , como:

req, err := http.NewRequest("GET", url, nil)
if err != nil {
    log.Fatal(err)
}
req.Header.Set("User-Agent", "Golang_Scraper/1.0")

client := &http.Client{}
res, err := client.Do(req)
if err != nil {
    log.Fatal(err)
}
defer res.Body.Close()

// Parsear el HTML como antes

Técnicas avanzadas para raspar datos web con Golang

Paginación

Muchos sitios web utilizan la paginación para dividir el contenido en varias páginas. Para extraer todos los datos, es necesario gestionar la paginación realizando peticiones a cada página de forma secuencial.

He aquí un ejemplo de gestión de la paginación:

paquete principal

importar (
    "fmt"
    "log"
    "net/http"
    "strconv"

    "github.com/PuerkitoBio/goquery"
)

func main() {
    baseURL := "https://example.com/page/"
    página := 1

    para {
        url := baseURL + strconv.Itoa(página)
        res, err := http.Get(url)
        if err != nil {
            log.Fatal(err)
        }
        defer res.Body.Close()

        if res.StatusCode != 200 {
            log.Println("No hay más páginas que recuperar, se ha detenido.")
            break
        }

        doc, err := goquery.NewDocumentFromReader(res.Body)
        if err != nil {
            log.Fatal(err)
        }

        doc.Find(".item").Each(func(index int, item *goquery.Selection) {
            title := item.Find(".title").Text()
            fmt.Println(título)
        })

        página++
    }
}

Tratamiento del contenido renderizado en JavaScript

Algunos sitios web utilizan JavaScript para mostrar contenido de forma dinámica. Go no tiene una forma incorporada de ejecutar JavaScript, pero puedes usar una directiva navegador sin cabeza como Chromedp.

go get -u github.com/chromedp/chromedp

Ejemplo de uso de Chromedp para scrapear contenido renderizado en JavaScript:

paquete principal

importar (
    "context"
    "fmt"
    "log"

    "github.com/chromedp/chromedp"
)

func main() {
    ctx, cancel := chromedp.NewContext(context.Background())
    aplazar cancelar()

    var htmlContenido cadena

    err := chromedp.Ejecutar(ctx,
        chromedp.Navegar("https://example.com"),
        chromedp.OuterHTML("body", &htmlContent),
    )
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(htmlContent)
}

Gestión de sesiones y cookies

Si un sitio web requiere inicio de sesión o gestión de sesiones, puede gestionar las cookies y las sesiones mediante http.CookieJar.

Ejemplo de gestión de cookies:

paquete principal

importar (
    "fmt"
    "log"
    "net/http"
    "net/http/cookiejar"

    "github.com/PuerkitoBio/goquery"
)

func main() {
    jar, _ := cookiejar.New(nil)
    client := &http.Client{Jar: jar}

    // Iniciar sesión y guardar cookies
    loginURL := "https://example.com/login"
    loginForm := url.Values{}
    loginForm.Set("nombre_usuario", "tu_nombre_usuario")
    loginForm.Set("contraseña", "tu_contraseña")

    res, err := client.PostForm(loginURL, loginForm)
    if err != nil {
        log.Fatal(err)
    }
    res.Body.Close()

    // Acceder a una página protegida
    url := "https://example.com/protected-page"
    res, err = client.Get(url)
    if err != nil {
        log.Fatal(err)
    }
    defer res.Body.Close()

    doc, err := goquery.NewDocumentFromReader(res.Body)
    if err != nil {
        log.Fatal(err)
    }

    doc.Find(".contenido-protegido").Each(func(index int, item *goquery.Selection) {
        contenido := item.Texto()
        fmt.Println(contenido)
    })
}

Estrangulamiento y limitación de velocidad

Para evitar que los sitios web te bloqueen, aplica la limitación de velocidad introduciendo retardos entre las solicitudes.

Ejemplo de limitación de velocidad:

paquete principal

importar (
    "fmt"
    "log"
    "net/http"
    "time"

    "github.com/PuerkitoBio/goquery"
)

func main() {
    urls := []cadena{"https://example.com/page1", "https://example.com/page2"}

    for _, url := rango urls {
        res, err := http.Get(url)
        if err != nil {
            log.Fatal(err)
        }
        defer res.Body.Close()

        doc, err := goquery.NewDocumentFromReader(res.Body)
        if err != nil {
            log.Fatal(err)
        }

        doc.Find(".item").Each(func(index int, item *goquery.Selection) {
            title := item.Find(".title").Text()
            fmt.Println(título)
        })

        // Retraso para evitar bloqueos
        time.Sleep(2 * time.Second)
    }
}

Gestión de solicitudes AJAX

Algunos sitios web cargan datos dinámicamente a través de peticiones AJAX. Puedes capturar y replicar estas solicitudes utilizando herramientas como las herramientas de desarrollo del navegador para encontrar los puntos finales de la API.

Ejemplo de obtención de datos desde un punto final de API AJAX:

paquete principal

import (
    "codificación/json
    "fmt"
    "log"
    "net/http"
)

type Artículo struct {
    Título string `json: "título"`
}

func main() {
    url := "https://example.com/api/items"

    res, err := http.Get(url)
    if err != nil {
        log.Fatal(err)
    }
    defer res.Body.Close()

    var items []Item
    if err := json.NewDecoder(res.Body).Decode(&items); err != nil {
        log.Fatal(err)
    }

    for _, item := rango items {
        fmt.Println(item.Title)
    }
}

Manejo de captchas y mecanismos anti-scraping

Los sitios web utilizan a menudo CAPTCHAs y otros mecanismos anti-scraping. Aunque resolver CAPTCHAs mediante programación es complejo y a menudo va en contra de los términos de servicio, puedes utilizar técnicas como agentes de usuario rotatorios y proxies para evitar ser detectado.

Ejemplo de rotación de agentes de usuario:

paquete principal

importar (
    "fmt"
    "log"
    "net/http
    "math/rand"
    "tiempo"
)

func main() {
    userAgents := []cadena{
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, como Gecko) Chrome/58.0.3029.110 Safari/537.3",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:54.0) Gecko/20100101 Firefox/54.0",
        // Añada más agentes de usuario aquí
    }

    client := &http.Client{}
    rand.Seed(time.Now().UnixNano())

    for i := 0; i < 5; i++ {
        req, err := http.NewRequest("GET", "https://example.com", nil)
        if err != nil {
            log.Fatal(err)
        }

        req.Header.Set("User-Agent", userAgents[rand.Intn(len(userAgents))])
        res, err := client.Do(req)
        if err != nil {
            log.Fatal(err)
        }
        res.Body.Close()

        fmt.Println("Solicitud enviada con user-agent:", req.Header.Get("User-Agent"))
    }
}

Uso de proxies

Para proteger aún más tu IP de los baneos, puedes utilizar proxies. Servicios como OkeyProxy o MacroProxy ofrecen soluciones de proxy.

Como uno de los mejores proveedores de proxy, OkeyProxy es compatible con HTTP/HTTPS/SOCKS y proporciona más de 150 millones de IPs residenciales reales, que cubren más de 200 países/áreas, lo que podría evitar la prohibición de IP en la medida de lo posible y garantiza la seguridad, fiabilidad y estabilidad de las conexiones de red.

okeyproxy

Ejemplo de utilización de un proxy para el raspado de datos con http.Client:

paquete principal

importar (
    "fmt"
    "log"
    "net/http"
    "net/url"
)

func main() {
    proxyURL, _ := url.Parse("http://proxyusername:proxypassword@proxyserver:puerto")
    transporte := &http.Transporte{
        Proxy: http.ProxyURL(proxyURL),
    }

    client := &http.Client{Transporte: transporte}

    res, err := client.Get("https://example.com")
    if err != nil {
        log.Fatal(err)
    }
    defer res.Body.Close()

    fmt.Println("Estado de la respuesta:", res.Status)
}

Raspado concurrente

Para acelerar el scraping, puede utilizar goroutines para manejar múltiples peticiones simultáneamente. Esto es útil para el scraping de grandes conjuntos de datos.

Ejemplo de raspado concurrente con goroutines:

paquete principal

importar (
    "fmt"
    "log"
    "net/http"
    "sync"

    "github.com/PuerkitoBio/goquery"
)

func scrape(url string, wg *sync.WaitGroup) {
    defer wg.Done()

    res, err := http.Get(url)
    if err != nil {
        log.Println(err)
        return
    }
    defer res.Body.Close()

    doc, err := goquery.NewDocumentFromReader(res.Body)
    if err != nil {
        log.Println(err)
        return
    }

    doc.Find(".item").Each(func(index int, item *goquery.Selection) {
        title := item.Find(".title").Text()
        fmt.Println(título)
    })
}

func main() {
    urls := []cadena{
        "https://example.com/page1",
        "https://example.com/page2",
        // Añadir más URLs
    }

    var wg sync.WaitGroup

    for _, url := rango urls {
        wg.Añadir(1)
        go scrape(url, &wg)
    }

    wg.Wait()
}

Extracción de datos de API

Muchos sitios web ofrecen API para acceder a los datos. El uso de API suele ser más sencillo y eficaz que el scraping HTML.

Ejemplo de llamada a una API:

paquete principal

import (
    "codificación/json
    "fmt"
    "log"
    "net/http"
)

func main() {
    url := "https://api.example.com/data"

    res, err := http.Get(url)
    if err != nil {
        log.Fatal(err)
    }
    defer res.Body.Close()

    var datos map[cadena]interfaz{}
    if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
        log.Fatal(err)
    }

    fmt.Println("Datos API:", datos)
}

Almacenamiento de datos

En función de sus necesidades, puede que necesite almacenar los datos obtenidos en una base de datos o en un archivo. He aquí un ejemplo de escritura de datos en un archivo CSV:

paquete principal

importar (
    "codificación/csv
    "fmt"
    "log"
    "os"
    "net/http"
    "github.com/PuerkitoBio/goquery"
)

func main() {
    file, err := os.Create("datos.csv")
    if err != nil {
        log.Fatal(err)
    }
    defer archivo.Cerrar()

    writer := csv.NewWriter(fichero)
    defer writer.Flush()

    urls := []cadena{"https://example.com/page1", "https://example.com/page2"}

    for _, url := rango urls {
        res, err := http.Get(url)
        if err != nil {
            log.Fatal(err)
        }
        defer res.Body.Close()

        doc, err := goquery.NewDocumentFromReader(res.Body)
        if err != nil {
            log.Fatal(err)
        }

        doc.Find(".item").Each(func(index int, item *goquery.Selection) {
            title := item.Find(".title").Text()
            writer.Write([]cadena{título})
        })
    }

    fmt.Println("Datos escritos en data.csv")
}

Gestión y registro de errores

La gestión de errores y el registro son esenciales para la resolución de problemas y el mantenimiento de los scrapers. Puede utilizar las capacidades de registro de Go o bibliotecas externas como logrus para el registro avanzado.

Bibliotecas esenciales para Web Scraping en Golang

  1. CollyInstalación: go get -u github.com/gocolly/colly
  2. GoqueryLibrería tipo jQuery para manipular y consultar HTML.Instalación: go get -u github.com/PuerkitoBio/goquery
  3. Solicitar:Cliente HTTP simplificado para realizar peticiones.Instalación: go get -u github.com/imroc/req
  4. Grequests:Biblioteca de peticiones HTTP de alto nivel, similar a Requests de Python.Instalación: go get -u github.com/levigross/grequests
  5. Cromadop:Automatización del navegador mediante el protocolo Chrome DevTools.Instalación: go get -u github.com/chromedp/chromedp
  6. Varilla:Moderna biblioteca de automatización de navegadores para Go, con énfasis en la facilidad de uso y las características modernas.Instalación: go get -u github.com/ysmood/rod
  7. Go-Selenium:Un cliente Selenium WebDriver para Go, útil para automatizar navegadores.Instalación: go get -u github.com/tebeka/selenium
  8. ScollyUna envoltura alrededor de Colly para simplificar el raspado web.Instalación: go get -u github.com/scolly/scolly
  9. BrowshotCliente Go de la API Browshot para realizar capturas de pantalla y extraer contenido de páginas web.Instalación: go get -u github.com/browshot/browshot-go
  10. Titiritero-goInstalación: go get -u github.com/chromedp/puppeteer-go
  11. Go-solicita:Sencilla biblioteca de peticiones HTTP inspirada en Requests de Python.Instalación: go get -u github.com/deckarep/golang-set
  12. Httpproxy:Un simple servidor proxy HTTP para Go, útil para enrutar el tráfico de web scraping.Instalación: go get -u github.com/henrylee2cn/httpproxy
  13. ArrastrándoseUna librería para construir rastreadores web distribuidos.Instalación: go get -u github.com/whyrusleeping/crawling
  14. K6Aunque se trata principalmente de una herramienta de pruebas de carga, K6 puede utilizarse para la extracción de datos web gracias a sus funciones de secuencias de comandos.Instalación: go get -u github.com/loadimpact/k6
  15. Red/http:La librería estándar para realizar peticiones HTTP en Go.Instalación: Incorporada con Go, no necesita instalación por separado.
  16. Goquery-html:Otra biblioteca de análisis sintáctico de HTML con mejoras basadas en Goquery.Instalación: go get -u github.com/PuerkitoBio/goquery-html
  17. Httpclient:Un cliente HTTP de alto nivel para Go, que ofrece funciones avanzadas de petición.Instalación: go get -u github.com/aymerick/raymond

Estas bibliotecas y herramientas cubren una amplia gama de funcionalidades, desde simples peticiones HTTP hasta la automatización completa del navegador, lo que las hace versátiles para diferentes necesidades de web scraping.

Resumen

La extracción de datos de la web con Golang ofrece varias ventajas, como la eficiencia del rendimiento y la facilidad de concurrencia. Las goroutines y canales ligeros de Go permiten manejar múltiples peticiones simultáneas con una sobrecarga mínima de recursos, lo que lo hace ideal para tareas de extracción de datos a gran escala. Además, la potente biblioteca estándar de Go soporta sólidas capacidades de análisis HTTP y HTML, lo que simplifica el desarrollo de aplicaciones de web scraping eficientes y fiables. Esta combinación de velocidad, concurrencia y herramientas integradas convierte a Golang en una opción convincente para proyectos de web scraping que requieren un alto rendimiento y escalabilidad.

Comentarios

No hay comentarios aún. ¿Por qué no comienzas el debate?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *