Информер погоды: делаем сами

Погода - всегда восстребованная в интернете информация. Мало новостных сайтов обходятся без информеров погоды: читателям обязательно предоставляют такую информацию на сегодня, завтра, послезавтра, реже на больший период времени. Да и каждый по себе сможет посудить о востребованности такой информации: ведь все мы чаще всего получаем прогноз погоды для своего города именно с городского новостного портала.

Прогноз погоды для своих сайтов новостные ресурсы реализовывают по-разному, чаще в виде готовых информеров с сторонних сервисов, которые легко интегрируются на сайт. Основное преимущество таких информеров погоды в том, что вебмастеру не надо беспокоиться об актуальности данных о погоде или работе скрипта информера: поставил на сайт и забыл! Но и минусы такого "взаимовыгодного сотрудничества" очевидны. Среди минусов погодных информеров с других сайтов:

  • подгрузка данных на вашем сайте с других серверов;
  • зачастую, внешняя ссылка, ведущая на сервис, отдающий погоду для информера;

Это основные, но не все "тормоза", которые обеспечивают веб-сайтам информеры погоды с внешних сервисов. Но так ли все безнадежно в эпоху, когда каждый третий школьник программирует на РHP?

Информер погоды своими руками

Итак, зададимся целью создать свой информер погоды для своего новостного сайта. Среди его особенностей:

  • реализуем прогноз погоды для отдельно взятого (любого) города на 10 дней вперед;
  • компактность информера с вкладками на чистом css (без конфликта с скриптами вашего сайта);
  • очень быстрая работа информера (данные подгружаются с вашего домена);
  • никаких внешних ссылок, полностью чистый индексируемый код, без каких-либо js, iframe и т.д.

Как сделать информер погоды для своего города, не обладая какими-либо специфическими навыками в программировании? Как сделать этот информер полностью бесплатным для своего сайта и стабильно работающим? Давайте разбираться в этих вопросах.

Естественно, мы не будем программировать сложные программы и алгоритмы для получения погоды со спутников! Найдем надежного и проверенного поставщика информации о погоде, будем получать от него такую информацию по некоторым критериям, кешировать на своем сайте с некой периодичностью и отдавать в браузер посетителям своего сайта в виде компактного информера.

Нам поможет Яндекс

В нашем случае, нашей жертвой будет http://pogoda.yandex.ru - крупный сервис, предоставляющий пользователям возможность бесплатного доступа к данным о температуре воздуха, облачности, осадках, давлении, влажности воздуха, направлении и скорости ветра, а также прогноз для метеочувствительных людей и описание климата разных городов мира. Естественно, у такого крупного сервиса есть и свои информеры, а также есть возможность получать данные о погоде через экспортный xml файл.

Экспортный xml от Яндекса мы и будем эксплуатировать, примеров чтения xml можно найти в сети великое множество, за основу мы возьмем попытку от diseltoofast. В описанном там примере, скрипт выводит прогноз погоды для выбранного города на 10 дней по временам суток, направление ветра стрелками, усредненные значения температуры т.д. Мы усовершенствуем данный скрип для построения информера погоды, а именно:

  • сделаем скрипт компактным, без кронов (запусков по расписанию);
  • добавим кэширование данных (чтобы не обращаться каждый раз к Яндексу и грузить погоду в браузер пользователя мгновенно);
  • добавим вкладки для переключения погоды на 10 дней (без js скриптов);
  • сделаем полноценный информер погоды, данные которого будут грузиться с нашего сервера;

Весь код поместится в одном файле: скрипт загружает экспортный xml-файл с адреса export.yandex.ru/weather-ng/forecasts/id_города.xml и формируют выдачу в браузер пользователя:

<?php
$city_id = 27612; //id города, вписать свой, можно узнать тут https://pogoda.yandex.ru/static/cities.xml - параметр city id=
$cache_lifetime = 7200; //время кэша файла в секундах, 3600=1 час
$cache_file = 'weather_'.$city_id.'.xml'; // временный файл-кэш 

function loadxmlyansex($city_id)
 {
$url = 'http://export.yandex.ru/weather-ng/forecasts/'.$city_id.'.xml';
$userAgent = 'Googlebot/2.1 (+http://www.google.com/bot.html)';
$xml = 'weather_'.$city_id.'.xml';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
$output = curl_exec($ch);
$fh = fopen($xml, 'w');
fwrite($fh, $output);
fclose($fh);
 }

if ( file_exists($cache_file) ) {
 $cache_modified = time() - @filemtime($cache_file);
 if ( $cache_modified > $cache_lifetime ) 

{
//обновляем файл погоды, если время файла кэша устарело
loadxmlyansex($city_id);
}
}
else {
//если нет файла погоды вообще, закачиваем его
loadxmlyansex($city_id);
}
?>
<?php
if(file_exists($cache_file)):
$data = simplexml_load_file($cache_file); ?>
<style type="text/css">
.weather .date{font-size:13px;font-weight:700;padding-bottom:5px;text-transform:uppercase;border-bottom:1px solid #d5d5d5;margin-top:10px;}
.weather .item{background-color:#DAD9D5;padding:15px;font-family:Georgia;margin-bottom:20px;}
.weather .item table{border:0;width:100%;}
.weather .item table td{padding-bottom:15px;width:20%;vertical-align:baseline;padding-right:5px;}
.weather .item .day-part td{font-size:18px;}
.weather .item .day-temp td{font-size:30px;}
.weather .item .day-temp td img{margin-left:5px;}
.weather .item .day-param td{font-size:12px;}
.weather .item .day-param td p{padding-bottom:3px;}
.weather .days{margin-top:35px;border:0;width:100%;}
.weather .days td{width:50%;padding-bottom:35px;}
.weather .days a{font-family:Georgia;font-size:18px;text-decoration:underline;font-weight:700;}

.tabs input[type=radio] {
position: absolute;
top: -9999px;
left: -9999px;
}
.tabs {
width: 1000px;
float: none;
list-style: none;
position: relative;
padding: 0;
margin: 75px auto;
font-family: "Georgia";
}
.tabs li{
float: left;
}
.tabs label {
display: block;
padding: 10px 8px;
border-radius: 2px 2px 0 0;
color: #000;
font-size: 18px;
font-weight: normal;
font-family: 'Lily Script One', helveti;
background: rgba(255,255,255,0.2);
cursor: pointer;
position: relative;
top: 3px;
-webkit-transition: all 0.2s ease-in-out;
-moz-transition: all 0.2s ease-in-out;
-o-transition: all 0.2s ease-in-out;
transition: all 0.2s ease-in-out;
}
.tabs label:hover {
background: rgba(255,255,255,0.5);
top: 0;
}
[id^=tab]:checked + label {
background: #B7B7B7;
color: white;
}
[id^=tab]:checked ~ [id^=tab-content] {
display: block;
}
.tab-content{
z-index: 2;
display: none;
text-align: left;
width: 100%;
font-size: 20px;
line-height: 140%;
padding-top: 10px;
background: #B7B7B7;
padding: 15px;
color: white;
position: absolute;
top: 53px;
left: 0;
box-sizing: border-box;
-webkit-animation-duration: 0.5s;
-o-animation-duration: 0.5s;
-moz-animation-duration: 0.5s;
animation-duration: 0.5s;
}</style><div class="weather"><ul class="tabs"><?php
foreach($data->day as $day):?>
<li><?php $s6=$s6+1;?><input type="radio" 
<?php if($s6==1) echo "checked";
else
echo "";?> name="tabs" id="tab<?php echo $s1=$s1+1;?>">
<label for="tab<?php echo $s2=$s2+1;?>"><div class="date"><?php echo getDayDate($day['date']);?></div></label>
<div id="tab-content<?php echo $s3=$s3+1;?>" class="tab-content animated fadeIn">
<div class="item"><table><tr class="day-part"><td>Утром</td><td>Днем</td><td>Вечером</td><td>Ночью</td>
</tr><tr class="day-temp"><?php for($i = 0;$i < 4;$i++): // т.к. нам не нужны данные day_short и night_short, мы останавливаем проход на 4
$img = $day->day_part[$i]->{'image-v3'};?><td><?php echo getTempSign($day->day_part[$i]->{'temperature-data'}->avg);?> °C <img src="pogoda/<?php echo $img;?>.png" width="48" height="48" /></td><?php endfor;?>
</tr><tr class="day-param"><?php for($i = 0;$i < 4;$i++): // т.к. нам не нужны данные day_short и night_short, мы останавливаем проход на 4?>
<td><p><strong><?php echo $day->day_part[$i]->weather_type;?></strong></p><p>ветер: <?php echo getWindDirection($day->day_part[$i]->wind_direction).' '.$day->day_part[$i]->wind_speed;?> м/с</p>
<p>влажность: <?php echo $day->day_part[$i]->humidity;?>%</p><p>давление: <?php echo $day->day_part[$i]->pressure;?> мм рт. ст.</p>
</td><?php endfor;?></tr></table></div></div></li><?php
endforeach;?>
</ul></div>
<?php
endif;
// получаем локализованную дату
function getDayDate($date)
{
$date = strtotime($date);
$months = array('','/01','/02','/03','/04','/05','/06','/07','/08','/09','/10','/11','/12');
$days = array('ВС','ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ');
return $days[date('w', $date)].', '.(int)date('d',$date).' '.$months[date('n', $date)];
}
// получаем знак температуры
function getTempSign($temp)
{
$temp = (int)$temp;
return $temp > 0 ? '+'.$temp : $temp;
}
// получаем направления ветра
function getWindDirection($wind)
{
$wind = (string)$wind;
$wind_direction = array('s'=>'&#8593; ю','n'=>'&#8595; с','w'=>'&#8594; з','e'=>'&#8592; в','sw'=>'&#8599; юз','se'=>'&#8598; юв','nw'=>'&#8600; сз','ne'=>'&#8601; св');
return $wind_direction[$wind];
}
?>

Тут нужны некоторые пояснения к настройкам скрипта, которые необходимо отредактировать непосредственно перед установкой информера погоды на сайт. По сути, нужно внесение лишь двух параметров: ввести id города, для которого будем получать погоду и время кеширования скрипта.

id города для информера погоды

В скрипте информера погоды ответственный параметр - $city_id - id города. Чтобы узнать id города, для которого нужно получать погоду, нужно открыть файл в браузере по ссылке https://pogoda.yandex.ru/static/cities.xml воспользоваться поиском (указав название города) и получить параметр "city id="

Время кеширования скрипта

Время кеширования скрипта (в скрипте информера погоды - переменная $cache_lifetime) указывается в секундах. Так, 3600 = 1 час. Меньше указывать нет смысла, это периодичность, с которой будут перепроверятся и закачиваться новые данные с Яндекса для построения информера. Есть смысл увеличивать данную переменную, чтобы не напрягать Яндекс. Тем более, за час погода не сильно меняется!

Картинки для информера погоды

Информер использует картинки, иллюстрирующие погодные сводки. Мы аккуратно их выкачали с Яндекса, поместили в папку и подгружаем со своего сервера.

Картинки для информера погоды (98.5 KiB, 782 downloads)

В архиве картинки лежат в папке pogoda и в скрипте (если сам скрипт будет рядом с папкой) подключаются кодом: <img src="pogoda/... Не забудьте отредактировать этот параметр, если Вами будут внесены изменения в путях к картинкам.

Собственно и все! Информер погоды для сайта готов: скачивайте, внедряйте, пользуйтесь! Информируйте своих посетителей сайта о погодных условиях в Вашем городе, безусловно, те будут вам благодарны!

Ах, да! Пример забыл показать! Вот он (погода на 10 дней для Москвы):

Красивый информер погода для сайта
Красивый информер погоды для сайта на php

FIX информера погоды (март 2016 года)

Описанный в статье информер погоды от Яндекса оказался востребованным, я знаю не менее дюжины сайтов его установивших, как собственно и новые, непредвиденные ситуации, которые возникли (и могут возникнуть в будущем) у пользователей скрипта на практике. К слову, многие "сдаются" в попытке установить и прикрутить такой скрипт погоды самостоятельно, для таких всегда есть готовый погодный информер для сайта.

Самая распространенная проблема - Яндекс может не отдать xml файл погоды при очередном его опросе, при этом будет показана страница с обычным HTTP-заголовком "200" (файл доступен). Наш скрипт закеширует нулевой weather_27612.xml и вся информация о погоде обнулится на нашем сайте. Информер будет пустой вплоть до истечения времени кеша файла, а если мы не получим информацию от Яндекса и в этот раз, не видать вашим посетителям погоды на протяжении длительного времени :)

Опытным путем удалось установить, что Яндекс не блокирует запросы к нему нашего скрипта, сервера Яндекса очень часто перегружены и xml отдаются порционно. Нижеследующий fix cкрипта поможет устранить проблемы с доступностью xml файла от Яндекса.

Я не буду полностью приводить скрипт, а лишь основную, верхнюю его часть, где скрипт кеширует xml файл от Яндекса:

<?php
$city_id = 27612; //id города, вписать свой, можно узнать тут https://pogoda.yandex.ru/static/cities.xml - параметр city id=
$cache_lifetime = 7200; //время кэша файла в секундах, 3600=1 час
$cache_file = 'weather_'.$city_id.'.xml'; // временный файл-кэш
$GLOBALS['url'] = 'http://export.yandex.ru/weather-ng/forecasts/'.$city_id.'.xml';

function loadxmlyansex($city_id)
{
global $url;
$userAgent = 'Googlebot/2.1 (+http://www.google.com/bot.html)';
$xml = 'weather_'.$city_id.'.xml';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
$output = curl_exec($ch);
$fh = fopen($xml, 'w');
fwrite($fh, $output);
fclose($fh);
}

if ( file_exists($cache_file) ) {
$cache_modified = time() - @filemtime($cache_file);
if ( $cache_modified > $cache_lifetime )

{//обновляем файл погоды, если время файла кэша устарело
$check_url = get_headers($url);
$ok = 'application/xml';
if (strpos($check_url[3],$ok)){
loadxmlyansex($city_id);
}}}
else {
loadxmlyansex($city_id);
}
?>

Надо сказать, что проблему и ее решение нашли сами пользователи. Отдельное спасибо пользователю под ником "lestvica" (см. комментарии) нашедшему оптимальное решение проверки удаленного xml файла на соответствие "Content-Type" (application/xml) - его вариант и внедрен в настоящем фиксе.

Как работает фикс? По истечении срока кеша, скрипт запрашивает удаленный xml от Яндекса, если нам отдают файл не xml формата, значит мы не обновляем файл кеша, а сделаем попытку обновить файл кеша в следующий раз - при следующем обращении к скрипту (не по истечении кеша). Так мы решаем проблему временной недоступности xml файла с погодой на серверах Яндекса и показываем посетителям закешированные данные с нашего сайта.

Оцените материал:
Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (13 голоса, рейтинг: 5,00 из 5)
Загрузка...

Вячеслав - типичный интернетчикВячеслав Скоблей (ака files) - типичный интернетчик. Скитаюсь интернетом, пишу на PHP, увлекаюсь созданием веб-сайтов на Wordpress, решаю многочисленные проблемы, которые до появления интернета не существовали...

Специализируюсь на безопасности сайтов: защищаю сайты от атак и взломов, занимаюсь лечением вирусов на сайтах и профилактикой...

Наверняка у Вас есть вопросы, просьбы или пожелания. Не стесняйтесь спросить, я отвечаю всегда быстро...

89 комментарий

  1. Добрый день.
    У яндекса все неустойчиво и очень низкие лимиты
    Не могли бы вы приспособить ваш скрипт под https://openweathermap.org/forecast5. с кешем 3 часа (за это время погода существенно не меняется
    1.Лимиты 60 в минуту!
    2.Получения прогноза не по названию и коду места, а просто по географическим координатам!
    Спасибо

  2. Здравствуйте, в последнее время не работает парсер погоды, потому как яндекс вроде как прикрыл доступ и теперь нужно получать у них ключ для доступа, кто что знает про это и как решить эту проблему?

  3. Александр says:

    Доброго времени. С удовольствием читаю ваши статьи, и некоторые даже уже использую для себя.
    К сожалению, такими навыками как вы не обладаю, а вот скрипт погоды нужен
    Не могли бы вы создать такой же только к примеру на gismeteo или на другом сервисе ?
    спасибо

  4. Вот сервис предоставляющий бесплатно погоду в xml в 3 вариантах, почасовую, на 5 и на 7 дней
    http://api.pogoda.com/
    Автору данной темы просьба на примере яндекса сделать парсер их погоды.

    1. Кевин says:

      У них есть готовое решение в виде плагина для Вордпресс
      https://wordpress.org/plugins/tiempocom/

  5. Вот и всё, яндекс закрыл xml погоду
    http://www.searchengines.ru/news/archives/yandeks_pogoda.html

    Подскажите альтернативу

  6. Kos says:

    Прикрыли... какие будут решения?

  7. Это косяк не яндекса, а скрипта. Так как с шела на сервере xml скачивается wget -q -O- http://export.yandex.ru/weather-ng/forecasts/37472.xml В то же время функция simplexml_load_file() не скачивает файл. Ответ долгий с сервера яндекса, вот и функция не может получить ответ. Надо самим функцию написать скрипт по другому.

    1. Вячеслав Скоблей says:

      Проблема не в долгом ответе сервера! Попробуйте ссылку открыть в браузере или тем же wget пару раз, сразу все увидите - Яндекс отдает файл по какому-то непонятному алгоритму.

  8. А моего населённого пункта нет в том списке... на сайте погоды есть а в xml по ссылке нет, всё в нотпаде xml переворошила- вообще нет... как в этом случае узнать id города?

    1. кстати,
      Warning: simplexml_load_file(): ^ in /home/bh..../public_html/....ru/yandex/4.php on line 37
      Warning: Invalid argument supplied for foreach() in /home/.../public_html/....ru/yandex/4.php on line 117

      1. Вячеслав Скоблей says:

        Ошибка Warning - лишь предупреждение. Уточните, сам скрипт выдает при этом результаты? Выключить предупреждение вы можете, добавив @ спереди. Например, так:

        @$data = simplexml_load_file($cache_file);
    2. Вячеслав Скоблей says:

      Значит, Яндекс для вашего населенного пункта не предоставляет погоды в xml (может быть и такое)

  9. Вчера погода с xml яндекса на 10 день не показывала данные, картинки не загружались. Сегодня уже показывает прогноз за 9 дней и на последнем дне тоже нет данных. Яндекс погода сильно барахлит, как бы через 9 дней вообще не загнулось.

    1. - 1 день, сегодня яндекс показывает погоду за 8 дней, причем на 8 день данные не верны.

      1. Вроде наладилось, и загружаться xml файл стал сразу. Непоймёшь этот яндекс.

    2. Алекс says:

      Уже пару дней не работает погода ни на хостинге ни с домашнего ПК. Получается открыть только через Opera Turbo. Попробовал открыть с IP, c которого ни разу не открывалось - тоже глухо. Проверялись Айпишники Украина-Эстония-Германия. Похоже Яндекс закрыл погоду географически.

  10. Владимир says:

    У меня такой вопрос: можно ли написать отдельный код, который будет выводить текущую температуру, подгружая её прямо из файла на хостинге, без проверки актуальности? То есть такой короткий код для информера в хидер.

    1. Вячеслав Скоблей says:

      А данный скрипт что делает? Он подгружает данные на страницу Вашего сайта из файла на хостинге. Проверка актуальности осуществляется по истечении выставленного вами срока (скажем каждые 3 часа) - чтобы закачать на ваш хостинг новый файл с данными. Или вас интересует ручное обновление файла с данными?

      1. Владимир says:

        Простите, я наверно неправильно выразился. Суть вопроса в небольшом дополнительном коде (помимо основного), который можно было бы вставить, чтобы вывести текущую температуру, например, в главном меню. То есть, чтобы загружалась только текущая температура и её можно было показывать на всех страницах сайта.

        1. Вячеслав Скоблей says:

          Вы можете считать основные переменные погоды из локального xml файла:

          $city_id = 33946;
          $data_file="weather_$city_id.xml";
          //считываем данные из xml;
          $xml = simplexml_load_file($data_file);
          // выбираем переменные
          $temp=$xml->fact->temperature;//температура
          if ($temp>0) {$temp='+'.$temp;} 
          $pic=$xml->fact->image; //картинка погоды
          $type=$xml->fact->weather_type;//тип погоды
          $wind_speed=$xml->fact->wind_speed;//скорость ветра
          $humidity=$xml->fact->humidity; //влажность
          $pressure=$xml->fact->pressure; //давление
          

          Данные получены, основные показатели погоды в переменных (вы можете выбрать какие использовать, какие не использовать), выводите в любых местах шаблона. Более расширенный вариант мини-информера погоды, где можно подсмотреть некоторые решения, выложил по ссылке http://pastebin.ru/WV3e09RP

          1. Владимир says:

            Как оказалось фактическая погода в xml не соответствует действительности и иногда опаздывает на 2-3 суток (!). Скажите пожалуйста, а можно как-то брать данные с аскетичной, например отсюда https://p.ya.ru/kirov ?

            1. Вячеслав Скоблей says:

              Использовать html парсер - http://seo-zona.ru/parsim-kontent-k-sebe-na-sajt-2013-02-09.html

          2. Владимир says:

            Кстати, когда на аскетичной версии начинаешь вводить название города, то в выпадающем списке рядом с названиями показывается именно та температура, которая 'fact' в xml-файле. Эту разницу можно заметить, сравнив с температурой, которая выйдет при выборе города.

  11. Сергей says:

    вы не могли бы выложить парсер погоды с более стабильного сервиса чем яндекс? в последнее время яндекс только разочировывает.... может гисметео? или яху? Спасибо

    1. Вячеслав Скоблей says:

      Скоро рассмотрим альтернативные варианты

      1. Не пробовали ещё делать публикацию погоды с других, более стабильных сайтов? Яндекс вообще что-то барахлит.

  12. Мне кажется, если файл погоды не грузится, то информер нужно заменить надписью:
    Сервис временно не доступен.

    Иначе погода будет отображаться не актуальная

  13. umbrella says:

    Почему не загружается yandex погода xml? Все информеры погоды "сдохли"? Кто писал Платонам? Никто ничего не пишет в инете, через поиск попал на эту страницу. Что делать-то с Яндекс.Погодой?

    1. Загружается, но очень плохо, наверное один из ста. В поддержку яндекса писать бесполезно, ниже их ответ который они прислали мне примерно неделю назад, на вопрос "Почему api погода яндекса так плохо работает".

      Размещенная в сети информация описывает недокументированные возможности сервиса Яндекс.Погода. Сервис не предоставляет данные через API, информацию о погодном API и соглашения на его использовании портал не размещал. В связи с этим техническую поддержку по данному вопросу мы оказать не можем.

  14. Сейчас модуль работает отлично, кэш файл не подменяется пока не загрузится нормальный xml файл. Однако яднекс очень плохо стал отдавать xml файл. Раз 100 перезагрузил чтоб обновилась погода.
    Никто не знает альтернативы погоде xml Яндекса?

    1. Вячеслав Скоблей says:

      Проблемы с Яндексом начались пару дней назад. Остается верить, что это временное явление. Альтернативы, естественно, есть! При наличии времени, постараюсь выложить рабочие варианты...

      1. Спасибо огромное, ждём с нетерпением=)

      2. Сейчас вроде наладилось, xml файл загружается сразу

  15. Юрий says:

    Вот набрел на Ваш сайт в поисках решения с кэшем. Последнее время, Яндекс ну совсем плохо отдает XML. Попробовал сделать фикс в своем коде, потом попробовал Ваш. Фикс не работает 146%. Получается 2 запроса, - если повезет, то второй проскакивает с данными, но в основном отдает 0. Пока добавил OR в условие обновления кэша (для Вашего кода будет так):

    $cash_size=filesize($cache_file);
    if ( $cache_modified > $cache_lifetime ||  $cash_size < 800 )

    Но это временное решение, т.к. пустышка, все равно приходит, когда стучится таймер(, но по крайней мере файл обновляется не ожидая таймер, пусть и не сразу.

    Я думаю, лучше создавать временный файл и если его размер больше 1000, то просто перезаписывать основной, другого варианта спасения пока Yandex не разрешит по-честному пользоваться файлом, наверное нет(((.

    1. Вячеслав Скоблей says:

      Если на быструю руку, то в функции loadxmlyansex($city_id) заменить строчки:

      $fh = fopen($xml, 'w');
      fwrite($fh, $output);
      fclose($fh);

      на

      if ($output <>'') {
      $fh = fopen($xml, 'w');
      fwrite($fh, $output);
      fclose($fh);
      }

      Тогда скрипт ни за что не перезапишет файл кеша на 0.

      1. Эту замену нужно произвести в коде что написан в новости? Тогда не будет происходить замена на нулевой файл?

        1. Вячеслав Скоблей says:

          Пропишите хоть в старом коде, хоть в новом. Фикс проверяет вытянутый удаленный файл от Яндекса и если он пустой, то не перезаписывает файл в кеше.

        2. Владимир says:

          У меня с фиксом, например, замена на нулевой файл не производится - показывает кэш-файл и ошибку в 27 строке. Но с другой стороны и не обновляется, хотя по факту по прямой ссылке зайти могу.

      2. Юрий says:

        Вячеслав, я думаю, вот так будет лучше:

        $info = curl_getinfo ( $ch );
        if ($info[http_code] == 200) {
        $fh = fopen($xml, 'w');
        fwrite($fh, $output);
        fclose($fh);
        }

        Если Yandex дал 200, то качаем.
        У меня погода сильно завязана на элементах дизайна сайта и при пустышках ломала вид, теперь все нормально, если Ya не закроет доступ к XML.

        1. Вячеслав Скоблей says:

          Можно и ответ "200" проверять, но надо учесть, что даже 404 в данном случае у Яндекса тоже отдает ответ "200", поэтому можем получить тот же нулевой xml.

          1. Юрий says:

            А ведь точно! Тогда проверяем тип контента в файле.

            $info = curl_getinfo ( $ch );
            if ($info[content_type] == 'application/xml') {
            $fh = fopen($xml, 'w');
            fwrite($fh, $output);
            fclose($fh);
            }

            Теперь нагрузка на Yandex вырастет в десятки раз. Сегодня из 70 обновлений, только 1-2 дают код 200(.

  16. Здравствуйте Вячеслав.

    Несколько недель погода показывается на сайте, всё отлично, однако порой погода не загружается яндекса и создаётся файл с кэшэм с размером 0. В таком случае погода не показывается до следующего обновления, или же пока не удалю файл кэша вручную.

    Подскажите, возможно ли как-то исправить эту проблему? Например чтоб была провер4ка, если файл кэша пустой, то пыталось загрузить опять.

    Заранее признателен за подсказку.

    1. Вячеслав Скоблей says:

      Артем, прочитайте комменты ниже. Человек придумал проверку по Content-Type, а именно:

      $check_url = get_headers($url);
      $ok = 'application/xml'; 
      if (strpos($check_url[3],$ok)){
      loadxmlyansex($city_id);
      }

      P.S. Должно помочь, но на практике не проверял. Мне не известно происхождение самой ошибки.

      1. Владимир says:

        Вячеслав, здравствуйте. Подскажите пожалуйста в какое место вставлять указанный код? Заменял им строку loadxmlyansex($city_id); (в обоих местах), но код не сработал. Заранее благодарен.

        1. Вячеслав Скоблей says:

          Владимир, смотрите фикс скрипта

          1. Владимир says:

            Вячеслав, благодарю, но кажется фикс не работает. Сделал точно по инструкции, но опять создается пустой кэш-файл и ошибки (пробовал множество раз и с разными городами). Вы сами проверяли работоспособность фикса?

            1. Вячеслав Скоблей says:

              ...опять создается пустой кэш-файл и ошибки...
              Это не проблема скрипта, а на стороне Яндекса наблюдаются серьезные проблемы. Особенно сегодня! xml то отдается Яндексом, то нет!
              Если у вас нет закешированного xml файла на сервере, то естественно, скрипт будет тянуть нулевой файл для кеширования, потому что нет НИКАКОГО! Если вам удалось заполучить и закешировать xml с погодой, то он будет показывать погоду до тех пор, пока не станет доступен удаленный xml файл.

              1. Владимир says:

                Вы правы, проблемы на стороне Яндекса (одни xml-ки грузит, другие нет). Сейчас удалось перейти по прямой ссылке к xml; скачал файл, переименовал и загрузил на сервер. Обновил страницу, вроде всё работает без ошибок.

              2. Уже два раза загрузило кэш файл с размером 0, данный вариант действительно не работает= (
                Не знаю что и делать.
                Может как-то возможно по другому?
                Наверное дело в том что яндекс всегда отдаёт xml файл, просто чаще он отдаётся пустой.

                1. Вячеслав Скоблей says:

                  Наверное дело в том что яндекс всегда отдаёт xml файл, просто чаще он отдаётся пустой.

                  Это надо проверить экспериментально, хотя я сильно сомневаюсь. Сам файл xml изначально был полным и информер исправно работал? Сам файл xml не удалялся в ручную?

                  1. Да, сам файл изначально был полным и информер исправно работал то время которое прописано кэшу. После загрузился xml файл с размером 0.

                    1. Вячеслав Скоблей says:

                      Надо поковыряться на досуге. Видимо Яндекс подкрутил гайки в вопросах отсечения искусственных запросов (ботов).

                    2. Владимир says:

                      Сейчас прочел это, решил проверить у себя. По факту яндекс опять пытался подсунуть нулевой файл, и загрузился кэш с сайта (как т должно быть). Единственное нарекание - над информером вышла одна ошибка Warning: get_headers() [function.get-headers]: Filename cannot be empty. В общем ругает 27 строку.

          2. Владимир says:

            Хм... Похоже мой ip-адрес заблокировали в Яндексе. Это при учете, что файл обновлял за всё время всего несколько раз. Странно.

            1. Владимир.
              Врят ли заблокировали, яндекс погода сейчас перегружен походу.
              Удаляйте пустой файл пока не загрузится нормальный, как я понял проверка первой загрузки, если нет файла кэша, не делается.

              1. Вячеслав Скоблей says:

                Смысл в проверке первой загрузки какой?

            2. Вячеслав Скоблей says:

              Проверяется очень легко. Попробуйте открыть в браузере ссылку xml - http://export.yandex.ru/weather-ng/forecasts/27612.xml

      2. Если я правильно понял, то надо найти в двух местах
        loadxmlyansex($city_id);

        и заменить на
        $check_url = get_headers($url);
        $ok = 'application/xml';
        if (strpos($check_url[3],$ok)){
        loadxmlyansex($city_id);
        }

        Однако вообще перестаёт загружаться файл кэша, многократное обновление страницы результатов не дают.

        И сверху уже есть такая строка
        $url = 'http://export.yandex.ru/weather-ng/forecasts/'.$city_id.'.xml';

        Может я что делаю не так?

        1. Вячеслав Скоблей says:

          Артем, пришлите Ваш код мне на почту

  17. Внедрил информер на свой сайт.
    Сделал его интерактивным, если плюс, то информер оранжевый, если минус, то синий, если ноль то серый.
    Сложностей никаких нет.
    Так же сделал прогноз на 10 дней под дизайн сайта.
    Кому интересно, могу помочь.
    Сайт в имени

  18. Здравствуйте.
    Очень порадовал скрипт, всё работает отлично.
    Подскажите, как сделать вывод погоды только на один текущий день?

    1. Вячеслав Скоблей says:

      Здравствуйте, Артем. Мини-информер погоды на текущий день я приводил здесь в комментариях (прочтите их внимательно).

      1. Я видел, однако там выводит только температуру и иконку.
        Мне же надо все те же данные что и в статье, только за один день.

        1. Вячеслав Скоблей says:

          Подключаем остальные переменные:

          $city_id = 33946; //id города, вписать свой, можно узнать тут  weather.yandex.ru/static/cities.xml - параметр city id=
          $cache_lifetime = 7200; //время кеша файла в секундах, 3600=1 час
          
          $cache_file = 'weather_'.$city_id.'.xml'; // временный файл-кеш 
          if ( file_exists($cache_file) ) {
           $cache_modified = time() - @filemtime($cache_file);
           if ( $cache_modified > $cache_lifetime ) 
          {
          //обновляем файл погоды, если время файла кеша устарело
          $url = 'http://export.yandex.ru/weather-ng/forecasts/'.$city_id.'.xml';
          $userAgent = 'Googlebot/2.1 (+http://www.google.com/bot.html)';
          $xml = 'weather_'.$city_id.'.xml';
          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
          curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
          $output = curl_exec($ch);
          $fh = fopen($xml, 'w');
          fwrite($fh, $output);
          fclose($fh);
          }
          }
          else {
          //если нет  файла погоды, закачиваем
          $url = 'http://export.yandex.ru/weather-ng/forecasts/'.$city_id.'.xml';
          $userAgent = 'Googlebot/2.1 (+http://www.google.com/bot.html)';
          $xml = 'weather_'.$city_id.'.xml';
          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
          curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
          $output = curl_exec($ch);
          $fh = fopen($xml, 'w');
          fwrite($fh, $output);
          fclose($fh);
          }
          ?>
          
          '↑ ю','n'=>'↓ с','w'=>'→ з','e'=>'← в','sw'=>'↗ юз','se'=>'↖ юв','nw'=>'↘ сз','ne'=>'↙ св');
          return $wind_direction[$wind];
          }
          
          $data_file="weather_$city_id.xml";
          $xml = simplexml_load_file($data_file);
          
          // выбираем требуемые параметры
          
          $city=$xml->fact->station;
          $temp=$xml->fact->temperature;
          $pic=$xml->fact->image;
          $type=$xml->fact->weather_type;
          $wind_direction=$xml->fact->wind_direction;
          $wind_speed=$xml->fact->wind_speed;
          $humidity=$xml->fact->humidity;
          $pressure=$xml->fact->pressure;
          if ($temp>0) {$temp='+'.$temp;}
           
          //вывод информера
          echo 'Сейчас в Москве: '.$temp.'oC
          Ветер: '.getWindDirection($wind_direction).'-'.$wind_speed.' м/с
          Влажность: '.$humidity.' %
          Давление: '.$pressure.' мм рт. ст.';

          P.S. Снова не проходит код. Заберите отсюда http://pastebin.ru/WV3e09RP

          1. Данный код работает отлично, но мне надо как в новости, чтоб было утро, день, вечер и ночь, но за один день= (
            Стили я сам смогу оформить.

            1. Вячеслав Скоблей says:

              В принципе, ничего сложного. В рабочий (полномасштабный код), нужно добавить счетчик дней, перед:

              foreach($data->day as $day):

              добавляем:

              $counter = 0 ;

              а после него:

              if($counter == 1) break;

              То есть, должно получится так:

              $counter = 0; foreach($data->day as $day): if($counter == 1) break;

              Тут цифра 1 - количество дней, которые нам необходимы. Можно, 2,3,4 дня... на выбор
              Теперь, перед:

              endforeach;

              добавляем:

              $counter++ ;

              Все! Стили обещали сами оформить! Удачи!

              1. Спасибо вам огромное
                Всё получилось=)

  19. Сергей says:

    Добрый день, я внимательно изучил и статью и комментарии, подскажите какой способ для подключения погодного информера самый правильный в случае с вордпрессом? просто вариант с разрешением php плагинами например "Allow PHP in Posts and Pages" мне кажеться не очень правильным... хотелось бы услышать ваше мнение. Хочу выводить в хидере где-то. Вариант кинуть файл с информером в папку с шаблоном вордпресса и в файле хидера выводить через

    <?php include( TEMPLATEPATH . '/pogoda.php' );

    и в самом файле дописать типа

    "defined('ABSPATH') or die;"

    чтобы к файлу нельзя было обратиться напрямую. Какой вариант правильный? спасибо за Ваш ответ.

    1. Вячеслав Скоблей says:

      Предпочтительнее все же вызывать через php (не через include). Если речь идет о хедер, вы можете вставить код в php-файл шаблона. Если нужно вставить в сайтбар, можно обойтись без плагинов. Просто добавьте в Ваш functions.php такой хук, и php код можно будет использовать в виджетах:

      function php_v_widget($widget_content) {
      if (strpos($widget_content, '<' . '?') !== false) {
      ob_start();
      eval('?' . '>' . $widget_content);
      $widget_content = ob_get_contents();
      ob_end_clean();
      }
      return $widget_content;
      }
      add_filter('widget_text', 'php_v_widget', 99);
  20. Для подключения к WordPress можно использовать фреймы.
    Закидываем файл Pogoda.php на сервер.
    Создаем новую запись в WordPress.
    В редакторе переходим в HTML
    Вставляем код фрейма
    Теперь информер будет отображаться без глюков.
    Ширину и высоту фрейма можно сделать любую, изменив значения width и height

    У меня вопрос Вячеславу.
    Когда внедряешь информер с помощью фрейма и переключаешь вкладки, то происходит эффект кнопки "Наверх" то есть браузер переходит вверх страницы.
    Нашел проблему вот в этом куске кода:

    .tabs input[type=radio] {
    position: absolute;
    top: -9999px;
    left: -9999px;
    }

    Если значение position заменить с absolute на fixed
    то проблема исчезает. Но вот в мобильном браузере эффект кнопки "Наверх" остается/
    Уже мозг кипит, не знаю как исправить.

  21. lestvica says:

    Уважаемый Вячеслав, подскажите пожалуйста, вот бывает что при загрузке файла - "http://export.yandex.ru/weather-ng/forecasts/'.$city_id.'.xml" - сервис Янекса недоступен, ошибка 503. И информер соответственно выдает кучу ошибок, очень некрасиво. Можно как-то при недоступности яндекса, что-бы не ошибки выходили, а какое либо сообщение.

    1. Вячеслав says:

      Добавьте вверху кода информера новую переменную:

      $url = 'http://export.yandex.ru/weather-ng/forecasts/'.$city_id.'.xml';

      Теперь, в двух местах кода, вместо

      loadxmlyansex($city_id);

      пишем:

      $check_url = get_headers($url); 
      if (strpos($check_url[0],'200')){
      loadxmlyansex($city_id);
      }

      Таким образом, загрузка xml с Яндекса будет происходить только, если получаем ответ 200 (когда страница доступна), иначе будем обходиться файлом кеша до следующей удачной попытки скачать xml.

      1. lestvica says:

        Если сервис Яндекса не доступен, он все равно в заголовке выдает - 200. Там просто загружается обычная веб-страничка с информацией о том, что сервис недоступен (похожий пример здесь - "https://tech.yandex.com/maps/jsbox/").
        Можно ли по типу контента сделать загрузку, так если все нормально, то "Content-Type: application/xml"
        А сли сервис не работает, и вместо xml-файла веб-страничка с информацией, то соответственно будет "Content-Type: text/html".

        1. Вячеслав says:

          А можно поинтересоваться: какой у вас период кеша выставлен? Есть подозрения, что вас просто блокируют. Старайтесь выставлять максимально возможный период кеша.

          1. lestvica says:

            Кэш 3600 ставил, но видно у Яндекса бывает такое кратковременно. Впрочем разобрался как сделать по "Content-Type":

            $check_url = get_headers($url);
            $ok = 'application/xml'; 
            if (strpos($check_url[3],$ok)){
            loadxmlyansex($city_id);
            }

            Единственное, с чем еще не разобрался, когда не доступен "xml", то берет из кэша, но и какая-то ошибка ещё все-таки то-же появляется:

            Warning: get_headers() [function.get-headers]: This function may only be used against URLs in /home/...../index.php on line ...
      2. Сергей says:

        Добрый день, сделал так как вы советуете, дело в том, что яндекс отдает код 200 даже когда не отдает страницу с xml(((( есть другой вариант проверки? кеш ставлю раз в час, но пару раз в день бывает такое что яндекс не очень корректно отдает xml и он пустой и информер коробит( Спасибо

  22. says:

    напишите как из gismeteo сделать информер...
    а то яндекс не все города показывает

    1. Вячеслав says:

      В Gismeteo есть вроде xml данные, но только на 24 часа (или по абонплате). К сожалению, не заморачивался.

      1. Добрый вечер Вячеслав! а не подскажите как реализовать парсер что бы писал в одну строчку например так: Москва +19 °C и иконка (картинка )

        1. Вячеслав says:

          Накидал на быструю руку, но скрипт работает (код поместить в pogoda.php, скачать картинки по ссылке выше в папку pogoda) уже готовый с кеширование. Выводит строку: город, иконка текущей погоды и температура:

           $cache_lifetime ) 
          
          {
          //обновляем файл погоды, если время файла кеша устарело
          $url = 'http://export.yandex.ru/weather-ng/forecasts/'.$city_id.'.xml';
          $userAgent = 'Googlebot/2.1 (+http://www.google.com/bot.html)';
          $xml = 'weather_'.$city_id.'.xml';
          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
          curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
          $output = curl_exec($ch);
          $fh = fopen($xml, 'w');
          fwrite($fh, $output);
          fclose($fh);
          }
          }
          else {
          //если нет  файла погоды, закачиваем
          $url = 'http://export.yandex.ru/weather-ng/forecasts/'.$city_id.'.xml';
          $userAgent = 'Googlebot/2.1 (+http://www.google.com/bot.html)';
          $xml = 'weather_'.$city_id.'.xml';
          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
          curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
          $output = curl_exec($ch);
          $fh = fopen($xml, 'w');
          fwrite($fh, $output);
          fclose($fh);
          }
          ?>
          
          
          fact->station;
            $temp=$xml->fact->temperature;
            $pic=$xml->fact->image;
            $type=$xml->fact->weather_type;
            if ($temp>0) {$temp='+'.$temp;}
          
          //выводим строчку с погодой (картинки из папки pogoda, см. в статье)
          echo 'Сейчас в Москве: '.$type.''.$temp.'oC';
          ?>
          
          1. Благодарю! код не захотел работать! но посыл понятен попытаюсь разобраться! Спасибо еще раз!

            1. Вячеслав says:

              Заберите по ссылке http://seo-zona.ru/files/mini.txt
              так как обрезается в форме комментирования. Тестировал, все работает.

              1. спасибо большое Вам! все работает!

  23. says:

    у меня не отображается(

    1. Вячеслав says:

      1. Сохраните весь код в файл pogoda.php
      2. Закачайте на сервер, запустите из браузера
      3. Проверьте, создался ли в папке с файлом файл weather_27612.xml

      1. says:

        да все создается... php файл в браузере нормально работает
        а вот на странице wordpress не отображается...точнее с ошибками

        1. Вячеслав says:

          Не уверен, что простым встраиванием кода в тело страницы получится. Тут много нюансов.
          Как вариант, сделать свой тип (шаблон) страницы:
          1) продублируйте page.php темы в pogoda.php и назовите внутри файла на свое название POGODA

          2) разместите код погоды внутри файла (там где основной вывод содержания - после the_content(); (или можно вместо этого)
          3) создайте страницу (пустую) ПОГОДА и выберите шаблон страницы из списка POGODA
          (это упрощенная инструкция для понимания сути, при желании инструкции как сделать свой шаблон страницы можете поискать в инете).

          1. says:

            вроде получилось..но с дизайном проблема
            думаю это можно исправить

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *