Rev 343 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php// Encodage : UTF-8// +-------------------------------------------------------------------------------------------------------------------+/*** Robots** Description : classe permettant d'analyser les pages d'un site web.* Notes : les noms des pages doivent être dans la bonne casse. http://fr.wikipedia.org/wiki/ambronay ne renvera rien alors que* http://fr.wikipedia.org/wiki/Ambronay renvera un résultat (Notez le A ou a).*//Auteur original :* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>* @copyright Tela-Botanica 1999-2009* @link http://www.tela-botanica.org/wikini/eflore* @licence GPL v3 & CeCILL v2* @version $Id: Robot.class.php 2057 2011-05-13 16:39:06Z Jean-Pascal MILCENT $*/// +-------------------------------------------------------------------------------------------------------------------+class Robot extends ScriptCommande {/*** Indique le nom du Robot.*/private $robot_nom;/*** Indique le fichier de config de la gestion des cookies du Robot.*/private $cookie;/*** Indique l'url de départ du Robot.*/private $page;/*** Tableau des URLs à analyse*/private $pages = array();/*** Chemin vers un fichier contenant les noms des pages à analyser (un nom de page par ligne).*/private $page_fichier;/*** Contient soit False soit le chemin vers le dossier où mettre les pages en cache.*/private $cache = false;/*** Contient le squelette de l'url à utiliser pour récupérer les pages web.*/private $url_tpl = '';/*** Contient false ou l'encodage des pages d'un site web si celui-ci n'est pas en UTF-8.*/private $encodage = false;/*** Contient la chaine de caractères indiquant où commencer une recherche d'informations dans la page web.*/private $chaine_debut = '';/*** Contient la chaine de caractères indiquant où terminer une recherche d'informations dans la page web.*/private $chaine_fin = '';/*** Tableau des expressions régulières récupérant des données lors de l'analyse*/private $regexps = array();/*** Indique le dossier ou fichier où le Robot doit sotcker les informations collectées.*/private $sortie;public $parametres = array( '-pgf' => array(false, '', 'Fichier contenant les pages que le Robot doit analyser'),'-s' => array(false, '', 'Fichier où stocker les données récupérées par le Robot'),'-pg' => array(false, '', 'Nom de la page que le Robot doit analyser'));public function executer() {$this->page = $this->getParam('pg');$this->page_fichier = $this->getParam('pgf');$this->cookie = dirname(__FILE__).DS.'configuration'.DS.'cookieconf.txt';$this->sortie = $this->getParam('s');// Construction du tableau contenant les noms des pages à analyserif (empty($this->page_fichier)) {$this->pages[] = $this->page;} else {$this->pages = $this->convertirFichierEnTableau($this->page_fichier);}// Création du chemin du cache si le fichier ini du projet l'indiqueif ($this->getIni('cache_chemin')) {$this->cache = $this->getIni('cache_chemin');}// Lancement du Robot demandé$cmd = $this->getParam('a');switch ($cmd) {case 'wp' :$this->lancerRobotWikipedia();break;case 'wp-pays' :$this->lancerRobotWikipediaPays();break;case 'wp-liste-communes' :$this->lancerRobotWikipediaListeCommunes();break;case 'ipni' :$this->lancerRobotIpni();break;case 'cassini' :$this->lancerRobotCassini();break;case 'utm' :$this->lancerRobotUtmConverter();break;default :$this->traiterErreur('Erreur : la commande "%s" n\'existe pas!', array($cmd));}}/*** Robot analysant les pages de Wikipedia correspondant à des communes.* Exemples d'utilisation :* /opt/lampp/bin/php script.php robot -p wp_commune -a wp -pgf ~/importation/robots/eFloreBotWp_INSEE_C.txt -s ~/importation/robots/wp_communes.tsv* /opt/lampp/bin/php script.php robot -p wp_commune -a wp -pg Montpellier -s ~/importation/robots/wp_communes.tsv* /opt/lampp/bin/php script.php robot -p wp_commune -a wp -pg Montpellier** @return unknown_type*/private function lancerRobotWikipedia() {// Valeur spécifique de ce Robot$this->robot_nom = 'eFloreBotWp';$this->url_tpl = 'http://fr.wikipedia.org/wiki/%s';$this->regexp_ligne = '/<!-- bodytext -->(.*)<!-- \/bodytext -->/umsi';$this->regexps = array( 'CodeInsee' => 'Code commune<\/a><\/th>(?:\n|\r\n)<td>(\d+)<\/td>','Nom' => 'class="entete map" style="[^"]+">(.*)<','Latitutde' => '<span class="geo-dec geo" title=".*"><span class="latitude">(.*)<\/span>','Longitude' => '<span class="geo-dec geo" title=".*">.*<\/span>, <span class="longitude">(.*)<\/span>','Superficie' => 'Superficie<\/a>(?:<\/b><\/td>|<\/th>)(?:\n|\r\n)<td>((?:[0-9]| | )+(?:,[0-9]+)?) km<sup>2<\/sup>','AltitudeMin' => 'Altitudes<\/a><\/th>(?:\n|\r\n)<td>mini. (-?[0-9]+) m — maxi. [ 0-9]+ m<\/td>','AltitudeMax' => 'Altitudes<\/a><\/th>(?:\n|\r\n)<td>mini. -?[0-9]+ m — maxi. ([ 0-9]+) m<\/td>','Population' => 'Population<\/a><\/th>(?:\n|\r\n)<td>(.*) hab.','PopulationAnnee' => 'Population<\/a><\/th>(?:\n|\r\n)<td>.* hab. <small>\(<a href="\/wiki\/[0-9]+"(?: title="[0-9]+")?>([0-9]+)<\/a>','CodePostal' => 'Code postal<\/a><\/th>(?:\n|\r\n)<td>([0-9]{5}).*<\/td>','PageWikipedia' => '(?:Ce document provient|Récupérée) de « <a href="http:\/\/fr.wikipedia.org\/wiki\/(.*)">');// Préparation des noms des pagesforeach ($this->pages as $id => $nom) {$this->pages[$id] = str_replace(' ', '_', $nom);}$this->analyserUrls();}/*** Robot analysant les pages de Wikipedia correspondant à des pays.* Exemples d'utilisation :* /opt/lampp/bin/php script.php robot -p wp_commune -a wp-pays -pgf ~/importation/robots/eFloreBotWp_pays.txt -s ~/importation/robots/wp-pays.tsv** @return unknown_type*/private function lancerRobotWikipediaPays() {// Valeur spécifique de ce Robot$this->robot_nom = 'eFloreBotWp';$this->url_tpl = 'http://fr.wikipedia.org/wiki/%s';$this->regexp_ligne = '/<!-- bodytext -->(.*)<!-- \/bodytext -->/umsi';$this->regexps = array( 'Nom' => '<table class="infobox_v2" cellspacing="[^"]+" style="[^"]+">(?:\n|\r\n)<caption style="[^"]+"><b>(.*)<\/b>','Latitutde' => '<span class="geo-dec geo" title=".*"><span class="latitude">(.*)<\/span>','Longitude' => '<span class="geo-dec geo" title=".*">.*<\/span>, <span class="longitude">(.*)<\/span>','Superficie' => 'Superficie<\/a><\/b><\/td>(?:\n|\r\n)<td>((?:[0-9]|\s*| )+(?:,[0-9]+)?)(?: |\s*)km<sup>2<\/sup>','Population' => 'Population<\/a><\/b>(?: |\s)*<small>\([0-9]+\)<\/small><\/td>(?:\n|\r\n)<td>(.*)(?: |\s*)hab.','PopulationAnnee' => 'Population<\/a><\/b>(?: |\s)*<small>\(([0-9]+)\)','Capitale' => 'Capitale<\/a><\/b><\/td>(?:\n|\r\n)<td>(?:<a href="\/wiki\/[^"]+" title="[^"]+">|)(.+)<','PageWikipedia' => '(?:Ce document provient|Récupérée) de « <a href="http:\/\/fr.wikipedia.org\/wiki\/(.*)">');// Préparation des noms des pagesforeach ($this->pages as $id => $nom) {$this->pages[$id] = str_replace(' ', '_', $nom);}$this->analyserUrls();}/*** Robot analysant une page de wikipedia à la recherche de plusieurs données par page.* Exemples d'utilisation :* /opt/lampp/bin/php script.php robot -p wp_commune -a wp -pgf ~/importation/robots/eFloreBotWp_INSEE_C.txt -s ~/importation/robots/wp_communes.tsv* /opt/lampp/bin/php script.php robot -p wp_commune -a wp -pg Montpellier -s ~/importation/robots/wp_communes.tsv* /opt/lampp/bin/php script.php robot -p wp_commune -a wp -pg Montpellier** @return unknown_type*/private function lancerRobotWikipediaListeCommunes() {// Valeur spécifique de ce Robot$this->robot_nom = 'eFloreBotWpListe';$this->url_tpl = 'http://fr.wikipedia.org/wiki/%s';$this->regexp_ligne = '/<tr>(.*)?<\/tr>/Uumsi';$this->mode = 'MULTI';$this->regexps = array( 'PageWikipedia' => '^<td align="left"><a href="\/wiki\/([^"]+)"','CodeInsee' => '^<td>.+<\/td>(?:\n|\r\n)<td>(\d+)<\/td>','CodePostal' => '^(?:<td>.+<\/td>(?:\n|\r\n)){2}<td>(\d+)<\/td>','Superficie' => '^(?:<td>.+<\/td>(?:\n|\r\n)){4}<td><span.+span>((?:[0-9]| | )+(?:,[0-9]+)?)<\/td>','Population' => '^(?:<td>.+<\/td>(?:\n|\r\n)){5}<td><span.+span>((?:[0-9]| | )+)<\/td>');// Préparation des noms des pagesforeach ($this->pages as $id => $nom) {$this->pages[$id] = str_replace(' ', '_', $nom);}$this->analyserUrls();}/*** Robot analysant les pages du site de l'IPNI.* Exemples d'utilisation :* /opt/lampp/bin/php script.php robot -p ipni_auteur -a wp -pgf ~/importation/robots/eFloreBotIpni_auteur.txt -s ~/importation/robots/ipni_auteurs.tsv* /opt/lampp/bin/php script.php robot -p ipni_auteur -a wp -pg Z -s ~/importation/robots/ipni_auteurs.tsv* /opt/lampp/bin/php script.php robot -p ipni_auteur -a wp -pg Z** @return unknown_type*/private function lancerRobotIpni() {// Valeur spécifique de ce Robot$this->robot_nom = 'eFloreBotIpni';$this->url_tpl = 'http://ipni.org/ipni/advAuthorSearch.do?output_format=delimited&find_surname=%s*';$this->regexp_ligne = '/^(.*)$/umi';$this->regexps = array( 'Id' => '^([^%]+)%' ,'Version' => '^(?:[^%]*%){1,}([^%]*)%' ,'DefaultAuthorName' => '^(?:[^%]*%){2,}([^%]*)%' ,'DefaultAuthorForename' => '^(?:[^%]*%){3,}([^%]*)%' ,'DefaultAuthorSurname' => '^(?:[^%]*%){4,}([^%]*)%' ,'StandardForm' => '^(?:[^%]*%){5,}([^%]*)%' ,'NameNotes' => '^(?:[^%]*%){6,}([^%]*)%' ,'NameSource' => '^(?:[^%]*%){7,}([^%]*)%' ,'Dates' => '^(?:[^%]*%){8,}([^%]*)%' ,'DateTypeCode' => '^(?:[^%]*%){9,}([^%]*)%' ,'DateTypeString' => '^(?:[^%]*%){10,}([^%]*)%' ,'AlternativeAbbreviations' => '^(?:[^%]*%){11,}([^%]*)%' ,'AlternativeNames' => '^(?:[^%]*%){12,}([^%]*)%' ,'TaxonGroups' => '^(?:[^%]*%){13,}([^%]*)%' ,'ExampleOfNamePublished' => '^(?:[^%]*%){14,}([^%]*)$' );$this->analyserUrls();}/*** Robot analysant les pages du site de Cassini.* Exemples d'utilisation :* /opt/lampp/bin/php script.php robot -p cassini -a cassini -pgf ~/importation/robots/eFloreBotCassini.txt -s ~/importation/robots/cassini.tsv* /opt/lampp/bin/php script.php robot -p cassini -a cassini -pg 1 -s ~/importation/robots/cassini.tsv* /opt/lampp/bin/php script.php robot -p cassini -a cassini -pg 1** @return unknown_type*/private function lancerRobotCassini() {// Valeur spécifique de ce Robot$this->robot_nom = 'eFloreBotCassini';$this->url_tpl = 'http://cassini.ehess.fr/cassini/fr/html/fiche.php?select_resultat=%s';$this->encodage = 'ISO-8859-1';$this->regexp_ligne = '/\s*var\s+chaine1\s+\t=\s+"(.*?)";/umsi';$this->regexps = array( 'NomCommune' => '^([^\\\\]+)\\\\n' ,'Superficie' => '\\\\nsuperficie;([^\\\\]+)\\\\n','AltitudeMin' => '\\\\naltitude;([^;]+);','AltitudeMax' => '\\\\naltitude;[^;]+;([^\\\\]+)\\\\n','LambertIIEtenduX' => '\\\\ncoordonnées;Lambert II étendu\\\\n;x;([^\\\\]+)\\\\n','LambertIIEtenduY' => '\\\\ncoordonnées;Lambert II étendu\\\\n;x;[^\\\\]+\\\\n;y;([^\\\\]+)\\\\n','Latitude' => '\\\\n;Latitude;(.+)?\\\\ncode','Longitude' => '\\\\n;Longitude;(.+?)\\\\n;Latitude','CodeInsee' => '\\\\ncode insee;([^\\\\]+)\\\\nstatut','Statut' => '\\\\nstatut\(s\);([^\\\\]+)\\\\n\\\\n');$this->analyserUrls();}/*** Robot analysant les pages du site de Cassini.* Exemples d'utilisation :* /opt/lampp/bin/php script.php robot -p cassini -a cassini -pgf ~/importation/robots/eFloreBotCassini.txt -s ~/importation/robots/cassini.tsv* /opt/lampp/bin/php script.php robot -p cassini -a cassini -pg 1 -s ~/importation/robots/cassini.tsv* /opt/lampp/bin/php script.php robot -p cassini -a cassini -pg 1** @return unknown_type*/private function lancerRobotUtmConverter() {// Valeur spécifique de ce Robot$this->robot_nom = 'eFloreBotUtmConverter';$this->url_tpl = 'http://www.rcn.montana.edu/resources/tools/coordinates.aspx?nav=11&c=DD&md=83&mdt=NAD83/WGS84&lat=%s&lath=N&lon=%s&lonh=E';$this->encodage = 'ISO-8859-1';$this->regexp_ligne = '/Universal Transverse Mercator \(UTM\):<\/td>(.*?)<\/table><\/td>/umsi';$this->regexps = array( 'UTM_Zone' => 'Zone: ([0-9]+)<' ,'UTM_Est_x' => 'Easting: ([0-9]+)<','UTM_Nord_y' => 'Northing: ([0-9]+)<');$this->analyserUrls();}private function analyserUrls() {// Lancement de l'analyse$heure_debut = date('c',time());echo "Analyse de l'URL # : ";$pagesNum = 0;// Pages$lignesNum = 0;// Lignes$sortie = '';foreach ($this->pages as $paramsPage) {$xhtml_page = $this->getHtml($this->url_tpl, $paramsPage);$xhtml_lignes = $this->extraireChaine($this->regexp_ligne, $xhtml_page);// Pour chaque chaine début/fin trouvées au sein de la page, nous recherchons les regexps des données.if (count($xhtml_lignes) > 1 && $this->mode != 'MULTI') {$this->traiterAttention("Plusieurs lignes correspondent à votre expression régulière de limitation du contenu :\n %s", array($this->regexp_ligne));} else if ($xhtml_lignes) {print_r($xhtml_lignes );foreach ($xhtml_lignes as $xhtml) {$champsNum = 1;// Champs$ligne = '';foreach ($this->regexps as $chp => $regexp) {// Si nous traitons la première ligne nous ajoutons les noms des champs en début de fichier de sortieif ($lignesNum == 0) {$sortie .= $chp.(($champsNum == count($this->regexps)) ? "\n" : "\t");$champsNum++;}// Ajout de la valeur trouvée grâce à l'expression régulière à la ligne de sortieif (preg_match('/'.$regexp.'/Umsi', $xhtml, $match)) {$ligne .= $this->nettoyer($match[1])."\t";} else {$ligne .= "\t";}}$lignesNum++;$ligne = trim($ligne);$sortie .= $ligne."\n";// Affichage en console...if (empty($this->sortie)) {echo "\t".$ligne."\n";}}} else {$this->traiterAttention("Impossible de trouver les chaines début et fin dans la page «%s» avec la regexp :\n%s", array($this->getNomPage($paramsPage), $this->regexp_ligne));}// Affichage en console...echo str_repeat(chr(8), ( strlen( $pagesNum ) + 1 ))."\t".$pagesNum++;}echo "\n";$heure_fin = date('c',time());// Ajout de métadonnées$metadonnees = "Début d'importation : $heure_debut\nFin d'importation : $heure_fin\n";$metadonnees .= "Source des données : ".$this->url_tpl."\n";$sortie = $metadonnees.$sortie;// Écriture du fichier de sortie ou retour dans la consoleif (!empty($this->sortie)) {file_put_contents($this->sortie, $sortie);}}private function nettoyer($txt) {$txt = trim($txt);$txt = preg_replace('/(?: | )/', ' ', $txt);return $txt;}private function getHtml($url_tpl, $paramsPage) {// Lancement en ligne de commande pour tester ://curl -v --url "http://fr.wikipedia.org/wiki/Montpellier" --config /home/jpm/web/eflore_bp/consultation/scripts/modules/robot/configuration/cookieconf.txtif ($this->cache && file_exists($fichier_cache = $this->cache.$this->getNomPage($paramsPage))) {$html = file_get_contents($fichier_cache);} else {$url = vsprintf($url_tpl, $paramsPage);$this->traiterAttention(" Url : ".$url);// Initialisation CURL$curl = curl_init();curl_setopt($curl, CURLOPT_COOKIEFILE, $this->cookie);curl_setopt($curl, CURLOPT_URL, $url);curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Linux x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1');$html = curl_exec($curl);// Mise en cacheif ($this->cache) {file_put_contents($fichier_cache, $html);}}// Nettoyage des entités html$html = $this->encoderUtf8($html, 'HTML-ENTITIES');// Nettoyage de l'encodage des urls$html = urldecode($html);// Convertion en UTF-8 si nécessaireif ($this->encodage) {$html = $this->encoderUtf8($html, $this->encodage);}return $html;}/*** Méthode récupérant seulement une partie du texte passé en paramétre.** @param $debut chaine de caractère indiquant le début du texte à prendre en compte.* @param $fin chaine de caractère indiquant la fin du texte à prendre en compte.* @param $txt le texte duquel extraire une partie bornée par $debut et $fin.* @return le texte extrait.*/private function extraireChaine($regexp, $txt) {if (preg_match_all($regexp, $txt, $match)) {return $match[1];} else {return false;}}/*** Charge les lignes d'un fichier dans un tableau et le retourne.* Supprime les caractères blancs et les nouvelles lignes.** @param $fichier* @return unknown_type*/private function convertirFichierEnTableau($fichier) {$tableau = array();$handle = fopen($fichier,'r');if ($handle) {while ($ligne = fgets($handle)) {$tableau[] = explode("\t", trim($ligne));}fclose($handle);}return $tableau;}private function getNomPage($paramsPage) {return str_replace(' ', '_', implode('_', $paramsPage)).'.html';}}?>