Introduction au web scraping

Magazine
Marque
Linux Pratique
Numéro
84
Mois de parution
juillet 2014
Domaines


Résumé
Extraction de données, configuration d'équipements réseau, bots, hacking, …, le web scraping est utilisé dans de nombreux domaines. Aspect légal, scripting, sécurisation serveur, cet article vous explique tout.

Body

1. Présentation du web scraping

À l'heure de l'open et du big data, la collecte de données (textes, images, fichiers hébergés) sur Internet devrait dans les années à venir être au centre de toutes les considérations. Référencement, collecte d'informations, provisioning et configuration d'équipements réseau, hacking, bots, le web scraping ou screen scraping est apparu au cours des années 90 dans un certain flou juridique.

1.1 Web scraping, une technique illégale ?

Malheureusement, depuis sa création, la popularité du web scraping s'est effectuée au travers de nombreuses affaires juridiques plutôt que pour ses aspects techniques. En 2008, Ryan Air gagna un procès à la cour de Hambourg contre le tour opérateur Vtours dans le cadre d'extractions de données (horaires des vols et tarifs) jugées illégales. Depuis ce jour, la compagnie ne lésine pas sur le développement de techniques permettant le barrage de toute tentative de scraping. En France, le site d'annonces immobilières « De Particulier à Particulier » a fait condamner quant à lui plusieurs entreprises dans le cadre d'atteinte aux droits de « producteur de sa base de données ».

Le web scraping serait donc une technique de cyber voyous ? Heureusement non ! De nombreuses entreprises et projets open source utilisent cette technique, tels que OpenStreetMap, WP Rocket, le Medialabde Sciences Po Paris, ainsi que plus généralement, des comparateurs de prix et autres réseaux sociaux.

1.2 Aspect légal ?

Quand est-il en France ?

Au titre de l'article L341-1 de la propriété intellectuelle, vous encourez jusqu’à 300 000 euros d'amende et 3 ans d'emprisonnement pour l'utilisation et l'extraction illégale de contenus. Cet article devrait toutefois apparaître dans les conditions générales d'utilisation du site, les fameuses CGU. Plus généralement, d'autres données telles que des données textuelles et images sont également soumises aux droits d'auteur.

1.3 Quel outil pour scraper ?

Que ce soit sous la forme de librairies (WWW::Mechanize en Perl, Ruby et Python, Simple HTML DOM Parser en PHP) ou de frameworks (Scrapy en Python), il existe de nombreuses solutions de scraping. Dans cet article, nous utiliserons la librairie WWW::Mechanize accompagnée du langage Perl et le serveur Selenium Remote Control en langage Java, associé lui-même à la librairie WWW::Selenium, toujours en langage Perl.

2. Le web scraping avec Mechanize et Selenium

2.1 Topologie de page web

Avant de scraper vos premières données, il est préférable d'étudier la topologie et la complexité de la page. Posez-vous les questions suivantes : votre page contient-elle une authentification HTTP ? Du JavaScript ? Des cookies ?

Comme nous allons le voir, il existe une méthode pour chacune de ces réponses.

2.2 WWW::Mechanize, une librairie dédiée au scraping

WWW::Mechanize est une librairie Perl permettant de scraper du contenu web très simplement.

2.2.1 Installation

Deux possibilités s'offrent à vous dans l'installation du package :

- via le CPAN :

cpan install WWW::Mechanize

- via les dépôts de votre distribution Debian ou dérivée :

apt-get install libwww-mechanize-perl

Afin de vérifier que votre module est bien installé, exécutez la commande :

perl -e 'use WWW::mechanize'

Si cette commande ne renvoie aucun retour, c'est qu'il est installé.

2.2.2 Développement du script « scraping.pl »

Notre librairie est maintenant installée ; créons notre premier script, que nous appellerons scraping.pl. Ce script aura pour fonction de récupérer le contenu d'une page cible. Dans notre exemple, la page cible sera la page d'accueil du site www.unixgarden.com.

#!/usr/bin/perl

use strict;

use warnings;

use www::mechanize;

use Data::Dumper;

#Définition de l'URL

my $url = 'http://www.unixgarden.com/';

#Instanciation de l'objet mech

#Définition du user agent « Mozilla Firefox, sous OS Linux »

#Mise en mémoire du cookie

my $mech = WWW::Mechanize->new(

 agent => 'Mozilla/4.73 [en] (X11; I; Linux 2.2.16 i686; Nav)',

 cookie_jar => {}

 );

#Création de la requête HTTP GET

my $result = $mech->get($url);

#Test de la réponse HTTP,

#Si différente de 200, le script s’arrête et affiche 'Erreur de la réponse HTTP GET'

die "Erreur de la reponse HTTP GET" unless $result->is_success;

#Récupération et affichage du code de la page

print Dumper($mech->content());

Dans cette première partie, nous effectuons donc une requête vers une URL, puis nous affichons le code source récupéré.

Sachez qu'il est également possible de récupérer uniquement le texte de la page avec :

$mech->text();

Ou bien son titre :

$mech->title();

Il est également possible d'afficher l'ensemble des liens de la page :

$mech->links();

Le code HTTP de la réponse :

$mech->status;

La liste des formulaires présents  :

$mech->forms;

Mechanize permet même de s'authentifier au travers de la méthode credentials :

$mech->credentials($login,$password) ;

Comme nous l'avons vu, il est assez facile d'extraire et de traiter des données.

Associez ce script à l'utilitaire wget et à quelques expressions régulières pour filtrer les données, et vous obtiendrez un robot vous permettant de télécharger en masse des données dans les méandres d'Internet. Cependant, Mechanize a une faiblesse majeure qui est de ne pas supporter JavaScript.

2.3 Aller plus loin dans le web scraping avec Selenium Remote Control

Basé sur une architecture client-serveur, Selenium Remote Control permet un scraping plus proche de l'expérience utilisateur. Survol de souris, clic droit, scrolling et j'en passe, de nombreuses options sont disponibles.

Le principe est simple : le client va envoyer des requêtes au serveur Selenium qui exécutera une instance du navigateur choisi (Firefox, Chrome ou Internet Explorer pour les plateformes Windows) et récupérera le résultat.

Notez également que dans l'exemple suivant, vous verrez votre navigateur s'ouvrir et afficher les pages à l’exécution du script. Sachez qu'il est possible de « bufferiser » les pages en mémoire, grâce à l'utilitaire xvfb (X virtual framebuffer) ; c'est d'ailleurs conseillé dans le cadre d'une mise en production d'un script de scraping sur des serveurs utilisant le runlevel 2 (sans serveur X).

Dans les exemples ci-dessous, le client sera notre script Perl utilisant la librairie WWW::Selenium. Le serveur, quant à lui, sera une archive .jar exécutée en mode standalone.

conf

2.3.1 Installation

Comme pour WWW::Mechanize, vous avez deux possibilités :

- via le CPAN :

cpan install WWW::Selenium

- via les dépôts de votre distribution Debian ou dérivée :

apt-get install libtest-www-selenium-perl

Et comme pour le module Mechanize, vérifions si notre module est bien installé :

perl -e 'use WWW::Selenium'

Installons maintenant notre serveur Selenium Remote Control.

On commence par installer Java :

apt-get install openjdk7-jre

Puis, on télécharge l'archive à l'adresse http://docs.seleniumhq.org/projects/remote-control/.

Pour lancer le serveur, ouvrez un terminal et lancez la commande :

java -jar selenium-server-standalone-x.xx.x.jar &

2.3.2 Développement du client

Ouvrez un second terminal pour écrire le client.

#!/usr/bin/perl

use strict;

use warnings;

use Data::Dumper;

use WWW::Selenium;

my $url = 'http://linuxfr.org';

# Création de l'objet Selenium

my $sel = WWW::Selenium->new( host => "localhost",

port => 4444,

browser => "*firefox",

browser_url => $url,

http_method => "POST"

);

$sel->start;

$sel->open($url);

# Définition de la rapidité d'affichage

$sel->set_speed(500);

# Temps d'attente de chargement de la page

$sel->wait_for_page_to_load(10000);

# Récupération de la source

my $page = $sel->get_html_source;

print Dumper($page);

$sel->stop;

Comme nous l'avons vu, notre client va envoyer ses requêtes sur le port 4444. L'instance de notre navigateur sera ici Firefox, il faut donc bien sûr qu'il soit installé sur votre machine. La méthode HTTP sera ici POST ; il est bien sûr possible d'utiliser une méthode de type GET.

2.3.3 Gestion des formulaires avec Selenium

Dans ce second exemple, nous allons prendre le cas d'une page contenant un formulaire, que nous allons valider après avoir renseigné des champs.

Il existe deux notions de validation dans Selenium : la première, en ciblant le nom du formulaire au travers de la méthode submit('nomduformulaire'). La seconde, en cliquant sur le bouton de validation grâce à la méthode click('valeur_name_du_bouton'). Notez qu'il est également possible de cibler un élément au travers de son arborescence CSS.

#!/usr/bin/perl

use strict;

use warnings;

use Data::Dumper;

use WWW::Selenium;

my $url = 'http://www.unixgarden.com';

# Création de l'objet Selenium

my $sel = WWW::Selenium->new( host => "localhost",

port => 4444,

browser => "*firefox",

browser_url => $url,

http_method => "POST"

);

$sel->start;

$sel->open($url);

# Setting du champ avec la valeur name à 's' du formulaire avec la valeur Linux

$sel->type("s","Linux");

# Clic du bouton, ici pour l'exemple nous ciblons sur le DOM CSS de l’élément

$sel->click("css=input.bouton.padding2");

# On attend le chargement de la page suivante

$sel->wait_for_page_to_load(10000);

my $page = $sel->get_html_source;

$sel->stop;

À l’exécution du script, vous ne devriez pas voir la valeur « Linux » apparaître dans le formulaire. Si vous souhaitez voir la valeur, il faut utiliser la méthode type_keys('s','Linux');.

2.3.4 Options et restrictions avec Selenium Remote Control

Comme Mechanize, Selenium permet de récupérer le texte de la page :

$sel->get_body_text();

Le titre de la page :

$sel->get_title();

La valeur d'un élément texte en particulier ($element ici désignant l’élément cible) :

$sel->get_text($element);

Et permet de vérifier si un élément checkbox est coché :

$sel->is_checked($element);

Concernant les restrictions, Selenium permet de récupérer le contenu des alertes et autres prompts, mais uniquement après l'affichage de l'élément. En effet, Selenium ne supporte pas en direct le JavaScript.

Pour cela, trois méthodes sont disponibles :

Pour les alertes :

$sel->get_alert();

Pour les pop-up :

$sel->get_prompt();

Pour les fenêtres de confirmation :

$sel->get_confirmation();

3. Comment se prémunir contre le web scraping ?

La principale difficulté est de déterminer parmi les visiteurs qui est un robot et qui est un utilisateur « réel ». Cependant, attention à ne pas bloquer l'ensemble des robots (y compris ceux d'indexation), cette action aurait un impact conséquent dans le référencement de votre site !

Les exemples suivants utilisent le serveur web Apache 2 et le package Fail2Ban sur une distribution Debian :

apt-get install apache2-server;

apt-get Fail2ban;

3.1 Honeypot ou la technique dite du « pot de miel »

La première technique, intitulée « pot de miel », consiste en la détection du chargement d'une page spécifique que nous appellerons pot.html.

1. Créez une page pot.html vide.

2. Dans les pages de votre site, ajoutez plusieurs liens non visibles par un visiteur humain pointant vers la page pot.html.

<a href="pot.html" style="display:none;">monlien</a>

3. Interdisez ensuite aux robots d'indexation de visiter la page dans le fichier Robots.txt.

User-Agent: Googlebot, Bingbot

Disallow: pot.html

4. Puis, pour finir, vous allez créer un nouveau filtre afin de permettre à Fail2Ban de détecter notre tentative de scraping :

vi /etc/fail2ban/filter.d/apache-webscrapping.conf

[Definition]

failregex = #Définissez ici votre expression régulière

ignoreregex =

Ajoutez une jail au fichier /etc/fail2ban/jail.conf permettant de bannir les adresses IP détectées :

[apache-webscrapping]

enabled = true

filter = apache-webscrapping

action = hostsdeny

#ban IP address outright

action = iptables-allports

#define which logs to search

logpath = /var/log/apache2/access.log

#end apache-webscrapping section

Redémarrez le service :

service fail2ban reload

Puis, vérifiez que la jail ait bien prise en compte :

fail2ban-client status apache-webscrapping

Ce qui devrait retourner :

Status for the jail: apache-webscrapping

|- filter

| |- File list: /var/log/apache2/access.log

| |- Currently failed: 0

| `- Total failed: 0

`- action

|- Currently banned: 0

| `- IP list:

`- Total banned: 0

Affichez votre page pot.html dans votre navigateur. L'appel apparaîtra dans le fichier de log /var/log/apache2/access.log :

127.0.0.1 - - [02/Apr/2014:21:42:16 +0200] "GET /test/pot.html HTTP/1.1" 200 280 "-" "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:22.0) Gecko/20100101 Firefox/22.0"

3.2 Détection du temps de consultation

Une autre pratique consiste en la mise en place d'un seuil de sollicitation de votre site, dans un délai que vous aurez défini ; par exemple : bloquer les adresses IP ayant consulté votre site plus de 150 fois dans un délai de 60 secondes.

Cependant, veillez dans ce cas à ajouter les adresses IP des robots Googlebot et Bingbot dans une « white list » (liste blanche), afin de ne pas bloquer l'indexation de votre site !

Notez au passage que cette pratique est également utilisée dans la détection d'attaques DDOS, ou plus généralement de flooding.

Vous utilisez ici le module Apache 2 mod_evasive :

apt-get install libapache2-mod-evasive

Éditez le fichier de configuration d'Apache /etc/apache2/apache.conf et ajoutez :

# mod_evasive

<IfModule mod_evasive20.c>

DOSHashTableSize 3097

DOSSiteCount 50

DOSSiteInterval 2

DOSBlockingPeriod 300

DOSEmailNotify "votre@contactemail"

DOSLogDir "/var/log/mod_evasive/"

DOSSystemCommand "/sbin/iptables -I INPUT -s %s -j DROP -m comment –comment 'BAN WEB SCRAPPING'"

DOSWhiteList 127.0.0.1

DOSWhitelist a.b.c.* #Ajouter ici les adresses des bots à ne pas bloquer

</IfModule>

DOSSiteCount définit le nombre de fois où un site peut être demandé par la même adresse IP avant que celle-ci soit bloquée.
DOSSiteInterval détermine un intervalle en secondes qui autorise l’affichage d’un même site avant le blocage.
DOSBlockingPeriod détermine la durée de blocage.
DOSEmailNotify détermine l'e-mail à contacter dans le cas de chaque blocage d’adresse IP.
DOSSystemCommand permet de définir la commande de blocage iptables.
DOSLogDir détermine le chemin où seront stockées les détections.
DOSWhiteListe définit une liste blanche d’adresses IP.

N'oubliez pas de créer votre dossier :

mkdir /var/log/mod_evasive/

Activez le mod_evasive :

a2enmod mod-evasive

Pour finir, au-delà de toute installation, le conseil le plus simple serait bien sûr de ne pas permettre l'indexation de vos dossiers pour ainsi ne pas vous faire aspirer l'ensemble de vos données !

Conclusion

Les possibilités du web scraping, comme nous l'avons vu, sont sans fin. Les entreprises l'ayant vite intégré dans leur process de production et de veille concurrentielle, il apparaît depuis plusieurs mois des annonces intitulées « Responsable Web Scraping » ou encore « Ingénieur Web Scraper » sur les sites d'annonces d'emplois spécialisés. De même, nous pouvons noter une large utilisation de cette technique dans le domaine du « data journalism », journalisme 2.0 où journalistes et développeurs collaborent dans l’agrégation de flux de données dans le but de produire des applications pour les lecteurs. Ce fut notamment le cas lors des différentes échéances politiques des trois dernières années. Et vous, quelle est votre utilisation du web scraping ?




Articles qui pourraient vous intéresser...

Notes : commentez votre navigation sur le Web

Magazine
Marque
Linux Pratique
Numéro
121
Mois de parution
septembre 2020
Domaines
Résumé

Développée par Mozilla Firefox, Notes est une extension pour votre navigateur web qui va ajouter un panneau latéral dans ce dernier afin que vous puissiez y apporter vos annotations lors de vos explorations sur la Toile.

Clippings : gagnez du temps avec votre presse-papier intelligent

Magazine
Marque
Linux Pratique
Numéro
120
Mois de parution
juillet 2020
Domaines
Résumé

À n’en pas douter, Clippings vous fera gagner un temps non négligeable en vous évitant de retaper les mêmes formulations/textes plusieurs fois dans vos mails (à noter que le module est compatible avec le client mail Thunderbird), billets et dans les divers formulaires que vous pourrez rencontrer en ligne. On peut imaginer cette extension comme un « presse-papier intelligent ».