Développez facilement un web spider en go

Un collecteur (ou crawler) est un logiciel qui explore automatiquement le Web. Souvent dans le but d'indexer les ressources qu'il trouve dans un moteur de recherche. Il peut être également intéressant de développer un crawler afin de vérifier qu'un site respecte des règles de contenu (style, règles éditoriales...) ou qu'il ne contienne pas d'erreurs (URL introuvable, parties manquantes, etc.). Dans cet article, nous verrons comment en développer ce type de vérificateur à l'aide de la bibliothèque tierce gocrawl.

Cas d'usage

Nous allons développer un vérificateur qui a pour but de valider un site avec les règles suivantes, pour toutes les pages web analysées :

  1. La balise META description doit être renseignée.
  2. Il doit y avoir au moins une balise H1.

Notre crawler sera lancé via la ligne de commande et indiquera les erreurs rencontrées au fil de son analyse.

Solution technique : gocrawl

La bibliothèque tierce gocrawl permet de créer le mécanisme de recherche récursive à partir d'une URL (le crawler), mais également des fonctions permettant d'examiner le contenu récupéré. Elle s'appuie pour cela sur les bibliothèques tierces suivantes :

  • robotstxt-go qui implémente le protocole d'exclusion des robots basé sur le fichier robots.txt
  • purell qui permet de normaliser les URL.
  • goquery qui permet de faire des requêtes sur un document HTML à la manière de jQuery.
  • cascadia est une dépendance de goquery et elle permet de faire des requêtes sur les feuilles de style.
  • go.net/html Le paquet expérimental (maintenu par l'équipe go) qui complétera un jour (peut être) la bibliothèque standard.

Durant l'analyse du contenu, on pourrait aussi s'appuyer sur la bibliothèque go standard (tels que les paquets net/http, net/url ou regexp).

Installation

Le gestionnaire de paquet intégré à Go récupèrera toutes les dépendances à l'aide des commandes d'installation et de compilation suivantes :

go get github.com/PuerkitoBio/gocrawl
go install github.com/PuerkitoBio/gocrawl

Exemple de code

Voici le code complet de notre vérificateur de site :

package main

import (
	"github.com/PuerkitoBio/gocrawl"
	"github.com/PuerkitoBio/goquery"
	"net/http"
	"time"
	"fmt"
)

type goCrawlExtender struct {
  gocrawl.DefaultExtender
}

func (this *goCrawlExtender) Visit(ctx *gocrawl.URLContext, res *http.Response, doc *goquery.Document) (interface{}, bool) {
	fmt.Printf("url : %s\n", ctx.URL().String())
	if val, ok := doc.Find("meta[name='description']").Attr("content"); !ok {
		fmt.Println("Pas de description ")
	} else {
		if val == "" {
			fmt.Println("Balise META description présente, mais champ vide")
		} else {
			fmt.Printf("description : %s\n", val)
		}
	}

	if len(doc.Find("h1").Nodes) == 0  {
		fmt.Println("Pas de H1")
	} else {
		fmt.Println("Au moins un H1")
	}

	return nil, true
}

func main() {
	opts := gocrawl.NewOptions(new(goCrawlExtender))
	opts.CrawlDelay = 1 * time.Second
	opts.LogFlags = gocrawl.LogAll
	opts.MaxVisits = 2
	c := gocrawl.NewCrawlerWithOptions(opts)
	c.Run("http://localhost/ionize/")
}

Commentaires à propos du code

La fonction Visit

La fonction Visit est une surcharge appelée par la bibliothèque gocrawl à chaque fois qu'elle télécharge une page dans le cadre de son parcours récursif d'un site analysé. Ce qu'il y a de bien, c'est la bibliothèque goquery qui permet de faire des requêtes dans le document HTML téléchargé avec la même syntaxe que jQuery. Par exemple :

  • doc.Find("meta[name='description']").Attr("content") créé une liste des valeurs de l'attribut content de toutes les balises HTML meta dont l'attribut name a pour valeur "description"
  • doc.Find("h1").Nodes créé une liste des balises HTML H1

Initialisation et lancement de la collecte

La bibliothèque gocrawl possède plusieurs options. On peut, par exemple, régler le stress infligé au site analysé avec l'option CrawlDelay. La fonction c.Run("http://localhost/ionize/") ne fait pas appel à une goroutine : elle parcourt toutes les pages du site (sauf que nous nous sommes limités dans cet exemple à un maximum de deux pages avec l'option MaxVisits), puis rend la main (après avoir exécuté la fonction End ou la fonction surchargée).

Les autres options et possibilités de surcharge sont résumées dans le paragraphe suivant.

Synthèse de la documentation disponible

La documentation complète se trouve sur la page du projet (en anglais). Les tableaux ci-dessous ne sont qu'une synthèse des possibilités.

Options du collecteur

ParamètreDescription
UserAgentUserAgent utilisé pour récupérer la page (c.-à-d. ce qui apparaîtra dans les logs du serveur). Firefox 15 par défaut
RobotUserAgentUserAgent utilisé pour interroger le fichier robots. Voir les spécifications ici. Google bot par défaut.
MaxVisitsNombre maximal de pages à collecter
EnqueueChanBufferTaille du buffer des pages supplémentaires à analyser
HostBufferFactorFacteur ou nombre de goroutine concurrentes collectant des pages. Par défaut, 10 fois le nombre d'hôtes différents.
CrawlDelayDélai entre deux récupérations de page et par hôte. 5 secondes par défaut.
WorkerIdleTTLDurée de vie de la connexion lorsque le collecteur est inactif. 10 secondes par défaut.
SameHostOnlyNe pas collecter les pages externes. Vrai par défaut.
HeadBeforeGetDemander des informations sur la ressource avant de demander la ressource elle-même. Faux par défaut.
URLNormalizationFlagsOptions à passer à la bibliothèque purell.
LogFlagsNiveau de verbosité des logs.
ExtenderInterface permettant d'implémenter les callbacks de la bibliothèque gocrawl (voir le paragraphe suivant).
Les options de la bibliothèque gocrawl

Fonctions pouvant être surchargées

FonctionDescription
StartAppelée quand le collecteur démarre (par la fonction Run)
EndInvoquée quand le collecteur s'arrête
ErrorDéclenchée à chaque erreur. Les erreurs ne stoppent pas le processus de collecte.
LogDéclenchée à chaque fois qu'un message de log est ajouté ; quel que soit le niveau de verbosité.
ComputeDelayAppelée juste avant la collecte (Fetch) d'une ressource.
FetchAppelée après l'obtention des informations sur une ressource (cf. HeadBeforeGet).
RequestGetPermet de déterminer si le collecteur doit récupérer une ressource ou pas (en fonction du résultat du HEAD sur la ressource).
RequestRobotsPermet de déterminer si le fichier robotos.txt doit être récupéré ou pas.
FetchedRobotsAppelée lorsque le fichier robotos.txt a été récupéré.
FilterFiltre de visite. C'est par exemple dans cette fonction que l'on pourrait ne s'intéresser qu'à certains types d'extensions de fichier ou seulement aux ressources respectant une certaine structure d'URL.
EnqueuedDéclenchée lorsqu'une ressource est insérée dans la file d'attente pour analyse.
VisitInvoquée après avoir téléchargé une ressource, afin de l'analyse.
VisitedAppelée après avoir visité une ressource.
DisallowedDéclenchée lorsqu'une URL ne peut être atteinte à cause d'une règle dans le fichier robots.txt.
Les fonctions qui peuvent être surchargées

Étiquettes :   html   thirdparty 
Portrait de Benjamin BALET
Benjamin BALET
Consultant APM

Retrouvez mes cooordonées

Benjamin BALET sur viadeo






Vous aimerez aussi

Les lois de la réflexion

Une traduction du blog officiel de golang expliquant le mécanisme de la réflexion en Go.   Lire »

Gobs le format natif d'échange de données en Go

Traduction d'un article du blog officiel expliquant comment échanger des données entre deux programmes golang grâce à un format natif   Lire »

Comment écrire du code Go ?

Traduction d'une partie des spécifications officielles du langage Go, cet article explique comment développer en Go.   Lire »

Comment gérer efficacement les erreurs en golang ?

Préconisations officielles pour la gestion des erreurs dans un programme golang. Cet article complète les explications sur panic, defer et recover   Lire »

Le modèle mémoire du runtime et du langage go

Traduction d'une partie des spécifications officielles du langage go, cet article explique comment go gère la mémoire.   Lire »

Commentaires

Soyez le premier à commenter cet article

Publier un commentaires

Tous les commentaires sont soumis à modération. Les balises HTML sont pour la plupart autorisées. Les liens contextuels et intéressants sont en follow.

(requis)
(requis)
(requis, mais non publié)
(recommandé si vous souhaitez être publié)