WdBlog

Étiquettes : Webservice

19 avr

PHP, XML & Prévisions Météo Posté dans PHP 1 commentaire

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 toute 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 ;-)