DEV Community

Cover image for Scrapper Concorrente
ionnss
ionnss

Posted on

Scrapper Concorrente

N|Solid

Objetivo do programa

Acessar páginas web ao mesmo tempo para extrair o título de cada página e exibir esses títulos no terminal. Isso é feito utilizando concorrência em Go, que permite acessar várias páginas simultâneamente, economizando tempo.

Explicação do Código

Pacotes utilizados

import (
    "fmt"
    "net/http"
    "sync"
    "github.com/PuerkitoBio/goquery"
)
Enter fullscreen mode Exit fullscreen mode

Função fetchTitle

Essa função é reponsável por:

  • Acessar uma página web (url)
  • Extrair o título da página
  • Evniar o resultado para um canal
func fetchTitle(url string, wg *sync.WaitGroup, results chan<- string) {
    defer wg.Done() // Marca a goroutine como concluída no WaitGroup
Enter fullscreen mode Exit fullscreen mode

Parâmetros da função:

  • url string: Representa o endereço da página web (url) que vamos acessar para obter o título
  • wg *sync.WaitGroup: Pointeiro para um WaitGroup, que usamos para sincornizar o término de todas as tarefas (goroutines) que estão rodando ao mesmo tempo. O*indica que estamos passando um "enderço" para oWaitGroup` e não uma cópia dela.
  • results chan<- string: Este é um canal unidirecional que permite enviar strings para outra parte do programa. Ele é usado para passar resultados (títulos ou mensagens de erro) para a função main

A linha defer wg.Done() diz ao programa para marcar esta tarefa (goroutine) como concluída quando a função fetchTitle terminar. Isso é importante para que o main saiba quando todas as tarefas foram concluídas.

Requisição HTTP


req, err := http.Get(url)
if err != nil {
results <- fmt.Sprintf("Erro ao acessar %s: %v", url, err)
return
}
defer req.Body.Close()

  • http.Get(url): Esta linha faz um pedido HTTP GET para a URL. Isso significa que estamos acessando a página e pedindo ao servidor o conteúdo dela.
  • err != nil: Aqui verificamos se houve algum erro ao acessar a página (por exemplo, se a página não existe ou o servidor não está respondendo). Se houver erro, enviamos uma mensagem para o canal results e encerramos a função com return.
  • defer req.Body.Close(): Isso garante que, depois que terminarmos de usar o conteúdo da página, liberaremos a memória alocada para armazená-lo.

Verificação de Status


if req.StatusCode != 200 {
results <- fmt.Sprintf("Erro ao acessar %s: status %d %s", url, req.StatusCode, req.Status)
return
}

  • req.StatusCode != 200: Verificamos se o servidor respondeu com o código 200 OK (indica sucesso). Se não for 200, isso significa que a página não foi carregada corretamente. Então, enviamos uma mensagem de erro para o canal results e encerramos a função.

Carregamento e Busca do Título


doc, err := goquery.NewDocumentFromReader(req.Body)
if err != nil {
results <- fmt.Sprintf("Erro ao carregar documento de %s: %v", url, err)
return
}
title := doc.Find("title").Text()
results <- fmt.Sprintf("Título de %s: %s", url, title)
}

  • goquery.NewDocumentFromReader(req.Body): Carregamos o conteúdo HTML da página (fornecido por req.Body) no goquery, que permite navegar e buscar partes específicas do HTML.
  • doc.Find("title").Text(): Procuramos a tag <title> no HTML da página e pegamos o texto dentro dela (ou seja, o título).
  • results <- fmt.Sprintf("Título de %s: %s", url, title): Enviamos o título extraído para o canal results, onde ele será lido mais tarde.

Função main

A função main é a função principal que configura e controla o programa.


func main() {
urls := []string{
"http://olos.novagne.com.br/Olos/login.aspx?logout=true",
"http://sistema.novagne.com.br/novagne/",
}

  • urls := []string{...}: Definimos uma lista de URLs que queremos processar. Cada URL será passada para uma goroutine que extrairá o título da página.

Configuração do WaitGroup e do Canal


var wg sync.WaitGroup
results := make(chan string, len(urls)) // Canal para armazenar os resultados

  • var wg sync.WaitGroup: Criamos uma nova instância de WaitGroup, que controlará o número de goroutines e garantirá que todas terminem antes que o programa finalize.
  • results := make(chan string, len(urls)): Criamos um canal results com capacidade igual ao número de URLs. Esse canal armazenará as mensagens com os títulos ou erros.

Início das Goroutines


for _, url := range urls {
wg.Add(1)
go fetchTitle(url, &wg, results)
}

  • for _, url := range urls: Aqui, percorremos cada URL da lista.
  • wg.Add(1): Para cada URL, incrementamos o contador do WaitGroup para indicar que uma nova tarefa (goroutine) será iniciada.
  • go fetchTitle(url, &wg, results): Chamamos fetchTitle como uma goroutine para cada URL, ou seja, fazemos com que ela rode em paralelo com as outras.

Espera e Exibição dos Resultados


wg.Wait()
close(results)


REPO: https://github.com/ionnss/Scrapper-GoRoutine


ions,

mais um dia da terra

Top comments (0)