Scrapathon

Extraire des données depuis le web en Java

Thomas Dudouet / @tdudouet / @datapublica


Une présentation disponible ici :
http://datapublica.github.io/scrapathon-java

Contenu de la présentation

  • Extraction de données depuis le web
  • Techniques de scraping
  • Scraper le web avec Java
  • Scraper le web avec Web Harvest
  • C'est à vous !

Extraction de données depuis le web


Deux techniques majeures :

  • Web crawling : on part d'une liste d'URL (la seed), on extrait des informations de ces pages, et on recommence le processus avec les liens détectés en leur sein
  • » Gros volume de données, mais pas de structuration

  • Web scraping : on analyse la structure HTML des pages d'un site précis (ou plus généralement un sous-ensemble), et on extrait de l'information ciblée
  • » Volume de données plus faible, mais très structuré

Extraction de données depuis le web

Web crawling


  • Pas de connaissance du site, suivi des liens à l'aveugle
  • Type de données extraites : titres, texte, liens hypertextes


Cas d'utilisation : Moteurs de recherche (Google), analyse de liens entrants/sortants,...

Extraction de données depuis le web

Web scraping


  • Reconstitution d'une base de données via un parcours connu et maîtrisé du site
  • Fortement lié à un site (extraction spécifique)


Cas d'utilisation : Récupération de données ciblées et structurées (voir http://resultats.lesprimairescitoyennes.fr/)

Techniques de scraping

  • Expressions rationnelles (régulières) (regex)

    On extrait le code source de la page, puis on applique des motifs d'extraction dessus, comme s'il s'agissait de texte brut.

  • XPath

    On extrait le code source de la page, on le normalise en un flux XML valide, puis on applique des expressions d'extraction sur le DOM.

Expressions rationnelles



Source : http://culot.org/public/Docs/regexp.html

XPath


<?xml version="1.0"?>
<racine>
  <encyclopedie nom="Wikipedia" site="http://fr.wikipedia.org/">
    <article nom="XPath">   
      <auteurs>
        <auteur>
          <nom>Dupont</nom>
        </auteur>
        <auteur>
          <nom>Dubois</nom>
        </auteur>
      </auteurs>
    </article>
  </encyclopedie>
</racine>
            
//article Sélectionne les éléments "article"
/racine/encyclopedie Sélectionne les éléments "encyclopedie" qui sont fils d'éléments "racine"
//article[@nom='XPath'] Sélectionne les éléments "article" dont l'attribut "nom" vaut "XPath"
//article[1]/auteurs/auteur[2] Sélectionne le second auteur (Dubois) du premier article


Source : http://fr.wikipedia.org/wiki/XPath

Scraper le web avec Java

  • Récupérer le contenu de pages web
  • Extraire des données en utilisant regex
  • Extraire des données en utilisant xpath


Ressources et exemples disponibles sur github

https://github.com/datapublica/jscraping-tools

Scraper le web avec Java

Récupérer le contenu de pages web


Utiliser la classe ScrapingIOUtils qui permet de récupérer le contenu d'une page web sous forme d'une String ou sous forme d'un InputStream.

Cette classe gère instinctivement les problèmes d'encodage, de compression des réponses, etc...



URL url = new URL("http://www.data-publica.com");
String html = ScrapingIOUtils.getResourceAsString(url);
try(InputStream stream = ScrapingIOUtils.getResourceAsStream(url)) {
    // Do something with streamed data
}
            

Scraper le web avec Java

Extraire des données en utilisant regex


Utiliser les classes du package java.util.regex (jdk).

Normaliser le texte extrait (suppression des entités html) avec la classe StringEscapeUtils (Projet Apache).



Pattern links = Pattern.compile("<a.+href=\"(.+?)\".*>(.+?)</a>");
Matcher m = links.matcher(html);
while(m.find()) {
    String href = StringEscapeUtils.unescapeHtml(m.group(1));
    String text = StringEscapeUtils.unescapeHtml(m.group(2));
    System.out.println(text + " > " + href);
}
            

Offre > http://www.data-publica.com/content/offer
Société > http://www.data-publica.com/content/
...
            

Scraper le web avec Java

Extraire des données en utilisant xpath


Utiliser la classe XPathUtils qui contient les méthodes :

  • getDocumentHTML : construit DOM valide à partir d'un flux HTML
  • getDocumentXML : parse un flux XML et retourne le DOM correspondant
  • getNodes : retourne une liste de noeuds du DOM extraits grâce à une expression xpath
  • getString : retourne une chaîne de caractères grâce à une expression xpath ne renvoyant qu'un noeud texte
  • unescape : normalise une chaîne de caractères (suppression des entités HTML et des espaces inutiles)

Scraper le web avec Java

Extraire des données en utilisant xpath



try(InputStream stream = ScrapingIOUtils.getResourceAsStream(url)) {
 // Get a valid XML stream.
 Document doc = XPathUtils.getDocumentHTML(stream, "UTF-8");
 // Print page title
 String title = XPathUtils.getString(doc, "//head/title/text()");
 System.out.println(title);
 // Get all links
 NodeList nodes = XPathUtils.getNodes(doc, "//a[@href and text()]");
 for(int i=0 ; i<nodes.getLength() ; i++) {
  Node node = nodes.item(i);
  Node attr = node.getAttributes().getNamedItem("href");
  String href = XPathUtils.unescape(attr.getNodeValue());
  String text = XPathUtils.unescape(node.getTextContent());
  System.out.println(text + " > " + new URL(url, href));
 }
}
            

Data Publica | Les données pour votre business
Offre > http://www.data-publica.com/content/offer
Société > http://www.data-publica.com/content/
clients > http://www.data-publica.com/content/clients
S'inscrire > http://www.data-publica.com/register
...
            

Scraper le web avec Web Harvest


Web Harvest est un outil open-source d'extraction de données web.

Les scrapers se configurent via un fichier XML, et peuvent être étendus grâce au développement de plugins en Java.

Une GUI est également disponible (attention aux yeux).


http://web-harvest.sourceforge.net/

Scraper le web avec Web Harvest


<?xml version="1.0" encoding="UTF-8"?>
<config>
 <var-def name="root">http://www.data-publica.com</var-def>
 <loop item="href">
  <list>
   <xpath expression="//a/@href">
    <html-to-xml>
     <http url="${root}" />
    </html-to-xml>
   </xpath>
  </list>
  <body>
   <var-def name="url">
    <template>${sys.fullUrl(root, href)}</template>
   </var-def>
   <var-def name="title">
    <xpath expression="//head/title/text()">
     <html-to-xml>
      <http url="${url}" />
     </html-to-xml>
    </xpath>
   </var-def>
   <file action="append" path="/Users/thomas/Desktop/scrapathon.output">
    <template>${url}     ${title} ${sys.lf}</template>
   </file>
  </body>
 </loop>
</config>
            

C'est à vous !


Objectif

Constituer un annuaire des services ministériels Français.

http://lannuaire.service-public.fr/navigation/gouvernement.html


  • Nom du ministère
  • Site internet
  • Adresse postale (normalisée, ou non)
  • Numéro de téléphone
  • Nom + Prénom + Fonction des responsables

LIENS À VISITER D'URGENCE



CHOSES À FAIRE D'URGENCE

  • Twitter (le verbe) #scrapathon