Pogoda na stronie www
23 czerwca 2010
Skryptów PHP do pobierania informacji o pogodzie widziałem kilka. Większość to straszne kobyły, część nie działa, inna część działa błędnie lub mało wydajnie. Znowu przyszło mi pisać coś swojego...
Z pogodą na stronie jest jeden podstawowy problem: trzeba skądś pobrać dane. Są trzy wyjścia:
- Wstawić na stronę gotową "wklejkę", która jest odpowiedzialna za wyświetlenie pogody (i przy okazji linka do źródła, logo innego serwisu itp.).
- Parsować jakąś stronę www i "na chama" wyciągać z niej informacje o pogodzie (np. z pogoda.onet.pl).
- Parsować ogólnodostępne źródło, najczęściej jakiś RSS
Pierwszym sposobem zajmować się nie będziemy wcale. Po to piszemy własny skrypt żeby wyświetlić pogodę dokładnie tak jak chcemy, bez zbędnych linków, obrazków itd. a nie tak jak ktoś nam nakaże.
Drugi sposób ma swoje zalety i wady.
Nasze rodzime serwisy informacyjne mają bogatą bazę polskich miejscowości. Każdy znajdzie tam swoją miejscowość lub inną, bardzo blisko położoną swojej. Dodatkowo najczęściej udostępniają bardzo wiele informacji pogodowych.
Przejdźmy do wad. Po pierwsze, nasze (znaczy polskie) serwisy nie udostępniają informacji o pogodzie w jakimś otwartym standardzie np. RSS. Musimy na własną rękę parsować wybraną witrynę. Gdy na stronie coś się zmieni to w najlepszym przypadku nasza pogoda nagle przestanie działać. W najgorszym, zaczną się u nas wyświetlać jakieś bzdury co w skrajnym przypadku rozwali nam cały serwis...
Druga wada jest powiązana z pierwszą. Skoro musimy parsować stronę to zwyczajnie kradniemy dane. I nie pomoże nawet informacja u nas na stronie skąd pobieramy pogodę. Jeżeli ktoś nie udostępnił RSS, XML czy innego ustrojstwa to znaczy, że nie chce nam czegoś dać, koniec kropka.
I nareszcie przechodzimy do trzeciego sposobu. Zagraniczne serwisy o pogodzie są bardziej liberalne od polskich i najczęściej każde miasto ma swój kanał RSS, który możemy spokojnie pobierać. Mamy dużo większą pewność, że nie będziemy musieli raz na kilka miesięcy zmieniać swoich skryptów w skutek zmian w strukturze pliku nad którym pracujemy. Nie obejdzie się jednak bez wad. Baza miejscowości jest przeważnie dużo skromniejsza niż byśmy tego oczekiwali. Jednak na własnym przykładzie przetestowałem, że nie jest to aż taki duży problem. Dla Tomaszowa Mazowieckiego na jednej ze stron wyświetlam pogodę z kanału Łodzi (jakieś 45km odległości licząc od środka jednego miasta do środka drugiego) i zawsze jest wyjątkowo aktualna ![]()
Udostępniono tylko kilka podstawowych informacji o pogodzie ale tu również praktyka pokazuje, że to jest wystarczające. Pamiętaj, że pogoda na Twojej stronie to tylko dodatek a nie główny element. Jeżeli jest inaczej to musisz podpisać umowę z odpowiednimi instytucjami o udostępnienie danych pogodowych a nie myśleć o pobieraniu tego wszystkiego od innych...
Przejdźmy do konkretów. Rok temu stanąłem przed problemem wyświetlania pogody na stronie www. Dzisiaj udostępniam skrypt
Zdecydowałem się skorzystać z serwisu weather.yahoo.com i po dziś dzień nie miałem okazji pożałować tego wyboru. Poniżej zamieszczam prostą klasę PHP5 z której korzystam:
-
<?php
-
-
class yahoo_weather {
-
-
public $city_code;
-
protected $weather;
-
-
public function __construct($city_code) {
-
$this->city_code = $city_code;
-
}
-
-
public function get($get_channel = NULL) {
-
-
-
try {
-
$xml = @new SimpleXMLElement('http://weather.yahooapis.com/forecastrss?w='. $this->city_code .'&u=c', NULL, TRUE);
-
} catch (Exception $e) {
-
return FALSE;
-
}
-
-
$xml->registerXpathNamespace('yweather', 'http://xml.weather.yahoo.com/ns/rss/1.0');
-
-
$wind = $xml->xpath('//channel/yweather:wind');
-
$atmosphere = $xml->xpath('//channel/yweather:atmosphere');
-
$astronomy = $xml->xpath('//channel/yweather:astronomy');
-
$condition = $xml->xpath('//channel/item/yweather:condition');
-
$forecast = $xml->xpath('//channel/item/yweather:forecast');
-
-
'chill' => "{$wind[0]['chill']}",
-
'direction' => "{$wind[0]['direction']}",
-
'speed' => "{$wind[0]['speed']}",
-
),
-
'humidity' => "{$atmosphere[0]['humidity']}",
-
'visibility' => "{$atmosphere[0]['visibility']}",
-
'pressure' => "{$atmosphere[0]['pressure']}",
-
'rising' => "{$atmosphere[0]['rising']}",
-
),
-
'sunrise' => "{$astronomy[0]['sunrise']}",
-
'sunset' => "{$astronomy[0]['sunset']}",
-
),
-
'text' => "{$condition[0]['text']}",
-
'code' => "{$condition[0]['code']}",
-
'temp' => "{$condition[0]['temp']}",
-
'date' => "{$condition[0]['date']}",
-
),
-
'day' => "{$forecast[0]['day']}",
-
'date' => "{$forecast[0]['date']}",
-
'low' => "{$forecast[0]['low']}",
-
'high' => "{$forecast[0]['high']}",
-
'text' => "{$forecast[0]['text']}",
-
'code' => "{$forecast[0]['code']}",
-
),
-
'day' => "{$forecast[1]['day']}",
-
'date' => "{$forecast[1]['date']}",
-
'low' => "{$forecast[1]['low']}",
-
'high' => "{$forecast[1]['high']}",
-
'text' => "{$forecast[1]['text']}",
-
'code' => "{$forecast[1]['code']}",
-
)
-
)
-
);
-
-
$xml = NULL;
-
}
-
-
if($get_channel == NULL) {
-
return $this->weather;
-
}
-
else {
-
return $this->weather[$get_channel];
-
}
-
}
-
}
Użycie skryptu wygląda następująco (pobieramy kanał http://weather.yahooapis.com/forecastrss?w=505120&u=c):
-
$yahoo_weather = new yahoo_weather('505120');
-
$weather = $yahoo_weather->get();
I od teraz w zmiennej $weather mamy piękną tablicę ze wszystkimi informacjami o pogodzie. Dodatkowo możemy dokonać pewnych przekształceń (według własnych upodobań):
-
-
-
$sunset[0] += 12;
-
-
$weather['astronomy']['sunset'] = $sunset[0] .':'. $sunset[1];
Specjalny kod miejscowości, który przekazujemy do klasy musimy znaleźć sami. Wchodzimy na weather.yahoo.com, odszukujemy miasto, które nam najbardziej odpowiada i klikamy w prawym górnym roku na pomarańczową ikonkę RSS. W adresie na jaki zostaniemy przekierowani w parametrze "p" odnajdziemy interesujący nas kod. Właśnie wyczytałem w dokumentacji, że w adresie RSS zamiast parametru "p" (który został uznany za przestarzały) należy używać parametru "w" podając tzw. kod WOEID. Problem w tym, że gdy odnajdzie się stronę z pogodą dla wybranej miejscowości to sami linkują ikonkę RSS pod adres z parametrem "p". Kod, którego potrzebujemy jest w adresie strony z pogodą dla miasta. Dla Łodzi adres to http://weather.yahoo.com/poland/lodz/%EF%BF%BD%EF%BF%BDd%EF%BF%BD-505120/ z czego interesują nas ostatnie cyferki czyli 505120. Oto nasz kod (wcześniej PLXX0014). Poprawiłem klasę, jest już przygotowana do nowego standardu.
Klasa jest prosta i nie będę jej omawiał
Na jej podstawie można napisać parser pogody z innego serwisu niż weather.yahoo.com lub np. nauczyć się jak pobierać i parsować dokumenty RSS, Atom, XML itp.
Skąd wziąć ikony pogody? Ten problem powtarza się bardzo często, ładne ikony to nieodzowny element prognozy pogody na każdej stronie www. Tu nie pomogą nam nawet zagraniczne serwisy. Nie chcą udostępniać swoich ikon bo to dla nich dodatkowy ruch na łączach i serwerach. A jak chcą to są dodatkowe obostrzenia, konieczność wyświetlania ich logo itp. Z tego powodu moja klasa nie wyciąga adresu do ikony aktualnej pogody mimo, że taki jest podawany (chociaż nie tak otwarcie jak reszta danych). Na szczęście w internecie jest sporo ikon, często darmowych (przynajmniej dla zastosowań niekomercyjnych), którymi możemy na swojej stronie zobrazować pogodę. Tu pojawia się zaleta wyboru weather.yahoo.com. Ich RSS udostępnia kod warunków pogody np. w chwili gdy to piszę jest częściowe zachmurzenie w nocy czemu powinna odpowiadać ikona księżyca za lekkimi chmurkami i takim warunkom przypisano kod 33. Wiele gotowych pakietów ikon uwzględnia te kody przez co sami już nie musimy sprawdzać wszystkich kodów i samemu ich przypisywać do odpowiednich ikon. Wystarczy wyświetlić ikonę 33.png
Nie możesz znaleźć ikon dla siebie? Moim faworytem są te ikony. Są już przystosowane do kodów z weather.yahoo.com. Co więcej, ich autorem jest nasz rodak
Ikony są darmowe do zastosowań niekomercyjnych a za wykorzystanie w komercyjnym projekcie trzeba zapłacić 200zł (tak było rok temu, teraz nie wiem). Warte tych pieniędzy.
W ekstremalnej sytuacji można ściągnąć ikony weather.yahoo.com na własny serwer. Chyba się nie pogniewają...
Na koniec pamiętaj aby wynik powyższej klasy zapisywać jakoś do cache (np. korzystając z dobrodziejstw crona). Niedopuszczalne jest pobieranie informacji o pogodzie za każdym razem gdy musimy je wyświetlić u siebie na stronie. To spowodowałoby bardzo duży wzrost transferu, niepotrzebne obciążenie maszyny i opóźnienie w wyświetlaniu się naszej witryny. Osobiście ściągam pogodę raz na godzinę.
PS
Zachęcam do zapoznania się z dokumentacją RSS, którą można znaleźć pod tym adresem developer.yahoo.com/weather.
PS 2
A może jednak jakiś polski serwis udostępnia w prostej postaci i za darmo informacje o pogodzie? Poproszę o linki w komentarzach
Blog przede wszystkim o Internecie i mojej pasji jaką jest tworzenie stron www. Ale nie ograniczam się do jednej tematyki, piszę o wszystkim o czym mam ochotę :-)