Collecter des données sur internet est une tâche courante dans le domaine commercial. Aller vérifier les prix de vos concurrents est une pratique de base pour conserver votre compétitivité. Cela peut être réalisé manuellement, mais quand la quantité d’informations devient importante, le temps passé à réaliser cette tâche n’est plus très productif. C’est la raison pour laquelle les robots (Bots, scrappers, crawlers, etc) ont été crées. Ces robot sont des programmes, écrit dans différents langages, ils ont pour but d’aller sur les sites internets pour récolter des informations de manière automatique.
Mais, avec leur très grande vélocité, bien au delà de ce qui est humainement possible de faire, ces robots surchargent les serveurs et, au delà de la volonté de protéger ses données, l’entreprise « cible » tente aussi de protéger ses serveurs. Les ingénieurs en charge des sites web ont donc déployé des parades pour contrer cette nuisance.
Voici un exemple. Sur le site monetas.ch, diverses informations sont disponibles comme par exemple des adresses email. Je vous engage par exemple à aller à cette adresse. Vous voyez apparaitre l’adresse email de cette entreprise, mais comme le montrent les deux portions de code R suivants, l’information n’est pas « visible » dans le code source de la page internet cible et n’est donc pas récoltée.
1 2 3 4 5 6 7 8 9 |
library(rvest) URL <- "http://www.monetas.ch/htm/660/fr/Contact-Roger-Claude-Choffat.htm?subj=2022352" search <- html(URL) A <- html_nodes(search, "div div div div ul li li a") B <- html_text(A) # Résultat: # [1] "dcw('CQxXXlUJFyoFVV9HAQVIEA0=')" |
ou,
1 2 3 4 5 6 7 8 9 10 11 12 |
library(RCurl) library(XML) URL <- "http://www.monetas.ch/htm/660/fr/Contact-Roger-Claude-Choffat.htm?subj=2022352" data <- getURL(URL, ssl.verifypeer = FALSE, encoding="UTF-8") data_parsed <- htmlTreeParse(data, encoding = 'UTF-8') parsed_lines <- capture.output(data_parsed) grep("[a-zA-Z]{1,}@[a-zA-Z]{1,}.[a-zA-Z]{1,}", parsed_lines) # Résultat: # integer(0) |
Aucun résultat!
Dans la page web, il y a en fait un script qui en s’exécutant, affiche l’adresse mail. Les portions de code R, eux ne voient que le script, pas le résultat de son exécution. C’est une parade simple et relativement efficace.
Mais comme souvent, une solution, enfin de multiples solutions existent pour contourner cette pratique. Il faut transformer le comportement du « robot » (ici le code R) en un comportement humain. C’est possible ! Quand des portions de code comme précédemment utilisées sont vues telles quelles par le site « cible », la solution que l’on va utiliser pour contourner cette parade « ne montre que » votre navigateur internet.
Je m’explique: à ce stade, en se basant sur R, deux options s’offrent à vous: utiliser votre navigateur internet préféré (chrome, firefox, safari, etc…) ou phantomjs. Phantomjs ne vous parle pas? C’est normal, vous n’allez pas l’utiliser pour aller regarder votre page facebook, phantomjs n’affiche rien. Phantomjs navigue sur le net, il fait un rendu de toute une page internet, il stock ce rendu dans la mémoire de votre ordinateur, mais ne vous propose aucune visualisation de celle-ci. L’intérêt? Si vous cherchez un gain de temps (la productivité), ne pas avoir à afficher une page internet vous en fait gagner, du temps. C’est la différence majeure avec les autres navigateurs.
Dans la pratique que doit-on faire: sur mac, comme c’est mon cas, j’utilise homebrew pour mes installations en lignes de commande via le Terminal. Si vous avez déjà installé homebrew, phantomjs s’installe avec la ligne de commande suivante:
1 |
brew install phantomjs |
Il vous faut ensuite aller télécharger sélénium, l’outil qui va permettre de poursuivre notre quête d’information (ici une adresse email). J’utilise pour ma part une ancienne version: selenium-server-standalone-2.53.1.jar.
Je place le fichier .jar où je le souhaite, le chemin ici est le suivant Users > admin.
De retour sur le Terminal, nous lançons le serveur sélénium. Cette étape est à réaliser à chaque fois que vous voulez faire de la récolte sur internet avec sélénium, depuis R.
1 2 |
cd /Users/admin java -jar selenium-server-standalone-2.53.1.jar |
In fine vous devez voir apparaitre dans le Terminal l’information suivante:
1 |
09:48:11.903 INFO - Selenium Server is up and running |
De retour dans R, nous lançons la récolte de données:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
library(RSelenium) library(stringr) # A la place de "phantomjs" vous pourriez utiliser "chrome" remDr <- remoteDriver(browserName = "phantomjs") remDr$open() #[1] "Connecting to remote server" #$platform #[1] "OS X 10.11" #$acceptSslCerts #[1] FALSE #$javascriptEnabled #[1] TRUE #$browserName #[1] "phantomjs" #... URL <- "http://www.monetas.ch/htm/660/fr/Contact-Roger-Claude-Choffat.htm?subj=2022352" remDr$navigate( URL) webElem <- remDr$findElement(using='xpath', value='//*[@id="content"]/div/div[2]/div[2]/ul/li[2]/ul/li[2]//a') elemtxt <- unlist(webElem $getElementAttribute("outerHTML")) Splitted4Email <- unlist(str_split(elemtxt, "[\\\\< \\\\>]")) Splitted4Email [grep("@", Splitted4Email)] # Résultat: # [1] "choffat@valtra.ch" |
L’information que l’on recherche s’affiche comme résultat de ce code. Notez toutefois que la démarche est plutôt lente. De plus, si le site « cible » cherche à se préserver de toute « intrusion » trop importante, vous devriez prendre ce comportement comme un « avertissement » lorsque vous interagissez avec lui. Si vous lancez de nombreuses requêtes sur ce site via une boucle dans R par exemple, vous pourriez ralentir de manière aléatoire votre visite de leurs pages internets afin de ne pas surcharger leur serveur (au passage votre robot sera plus « humain », vous limitez ainsi les chances que votre adresse IP ne soit bloquée). Voici un code à insérer à la fin de votre boucle générant les requêtes répétées sur le site « cible ». Ce code indique à R de patienter entre 2 et 5 secondes entre chaque requête:
1 |
Sys.sleep(runif(1, 2, 5)) |
Enfin, et ce n’est pas à négliger dans ce type de démarche de collecte d’informations, allez lire les conditions générales de ventes et particulièrement les aspects juridiques du site cible. On les trouve en bas de page généralement. Reconstituer une base de donnée propriétaire à des fins commerciales n’est pas une bonne idée!
NB: Sélénium, est utilisé ici de manière extrêmement simple. Il peut toutefois être utilisé pour des collectes beaucoup plus complexes comme soumettre une requête de recherche comme vous pourriez le faire sur google et traiter le contenu affiché suite à cette recherche. Les possibilités sont immenses!
Bon webscrapping!
Update: si vous vous trouvez face à une erreur de ce type en voulant lancer le serveur sélénium:
Exception in thread « main » java.lang.UnsupportedClassVersionError: org/openqa/gr
id/selenium/GridLauncher : Unsupported major.minor version 51.0
Vous devez faire une update de java, plus précisément le JDK (et potentiellement le JRE):
Solution trouvée ici.