Étiquettes : Webservice
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:
- On demande le code de la ville dont on souhaite connaitre les prévisions météo.
- On demande les prévisions météo pour les jours à venir.
- 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 :
- On crée l'objet.
- On récupère le code de la ville qui nous intéresse. Ici Toulouse, parce que c'est chez moi.
- 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($code, 4);
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 ' · ';
echo WdWeather::to24H($day['suns']);
echo '<br />';
echo $day['hi'] == 'N/A' ? '—' : WdWeather::toCelsius($day['hi']) . '°C';
echo ' · ';
echo $day['low'] == 'N/A' ? '—' : 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 :-)

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