[Javascript] Réaliser son propre Crawler

Capture

 

 

Je l'avoue, c'est une idée qui m'avait effleurée l'esprit, mais que j'ai longtemps mis de coté ...
Car j'ai toujours préférer développer mes crawler en PHP sur des serveurs, au détriment d'outil pour client léger.
Hier, j'ai été contacté pour réaliser une extraction de données ... aussi ne disposant pas de toutes ma petite gamme d'outils (home made) ... ni d'une connexion fiable à mon serveur ...

 

J'ai dû faire avec les "moyens du bord" :

  • Un navigateur Chrome / Firefox
  • Un éditeur de texte
  • Un outils de compression Zip

 

 

Aussi, j'ai voulu vous faire partager un peu le concept :

Prenons par exemple le site : www.mines-paristech.fr

En fouinant un peu ... on tombe sur un annuaire !

 

 

Capture

 

 

 

Bien entendu, cet annuaire ne donne pas UNE liste, mais permet de faire des recherches avec des filtres !!!

 

Aussi ...

 

Nous allons chercher le filtre qui permet de récupérer toute la liste, en un minimum d'action.

 

 

 

Capture

 

 

 

Maintenant qu'on a le filtre le plus "court" ..

 

Nous allons voir à quoi ressemble l'affichage de l'annuaire !
En lançant une petite recherche avec ce filtre, on constate un affichage homogène et sur une seule page !

 

 

Ce qui est encore mieux !!!!

 

 

Capture

 

 

Regardons à présent, le code source (HTML) pour UN résultat ....

(J'ai ici volontairement épuré un peu le code HTML, pour n'afficher que l'essentiel)

 

 

<div class="person-result" id="person-result-16015"> 
    <b><a href="#">Hayat ******* </a></b>
    <div class="person-data">
        <table>
            <tr>
                <td><i>Fonction: </i></td>
                <td><b>Doctorant(e)</b></td>
            </tr>
            <tr>
                <td><i>Centre: </i></td>
                <td>MAT (Evry)</td>
            </tr>
            <tr>
                <td><i>Téléphone: </i></td>
                <td>01.xx.xx.xx.xx</td>
            </tr>
            <tr>
                <td><i>Email:</i></td>
                <td>
                    <script type="text/javascript">
                        /*<![CDATA[*/
                        eval("var a=\"kQNx80W@. ... ") /*]]>*/
                    </script>
                </td>
            </tr>
            <tr>
                <td><i>Promotion: </i></td>
                <td>14</td>
            </tr>
        </table><a href="#person-result-16015">+ de détails...</a></div>
</div>

 

 

On constate donc que chaque élément est affiché dans une div qui porte la classe "person-result"

 

Donc nous pourrons récupérer tous les résultats avec ce code Javascript :

 

myRecords = document.getElementsByClassName('person-result');

 

Que le nom est prénom de chacun des membres est situé dans le premier lien "<a>" de cette div.

 

Que l'on pourra alors extraire directement  :

 

myRecords[ Id record ].getElementsByTagName('a')[0];

 

Pour finir, toutes les données sont dans un bête tableau ... aussi nous n'aurons qu'à extraire les TD :

myRecords[ Id record ].getElementsByTagName('td');

 

 

Petit bonus ...

 

Préférez toujours dans vos dev' la mise en place d'une image pour afficher vos mails ...
ça demande de la ressource pour créer l'image, mais une fois créé, vous n'aurez plus à la régénérer ...

 

Car sur l'exemple que je vous donne ...

 

L'adresse email c'est ça :

 

<span id="e722665973">[javascript protected email address]</span><script type="text/javascript">/*<![CDATA[*/eval("var a=\"kQNx80W@vRoOVCtYE_ch.jiBa-gGH9X4+wylAfrz52s73ZUTqKSId6DMFnePJbLmpu1\";var b=a.split(\"\").sort().join(\"\");var c=\"q2u2JN2s3ZPPZd26C6KDZPQF2eKPJZ7qNUe\";var d=\"\";for(var e=0;e<c.length;e++)d+=b.charAt(a.indexOf(c.charAt(e)));document.getElementById(\"e722665973\").innerHTML=\"<a href=\\\"\"+String.fromCharCode(109,97,105,108,116,111)+\":\"+d+\"\\\">\"+d+\"</a>\"")/*]]>*/</script>

 

Oh mon Dieu !!!

ça peut être effrayant ...

Sauf que ça n'est que du Javascript ... par chance notre extension est en Javascript ...

Aussi lorsque nous parcourons les données du tableau ... sinon détectons un eval( quelque chose);

Nous exécutons le code, et nous récupérons le résultat ...

 

td = datas[k].innerText;
if ((test = /eval\("(.*)\);/.exec(td))) {
    while (test[1].indexOf('\\') != -1) test[1] = test[1].replace('\\', '');
    eval(test[1] + ");");
    td = d;
}

 

 

En Assemblant un peu tout ça ... nous obtenons ce joli morceau de code à injecter dans dans notre page, ou à packager dans une extension Chrome ou Firefox :

 

var trim = function(str, charlist) {
  var whitespace = [' ','\n','\r','\t','\f','\x0b','\xa0','\u2000','\u2001','\u2002','\u2003','\u2004','\u2005',
					'\u2006','\u2007','\u2008','\u2009','\u200a','\u200b','\u2028','\u2029','\u3000'].join('');
  var l = 0,i = 0;
  str += '';
  if (charlist) whitespace = (charlist + '').replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^:])/g, '$1')
  l = str.length;for (i = 0; i < l; i++) if (whitespace.indexOf(str.charAt(i)) === -1) { str = str.substring(i);break } l = str.length; for (i = l - 1; i >= 0; i--) 
    if (whitespace.indexOf(str.charAt(i)) === -1) {
      str = str.substring(0, i + 1);break
    }
  return whitespace.indexOf(str.charAt(0)) === -1 ? str : ''
}




var Crawl = function(){
	dmp = document.createElement('textarea');
	dmp.setAttribute('id', 'dmp_crawl');
	dmp.setAttribute('style', 'width:100%;height:1000px;border:1px solid black');
	document.getElementsByTagName('html')[0].appendChild(dmp);
	var list = document.getElementById('localityName').addEventListener('change', function(e){
			var localityName = e.target.value;
			$.get("http://www.mines-paristech.fr/libmines/Annuaire/Commun/ajax-search.php?&localityName="+localityName, function(e){
				var parser = new DOMParser(), doc = parser.parseFromString(e, "text/html");
				var personnes = doc.getElementsByClassName('person-result');
				for (var j in personnes){
					if (!personnes[j].getElementsByTagName) continue;
					var datas = personnes[j].getElementsByTagName('td'), info=personnes[j].getElementsByTagName('a')[0].innerText;
					for (var k in datas) {
						td = datas[k].innerText;
						if ((test = /eval\("(.*)\);/.exec(td))){
							while (test[1].indexOf('\\')!= -1) test[1]=test[1].replace('\\', '');
							eval(test[1]+");");
							td=d;
						}
						info+=";"+trim(td);
					}
					document.getElementById('dmp_crawl').value+="\n"+info;
				}
				alert("Dumped !");
			});
	});
}


window.addEventListener('load', Crawl);

 

 

Qui va donc à chaque clic, parcourir tous les résultats, extraire le nom/Prenom, les données, le mettre au format CSV (séparation des données par des points virgule)
et stocker tout ça dans une textarea.

 

 

Partagez ce contenu

One comment

  • Bonjour et merci pour ce beau tuto,

    Toutefois, peux tu être plus précis quand tu dis « injecter » dans la page ? Ou « packager dans une extension Chrome » ?
    Aurais tu un autre tuto, ou un complément d’informations à fournir à se sujet ?

    Merci d’avance
    JP

Laisser une réponse

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