Web Scraping en Go
Tags: go, spanish, webscraping
Published: 2024-04-03 22:30:16

## Primeros pasos

En primer lugar debemos de tener instalado Go (1.22.0 o superior), [Instrucciones para descargar e instalar Go](https://go.dev/doc/install).

Creamos una nueva carpeta para el proyecto, nos movemos al directorio y ejecutamos el siguiente comando:

```bash
go mod init scraper
```

> 💡 El comando `go mod init` se utiliza para inicializar un nuevo módulo Go en el directorio donde se ejecuta y crea un archivo `go.mod` para rastrear las dependencias del código. [Gestión de dependencias](https://go.dev/doc/modules/managing-dependencies)
> 

Ahora instalemos `Colibri`:

```bash
go get github.com/gonzxlez/colibri
```

> 💡 Colibri es un paquete Go que nos permite rastrear y extraer datos estructurados en la web usando un conjuntos de reglas definidas en JSON. [Repositorio](https://github.com/gonzxlez/colibri)
> 

---

## Reglas de extracción

Definimos las reglas que usara colibri para extraer los datos que necesitamos. [Documentación](https://pkg.go.dev/github.com/gonzxlez/colibri#section-readme)

Vamos a realizar una petición HTTP a la URL [https://pkg.go.dev/search?q=xpath](https://pkg.go.dev/search?q=xpath) la cual contiene los resultados de una consulta de paquetes Go relacionados con xpath en [Go Packages](https://pkg.go.dev/).

Usando las herramientas de desarrollo incluidas en nuestro navegador web, podemos inspeccionar la estructura HTML de la página. [¿Cuáles son las herramientas de desarrollo del navegador?](https://developer.mozilla.org/es/docs/Learn/Common_questions/Tools_and_setup/What_are_browser_developer_tools)


![Captura de pantalla](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lz78pmcj0itfpx16mqdi.png)

```html
<div class="SearchSnippet">
   <div class="SearchSnippet-headerContainer">
      <h2>
         <a href="/github.com/antchfx/xpath" data-gtmc="search result" data-gtmv="0" data-test-id="snippet-title">
         xpath
         <span class="SearchSnippet-header-path">(github.com/antchfx/xpath)</span>
         </a>
      </h2>
   </div>
   <div class="SearchSnippet-infoLabel">
      <a href="/github.com/antchfx/xpath?tab=importedby" aria-label="Go to Imported By">
      <span class="go-textSubtle">Imported by </span><strong>143</strong>
      </a>
      <span class="go-textSubtle">|</span>
      <span class="go-textSubtle">
      <strong>v1.2.5</strong> published on <span data-test-id="snippet-published"><strong>Oct 26, 2023</strong></span>
      </span>
      <span class="go-textSubtle">|</span>
      <span data-test-id="snippet-license">
      <a href="/github.com/antchfx/xpath?tab=licenses" aria-label="Go to Licenses">
      MIT
      </a>
      </span>
   </div>
</div>
```
> Fragmento de la estructura HTML que representa un resultado de la consulta.
> 

Entonces necesitamos un selector “*packages”* que encontrará todos los elementos div en el HTML con la clase ***SearchSnippet***, de esos elementos un selector “*name”* tomará el texto del elemento ***a*** dentro de un elemento ***h2*** y un selector “*path”* tomará el valor del atributo ***href*** del elemento ***a*** dentro de un elemento ***h2***. En otras palabras, “*name”* tomará el nombre del paquete Go y “*path”* la ruta del paquete :)

```json
{
	"method": "GET",
	"url":    "https://pkg.go.dev/search?q=xpath",
	"timeout": 10000,
	"selectors": {
		"packages": {
			"expr": "div.SearchSnippet",
			"all": true,
			"type": "css",
			"selectors": {
				"name": "//h2/a/text()",
				"path": "//h2/a/@href"
			}
		}
	}
}
```

- **method:** especifica el método HTTP (GET, POST, PUT, ...).
- **url:** URL de la solicitud.
- **timeout:** límite de tiempo en milisegundos para la solicitud HTTP.
- **selectors:** selectores.
    - *“packages”***:**  es el nombre del selector.
        - **expr:** expresión del selector.
        - **all:** especifica que se deben encontrar todos los elementos que coincidan con la expresión.
        - **type:** el tipo de expresión, en este caso un selector CSS.
        - **selectors:** selectores anidados.
            - *“name”* y *“path”* son los nombre de los selectores y sus valores son expresiones, en este caso expresiones XPath.

---

## Código en Go

Estamos listos para crear un archivo `scraper.go`, importar los paquetes necesarios y definir la función `main`:

```go
package main

import (
	"encoding/json"
	"fmt"

	"github.com/gonzxlez/colibri"
	"github.com/gonzxlez/colibri/webextractor"
)

var rawRules = `{
	"method": "GET",
	"url":    "https://pkg.go.dev/search?q=xpath",
	"timeout": 10000,
	"selectors": {
		"packages": {
			"expr": "div.SearchSnippet",
			"all": true,
			"type": "css",
			"selectors": {
				"name": "//h2/a/text()",
				"path": "//h2/a/@href"
			}
		}
	}
}`

func main() {
	we, err := webextractor.New()
	if err != nil {
		panic(err)
	}

	var rules colibri.Rules
	err = json.Unmarshal([]byte(rawRules), &rules)
	if err != nil {
		panic(err)
	}

	output, err := we.Extract(&rules)
	if err != nil {
		panic(err)
	}

	fmt.Println("URL:", output.Response.URL())
	fmt.Println("Status code:", output.Response.StatusCode())
	fmt.Println("Content-Type", output.Response.Header().Get("Content-Type"))
	fmt.Println("Data:", output.Data)
}
```

> 💡 WebExtractor son interfaces predeterminadas para Colibri listas para comenzar a rastrear o extraer datos en la web.
> 

Usando la función New de webextractor, generamos una estructura [Colibri](https://pkg.go.dev/github.com/gonzxlez/colibri#Colibri) con lo necesario para comenzar a extraer datos.

Luego convertimos nuestras reglas en JSON a una estructura [Rules](https://pkg.go.dev/github.com/gonzxlez/colibri#Rules) y llamamos al método [Extract](https://pkg.go.dev/github.com/gonzxlez/colibri#Colibri.Extract)  enviando como argumento las reglas.

Obtenemos la salida y se imprimen en pantalla la URL de la respuesta HTTP, el código de estado HTTP,  el tipo de contenido de la respuesta y los datos extraídos con los selectores. Consulte la documentación de la estructura [Output](https://pkg.go.dev/github.com/gonzxlez/colibri#Output).

Ejecutamos el siguiente comando:

```bash
go mod tidy
```

> 💡 El comando `go mod tidy` se asegura de que las dependencias en el `go.mod` coinciden con el código fuente del módulo.
> 

Finalmente compilamos y ejecutamos nuestro código en Go con el comando:

```bash
go run scraper.go
```

---

## Conclusión

En este post, hemos aprendido cómo realizar Web Scraping en Go utilizando el paquete Colibri, definiendo reglas de extracción con selectores CSS y XPath. Colibri emerge como una herramienta para aquellos que buscan automatizar la recopilación de datos web en Go. Su enfoque basado en reglas y su facilidad de uso la convierten en una opción atractiva para desarrolladores de todos los niveles de experiencia.

En definitiva, el Web Scraping en Go es una técnica poderosa y versátil que puede utilizarse para extraer información de una amplia gama de sitios web. Es importante destacar que el Web Scraping debe realizarse de manera ética, respetando los términos y condiciones de los sitios web y evitando sobrecargar sus servidores.