Jean-Hugues Roy

Expériences | réflexions | scrapbook

Élections 2015: palmarès du «scraping»

Il est devenu coutume, quand approchent des élections, de comparer les sites web des partis, leur présence sur les réseaux sociaux, etc. J’ai fait un banc d’essai avec une «question de recherche» qui est, je le crois bien, inédite:

quel est le parti dont le site est le mieux fait pour faire du scraping, pour en extraire de l’information?

J’ai donc rédigé cinq scripts pour extraire quelques données des sites web des cinq principaux partis politiques qui participeront à l’élection fédérale du 19 octobre prochain: une simple liste de candidats en format CSV avec leur nom, leur circonscription, leur province, et des infos de contact. J’ai aussi inclus une minuterie dans mes scripts: je prends l’heure quand le script commence et la prends à nouveau quand il arrête, puis je fais la différence entre les deux. Voici les résultats:

NPD : 1,9 secondes

La page des candidats du Nouveau parti démocratique est un charme à scraper. Tout est accessible rapidement et tient en une seule page web. Bref, c’est un site conçu pour faciliter la diffusion de l’information.

Inspection NPD

Bloc québécois : 3,6 secondes

Si la page des candidats du Bloc prend si peu de temps à extraire, c’est en grande partie en raison du fait qu’elle contient beaucoup moins de candidats que les autres partis. Non seulement le Bloc n’est présent qu’au Québec, mais il est encore loin d’avoir des candidats dans les 78 circonscriptions de la province.

Le site du Bloc comporte néanmoins une difficulté. Tous les candidats n’apparaissent pas dans la page. Pour les avoir tous, il faut soit faire défiler la page vers le bas, soit cliquer sur un bouton intitulé «Dévoiler plus» qui apparaît en bas de page.

DevoilerPlusBQ

C’est un problème, car en scraping, on aime les pages statiques. Ici, la page est dynamique: il faut cliquer ou scroller pour charger tout le contenu.

Heureusement, il appert que le contenu qu’on fait apparaître lorsqu’on clique sur ce bouton est aussi accessible sur d’autres pages disposant chacune d’un URL distinct:

http://www.blocquebecois.org/equipe-2015/candidats/page/2/,

http://www.blocquebecois.org/equipe-2015/candidats/page/3/

et ainsi de suite.

Il est donc possible de faire une boucle pour aller chercher toutes ces pages, qui sont statiques, et en extraire l’info qui nous intéresse (tout en prenant le soin de s’identifier, car le journalisme se fait à visière levée):

urlBloc = "http://www.blocquebecois.org/equipe-2015/candidats/"

# [...]

(1..5).each do |page|
  url = urlBloc + "page/#{page}"

  pageBloc = Nokogiri::HTML(open(url, "User-Agent" => "Jean-Hugues Roy, UQAM (roy.jean-hugues@uqam.ca)"))

# extraction
Parti libéral : 10,5 secondes

Aussi facile de glaner l’info, ici, que dans le cas du NPD. Ces deux partis sont vraiment faits pour aller ensemble!

Chaque candidat est dans une balise li à l’intérieur de laquelle on identifie facilement les différents éléments.

Inspection PLC

Je me suis même servi du site du Parti libéral pour construire une variable des codes de circonscription qui a été utile pour scraper le site du parti suivant.

urlLib = "https://www.liberal.ca/fr/candidats/"

# [...]

pageLib = Nokogiri::HTML(open(urlLib, "User-Agent" => "Jean-Hugues Roy, UQAM (roy.jean-hugues@uqam.ca)"))

# variable-tableau codeCirc
codeCirc = []
pageLib.css("li.candidate-type-candidate").map do |pouetpouet|
  codeCirc.push pouetpouet["data-riding-riding_id"]
end
Parti vert : 9 minutes et 49,2 secondes

Whoa! Qu’est-ce qui se passe, ici? On passe de quelques secondes à quelques minutes!

C’est simplement parce que la page des candidats du Parti vert ne contient pas toute l’info. On est obligés d’aller sur la page de chacun des candidats pour recueillir toutes les infos sur ces derniers.

Les URL de ces pages sont construits avec les codes de circonscription que j’ai préalablement recueillis sur le site du Parti libéral. Avec le code 24010, par exemple, on peut faire l’URL de la page du candidat dans la circonscription Bellechasse — Les Etchemins — Lévis, André Bélisle.

Inspection Verts

Parti conservateur : 14 minutes et 4,0 secondes

InspectHarperLa palme du code qui donne envie de sacrer son ordinateur par la fenêtre revient cependant au site du Parti conservateur. Sa page de candidats a l’air simple à scraper quand on en inspecte le HTML. Mais c’est rempli de sournoiseries dynamiques qui font que ce qu’on voit dans l’inspecteur de code n’est pas recueilli par notre script, si on s’en tient aux bibliothèques de scraping classiques (Nokogiri, dans le cas du ruby, BeautifulSoup dans le cas du python, node-soupselect dans le cas du node.js).

Il faut donc utiliser un webdriver, qui permet d’extraire de l’info d’un site dynamique. Et pour y parvenir, il a fallu faire une quantité invraisemblable d’essais et d’erreurs pour parvenir à ce code qui fait en sorte qu’on clique virtuellement sur un lien appelé «Candidats» et qu’on attende que la page se charge au complet (on considère qu’elle est toute chargée quand le candidat du Yukon, qui apparaît toujours en dernier, le pauvre, est là):

cons = Watir::Browser.new
cons.goto urlCon

lien = cons.link :text => "Candidats"
lien.click
cons.div(:id => "candidates-yt").wait_until_present

On demande ensuite à notre webdriver de mettre une partie du contenu de la page qui vient d’être chargée (un div ayant pour id la valeur de candidates) dans une variable qu’on va appeler liste:

liste = cons.div(:id => "candidates")

Ensuite, on peut utliser un extracteur plus classique pour analyser (parse) notre variable:

pageCon = Nokogiri::HTML::Document.parse(liste.html)

Comme dans le cas du Parti vert, chaque candidat conservateur a sa propre page. Mais voilà. Pour compliquer la vie du scrapeur, les pages de certains candidats ne fonctionnent pas. Les codeurs conservateurs ne sont pas capables d’écrire correctement les noms de certains de leurs candidats. Un exemple?

TillyOneillGordon

Pour scraper les infos d’un candidat, il faut aller sur la page qui apparaît lorsqu’on clique sur le lien «Pour en savoir plus». Dans le cas de Mme O’Neill Gordon, voici le l’URL vers lequel on est envoyé:

http://www.conservateur.ca/equipe/member/?fname=Tilly&lname=O%27Neill%20Gordon&type=candidates

Fin juillet, lorsqu’on clique sur ce lien, on aboutit ici:

404Justin

Un amusante page d’erreur 404 trafiquée par les conservateurs avec l’image de Justin Trudeau. Le Huff Post en avait déjà parlé. Le problème, c’est que j’ai essayé de corriger cet hyperlien en remplaçant l’apostrophe du O’Neill (codée %27) par d’autres caractères semblables (%60, %92, un espace, rien du tout, alouette). Mais en vain.

Bref, des pépins ridicules comme celui-ci deviennent des obstacles considérables quand on scrape un site dynamique qui peut prendre jusqu’à 15 minutes à chaque essai!

Le site conservateur se démarque pour une autre raison. En consultant l’inspecteur de code, on se rend compte que ses créateurs ont donné le nom de Stephen Harper à plusieurs classes dans leur feuille de style. C’est vraiment étrange! Et ça donne ça quand on consulte le code de la candidate dans Drummond, par exemple:

CSSHarper

On est pas loin du cyber-culte de la personnalité.


 

Bref, j’ai réuni les cinq scripts en un seul, l’ai fait rouler ce matin, et voici les performances de chaque parti:

Temps-scraping-partis


Mise à jour, 2 août.

Sur Twitter, Jean-François Fortin a posé une bonne question:

À quoi bon faire pareil exercice, donc? Le but original n’était pas de comparer les cinq partis, mais de trouver une façon de constituer dès maintenant, avant que la campagne électorale soit officiellement lancée, une liste de candidats. Ce script peut être exécuté régulièrement (deux, trois ou quatre fois par jour, par exemple) afin d’avoir une liste continuellement à jour.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Jean-Hugues Roy [CC] BY-NC-SA, 1988-aujourd'hui Frontier Theme