PHP, XML & Prévisions Météo

On ne sait plus trop comment s'habiller ces jours-ci. Un jour on se ballade poils au vent, caressé par un soleil complice. Le lendemain on rentre du boulot en vélo, arrosé par une pluie moqueuse. Des conditions climatiques perplexes, idéales pour présenter ma dernière classe : WdWeather.

Présentation

Utilisant les services pratiques et connus de weather.com, WdWeather permet d'obtenir les prévisions météorologiques jusqu'à 10 jours (limite imposée par le service). Les informations sont aussi nombreuses que variées. Ainsi pour chaque jour on obtient, en autre, les informations suivantes :

  • Les heures de lever et de coucher du soleil
  • Les températures les plus basse et les plus hautes

Et pour chaque période de la journée (Jour / Nuit) :

  • Le numéro du pictogramme associé au temps.
  • Une description du temps en anglais, par exemple : Mostly Sunny.
  • La force et la direction du vent.
  • Les précipitations.
  • Le taux d'humidité.

Bref, il y a de quoi faire.
Voyons justement comment tout ça marche.

Comment ça marche ?

C'est vraiment très simple. Le principe est le suivant:

  1. On demande le code de la ville dont on souhaite connaitre les prévisions météo.
  2. On demande les prévisions météo pour les jours à venir.
  3. On affiche le résultat.

C'est tellement fastoche que je me suis presque endormi en écrivant les étapes.

Le Code

<?php

class WdWeather
{
    var $markup_contents = '([^<]+)';
    
    function getCityCode($search)
    {
        #
        # we create a nice looking URL
        #
        
        $search = explode(','$search);
        $search = array_map('urlencode'$search);
        $search = implode(',+'$search);
        
        #
        # ask the service about the location
        #
    
        $xml = file_get_contents
        (
            'http://xoap.weather.com/search/search?where=' . $search
        );
        
        #
        # try to get the first result
        #
        
        if (!preg_match('#loc id="([^"]+)#'$xml$matches))
        {
            return;
        }
        
        return $matches[1];
    }

    function getWeather($city_code$days)
    {
        $xml = file_get_contents
        (
            'http://xoap.weather.com/weather/local/' . $city_code .
            '?cc=*&unit=s&dayf=' . $days
        );
        
        if (!$xml)
        {
            return;
        }
        
        return $this->parseDays($xml);
    }
    
    function parseDays($xml)
    {
        $days = array();
        
        #
        # split xml by days
        #

        $parts = preg_split('#<day d=[^>]+>#'$xml);

        array_shift($parts);

        $mc = $this->markup_contents;

        foreach ($parts as $xml)
        {
            $days[] = $this->parseDay($xml);
        }
        
        return $days;
    }

    function parseDay($xml)
    {
        $mc = $this->markup_contents;
    
        preg_match
        (
            '#' .
            
            '<hi>' . $mc . '</hi>\s*' .
            '<low>' . $mc . '</low>\s*' .
            '<sunr>' . $mc . '</sunr>\s*' .
            '<suns>' . $mc . '</suns>\s*' .
            '<part p="d">(.*)</part>\s*' .
            '<part p="n">(.*)</part>' .
            
            '#ms',
            
            $xml$matches
        );
        
        array_shift($matches);
                    
        #
        # parse day periods (day / night)
        #
        
        $matches[4] = $this->parseDayPeriod($matches[4]);
        $matches[5] = $this->parseDayPeriod($matches[5]);
        
        #
        #
        #
        
        return array_combine
        (
            array('hi''low''sunr''suns''day''night')$matches
        );
    }
    
    function parseDayPeriod($xml)
    {
        $mc = $this->markup_contents;

        preg_match
        (
            '#' .
            
            '<icon>' . $mc . '</icon>\s*' .
            '<t>' . $mc . '</t>\s*' .
            '<wind>(.*)</wind>\s*' .
            '<bt>' . $mc . '</bt>\s*' .
            '<ppcp>' . $mc . '</ppcp>\s*' .
            '<hmid>' . $mc . '</hmid>' .
            
            '#ms',
            
            $xml$matches
        );
        
        array_shift($matches);
        
        $matches[2] = $this->parseWind($matches[2]);
        
        return array_combine
        (
            array('icon''t''wind''bt''ppcp''hmid')$matches
        );
    }
    
    function parseWind($xml)
    {
        $mc = $this->markup_contents;

        preg_match
        (
            '#' .
            
            '<s>' . $mc . '</s>\s*' .
            '<gust>' . $mc . '</gust>\s*' .
            '<d>' . $mc . '</d>\s*' .
            '<t>' . $mc . '</t\s*' .
            
            '#ms',
            
            $xml$matches
        );
        
        array_shift($matches);
        
        return array_combine
        (
            array('s''gust''d''t')$matches
        );
    }

    static function toCelsius($f)
    {
        if (!is_numeric($f))
        {
            return $f;
        }
    
        return round(($f-32) * 5 / 9);
    }
    
    static function to24H($time)
    {
        preg_match('#(\d+)\:(\d+)\s+(AM|PM)?#'$time$matches);
        
        if ($matches[3] == 'PM')
        {
            $matches[1] += 12;
        }

        return $matches[1] . ':' . $matches[2];
    }
}

?>

L'exemple

Trois lignes d'initialisation :

  1. On crée l'objet.
  2. On récupère le code de la ville qui nous intéresse. Ici Toulouse, parce que c'est chez moi.
  3. On récupère les prévisions météo pour les quatre jours qui viennent.
<?php

require_once 'wdweather.php';

$weather = new WdWeather();

$code = $weather->getCityCode('Toulouse, France');
$days = $weather->getWeather($code4);

define('WEATHER_ICONS_URL''wdweather/');

?>

On met tout ça dans un tableau

<table id="weather" cellpadding="4" cellspacing="0">
<tr>

Pour chaque jour on affiche les informations suivantes :

  • Pictogramme des conditions météo pour le jour et la nuit.
  • Heures de lever et de coucher du soleil.
  • Température la plus haute, température la plus basse.
<?php

foreach ($days as $day)
{
    echo '<td>';
    
    $title = $day['day']['t'];
    
    echo '<img src="' . WEATHER_ICONS_URL . $day['day']['icon'] . '.png"';
    echo ' alt="' . $title . '" title="' . $title . '" />';

    $title = $day['night']['t'];

    echo '<img src="' . WEATHER_ICONS_URL . $day['night']['icon'] . '.png"';
    echo ' alt="' . $title . '" title="' . $title . '" />';

    echo '<br />';

    echo WdWeather::to24H($day['sunr']);
    echo ' &middot; ';
    echo WdWeather::to24H($day['suns']);
    
    echo '<br />';
    
    echo $day['hi'] == 'N/A' ? '&mdash;' : WdWeather::toCelsius($day['hi']) . '°C';
    echo ' &middot; ';
    echo $day['low'] == 'N/A' ? '&mdash;' : WdWeather::toCelsius($day['low']) . '°C';

    echo '</td>';
}

?>

Et voilà, c'est fini. On remarquera juste l'utilisation de la méthode WdWeather::to24H() pour transformer la vilaine heure sur 12H en jolie heure sur 24H. On remarquera aussi l'utilisation de la méthode WdWeather::toCelsius()pour transformer les vilains degrés Fahrenheit en jolis degrés Celsius.

</tr>
</table>

Le résultat

Voici le résultat pour ce glorieux jour de soleil. Nous sommes le 19 Avril 2008, il est 12H27 et dans quelques heures le weekend va être tout trempé et morne.

Espérons que ces prévisions là soient toutes pourries :-)

WdWeather

Cadeau bonux

Pour ceux qui sont tentés, voici quelques pictogrammes pour agrémenter vos présentations. Vous en trouverez sans doute de bien mieux ailleurs, mais là vous n'avez pas à chercher ;-)

11 commentaires

1
007 a écrit : Mardi 12 Août 2008 à 14:32

Bonne info ! Tres bon script et bonne explication ! Continue comme ca, je t'ajoute dans mes lectures rss quodiennes

2
Yanice a écrit : Mardi 12 Mai 2009 à 16:21

il ya une chose qui m'échappe, sur la plupart des sites proposant des tuto pour l'utilisation de weather.com, on voit des fonctions « maisons » pour convertir les degré Fahrenheit en degré Celsius, or le paramètre « unit » de l'url du xml permet de l'obtenir directement « &unit=m ». sinon, pour ce qui est de la recherche du code de la ville, comment faire pour rechercher Alger? Venise? ou même Pékin? merci

3
Olivier a écrit : Samedi 16 Mai 2009 à 19:52

Salut Yanice,

Merci pour l'info concernant le paramètre « unit ». Comme tu peux peut-être t'en douter, je n'avais aucune documentation lors de la création de la classe et c'est vrai que je n'y suis pas retourné depuis.

Concernant la recherche du code de la ville, il faut peut-être utiliser son appellation Anglaise…

4
SAMY a écrit : Mardi 04 Août 2009 à 10:26

Salut,

j'ai un soucis, j'ai rien qui s'affiche à l'écran, la page reste blanche.

pourtant j'ai tout fait comme toi

il me récupere le code « $code ». j'ai vu qu'il déconnait à partir de « $days = $weather->getWeather($code, 4); » et du foreach

Cordialement

5
Olivier a écrit : Lundi 10 Août 2009 à 11:49

Il semblerait que le code « partenaire » soit maintenant obligatoire, ce qui n'était pas le cas auparavant… Je suis en train de décortiquer l'extension « 1-ClickWeather » de Firefox afin de trouver une solution. Sinon, vous pouvez toujours vous enregistrer :

http://www.weather.com/services/oap.html

6
Samy a écrit : Mardi 11 Août 2009 à 12:29

Il semblerait que le code « partenaire » soit maintenant obligatoire, ce qui n'était pas le cas auparavant… Je suis en train de décortiquer l'extension « 1-ClickWeather » de Firefox afin de trouver une solution. Sinon, vous pouvez toujours vous enregistrer :

http://www.weather.com/services/oap.html

On peut meme pas s'enregistrer sur le site, le lien new user ne marche pas

7
Yanice a écrit : Jeudi 13 Août 2009 à 13:03

ben pas de quoi :) sinon, pour l'appellation anglaise des villes, c'est ce que je me suis résolu à faire, mais disons que c'est extrêmement fastidieux et particulièrement compliqué. d'autant que toutes les villes n'ont pas de nom « anglais »; bref vous vous rendez-bien compte du boulot que ça entraîne, donc si quelqu'un trouve un jour une meilleure solution, je suis preneur!!

8
Soraya a écrit : Lundi 19 Octobre 2009 à 16:43

merci pour le parseur  !!! je l'ai utilisé et impec. il faut cependant changer l 'url dans la finction function getWeather($city_code, $days) par 'http://xml.weather.com/weather/local/' . $city_code . '?cc=*&unit=s&dayf=' (..xml..à la place de.. xoap..)

Sinon une question: comment je peux faire pour afficher les jours ? « monday, tuesday.. »  ??

merci ;)
vive le p2p

9
Soraya a écrit : Lundi 19 Octobre 2009 à 16:47

à yanice: j'ai mis directement le code ville de type FRXXXX que tu peux trouver ici http://xoap.weather.com/search/search?where=%20paris

tu affectes ce code à la variable $code: $code = « FRXX0076 »;

hasta batata !

10
Fabrice a écrit : Mardi 19 Janvier 2010 à 23:02

Bonjour, ce code à l'air pas mal mais je n'arrive pas a le faire fonctionner. Y'a t'il une personne qui pourrait faire les corrections afin qu'il fonctionne en s'enregistrant comme partenaire.

j'ai créer un page wdweather.php et j'y ai copier le code fournit « Le Code ». ensuite j'ai créé un page météo ou j'y ai mis le r este du code « L'exemple »

probleme : Parse error: syntax error, unexpected T_STATIC, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}' in /homepages/29/d311675876/htdocs/wdweather.php on line 171

j'imagine que le code a du changé depuis le temps et je voulai donc savoir si il était possible de l'avoir corrigé ?

Merci à vous tous !!

11
Olivier a écrit : Mercredi 27 Janvier 2010 à 20:23

Le message d'erreur que tu rapportes est assez typique. C'est la version 4 de PHP qui interprète le code, essaie donc avec la version 5, il ne devrait pas y avoir de problème.

Tu as raison, ce serait pas mal de mettre à jour le code. Promis je m'en occupe dès qu'une mairie me demande la météo sur son site.

Laisser un commentaire

 
 Souhaitez-vous être informé par E-Mail de la réponse à votre message ?