Язык информера
Русский Английский Латышский Литовский Немецкий Польский Румынский Украинский Название местоположения Параметры Название местоположения автоматически сверху слева Текущая погода иконка описание ветер давление влажность Прогноз дата иконка ветер давление влажность температура воздуха иконка температура воды ветер Температура °C °F Скорость ветра м/с км/ч Давление мм рт. ст. гПа Иконки
Внешний вид Граница Основные цвета — прозрачный фон Дополнительные — прозрачный фон
Текст Шрифт Кодировка UTF-8 Windows-1251 Персонализация Сайт, на котором будет установлен информер Вводите домены через запятую «,» На других сайтах информер работать не будет Электронная почта, на которую отправить код информера
Получить код информера приняв условия использования. |
Показатели даны для примера
Размер информера без полей: x x пикселей Цвет фона вашего сайта Не является частью информера Ссылка на черновик |
Простой информер погоды
Время на прочтение
1 мин
Количество просмотров 3.3K
Недавно мне понадобилось разместить на сайте небольшой погодный информер те варианты, что предлагаются на гисметео не подошли.
После длительного поиска по интернету было обнаружено несколько вариантов разбора кода xml который передает гисметео, но все они были очень сложны и запутаны…
Пришлось написать свой )) получилось на мой взгляд достаточно элегантно… может кому пригодиться.
$url=’http://informer.gismeteo.ru/xml/27612_1.xml’;
$content=file_get_contents($url);
$xml = simplexml_load_string($content);
$tod_array=array(‘ночь’, ‘утро’,’день’,’вечер’);
$rumb_array=array(‘C’, ‘СВ’, ‘В’, ‘ЮВ’, ‘Ю’, ‘ЮЗ’, ‘З’, ‘СЗ’);
$text=»;
if($xml){
$text.='<div class=«block-head red»><h3><a href=»#»>Прогноз погоды</a></h3></div><div class=«iTable»><table width=«100%»>’;
foreach($xml->REPORT->TOWN->FORECAST as $value){
$tod=(int)$value->attributes()->tod;
$text.='<tr><td>’.$tod_array[$tod].'</td><td>’.(int)$value->TEMPERATURE->attributes()->min.’ — ‘.(int)$value->TEMPERATURE->attributes()->max.’ ° C</td><td>’.(int)$value->WIND->attributes()->min.’ — ‘.(int)$value->WIND->attributes()->max.’ мс ‘.$rumb_array[(int)$value->WIND->attributes()->direction].'</td></tr>’;
}
$text.='</table></div>’;
}else{
$text.='<b>Информация не доступна</b>’;
}
echo $text;
Является кроспостом с моего блога
Building a Weather app with JavaScript is an excellent project for beginners. It helps to understand the core basics of the DOM and teaches how to use fetch API, to call and get data from a third-party service.
In this tutorial, we’ll be building a geolocation-based weather app that will show us the current weather data depending on the user’s location.
Prerequisites for this tutorial:
-
Basic HTML
-
Basic CSS (including CSS Flexbox)
-
Basic JavaScript (knowing Javascript promise is a plus)
If you are not familiar with any of that, you can check some fantastic guides below:
-
HTML Course
-
CSS Course
-
JavaScript Course
What will we learn? By building this app, we’ll learn some stuff like,
-
Interacting with the DOM
-
The use of Fetch API
-
The navigator object of JavaScript
-
How to use a third-party API service and more
Now that we have understood the prerequisites and other vital information let’s jump into coding our app.
Markup of the App
The markup or HTML of the app is straightforward. You can see the image below of the final output to get an idea about our markup style.
We have an image that will change according to the weather. The location will be based on the user’s geolocation. Below it is the summary of the weather, the temperature is in both Celcius and Fahrenheit. And in the end, we are showing the sunrise and sunset time. We are also using the Lora google font.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Weather app</title>
<link rel="stylesheet" href="styles.css" />
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,700;1,600&display=swap" rel="stylesheet">
</head>
<body>
<div class="container">
<img src="" alt="" srcset="" id="weather-icon">
<div id="location">Unable to Fetch Weather</div>
<div class="desc">No Information Available.</div>
<div class="weather">
<div class="c">Error</div>
<div class="circle"></div>
<div class="f">Error</div>
</div>
<div class="info">
<h4>Sunrise: <span class="sunrise">No Information Available</span></h4>
<h4>Sunset: <span class="sunset">No Information Available</span></h4>
</div>
</div>
<script src="scripts.js"></script>
</body>
</html>
In the above code, you can see we are using multiple divs with classes and IDs. The classes and IDs are important because we will be using those to interact with the DOM. In the HTML file, we link the CSS file called styles.css and the JavaScript file called scripts.js. The whole information section is wrapped under a div
named container
. The container
contains an image tag with a blank src
attribute, another div
with an ID of location. The div
has a text saying «Unable to fetch weather». A desc
class is added under the location that will show the summary of the weather. And then, we are wrapping the temperatures inside a div
called weather
. The weather class consists of three classes to show Celcius’s temperature, Fahrenheit, and a div
to separate them. Finally, two divs
are used to indicate sunrise and sunset timing.
All the div’s text will be shown when the browser cannot get the users’ geolocation.
Up to this point, our markup will look like this, if you open the above HTML file in browser,
Styling the Markup
Now it’s time to style our app. The styling is also effortless. But before we start styling our app, please make sure you know about CSS flexbox. If you are not familiar with flexbox, check our two-part flexbox series.
-
CSS Flexbox Part 1
-
CSS Flexbox Part 2
Before starting to style our project, we will reset the default margins and paddings of the page.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
We will use the Lora font for the whole document. We will add the font-family
into the body section. The asterisk(*) is a global selector that selects all the elements, and after selecting all the elements, we are setting the margin and padding to 0. The box-sizing:border-box
makes working with flexbox easier.
body {
font-family: 'Lora', serif;
}
The serif font is a fallback to the Lora google font. Now let’s start designing the container. First of all, we need to set up a height and a width. We’ll be using 100 viewport height and 100 viewport width for the container. Then, to center the elements in our app, we’ll take the help of CSS flexbox. To invoke flexbox, we need to specify display:flex
in the container first. To center the elements along the main-axis, we use justify-content:center
, and to center along the cross-axis, we use align-items:center
. We also use the flex-direction: column
here to align the items along the vertical axis. For the background, I am using a radial gradient background. To speed up the process, I am using an online gradient generator tool. The final container styling is pasted below.
.container {
height: 100vh;
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background: rgb(251, 242, 133);
background: radial-gradient(
circle,
rgba(251, 242, 133, 0.6334908963585435) 0%,
rgba(224, 196, 91, 0.8407738095238095) 35%,
rgba(230, 224, 113, 1) 100%
);
}
We will design the temperature section now. It is inside a weather
class div. We are using a flexbox here also.
.weather {
display: flex;
align-items: center;
margin: 15px 0;
font-size: 1.5rem;
}
To add some space below and top of the temperature div
, we add some top and bottom margins. To style the location, we are using an ID of location. And for the description, a class desc
is used.
#location {
font-size: 3rem;
font-weight: 800;
font-style: italic;
}
.desc {
font-size: 1.25rem;
text-transform: capitalize;
}
I think the above lines doesn’t require any explanation. It is pretty self-explanatory. The text-transform: capitalize
property capitalizes the first letter of each word. And we are using rem units here for flexibility. Finally, to create the circle between the two temperatures, we are using a div called circle
. We are giving it a height and width of 15px and then adding a border-radius
of 50px, making it a circle.
.circle {
background-color: black;
border-radius: 50px;
height: 15px;
width: 15px;
margin: 0 15px;
}
Our styling for the app is done. Now it is time for the fun part. Before directly jumping to the JavaScript part, let’s first understand a few basic concepts.
Getting Data from API
The first thing to understand is how do we get the weather data? To get the data, we are dependent on a third-party service. We will use a website called OpenWeatherMap. OpenWeatherMap is a service that provides various weather data through API. We can integrate the API into our app and can use the data on our website. An API is like a waiter, it works as a medium between the server and the client to serve the data to the client according to the client’s request.
OpenWeatherMap is free up to a certain number of requests. After that, it charges money. To use the API, we need an API key. Let’s see how we can get our API key:
Step 1: Open OpenWeatherMap and click on Sign In:
Step 2: Click on «Not Registered? Create an account«, if you don’t have an account,
Step 3: Fill out the form and click on sign up to create your account.
Step 4: Click on API on the menu
Step 5: Because we need the current weather data, we will need to subscribe to the Current Weather Data API subscription. It is the first option you will see in the menu. Click on Subscribe.
Step 6: Now, the pricings window will open. We don’t need any paid plan for this hobby project. So, select the free option here, and we are almost done.
Step 7: After subscribing to it, in the top right corner, where your profile name appears, click on it, and select My API Keys
Step 8: You will find your API key here. Keep it safe, and do not share it publicly with anyone.
Now that we have our API key, we can move forward to building our app again.
In this app, we get the user’s geolocation to show weather data according to the user’s place. To get the geolocation data, we first have to know about the navigator object in JavaScript. The navigator object in JavaScript is used to fetch information related to the user agent or the browser. This object has a property called geolocation
. By using this property, we can get the user’s latitude and longitude. To know more about the navigator
object, check out this awesome article here.
Also Read: Build a Piano App using JavaScript
The JavaScript Part
The first thing that we need to do in our scripts.js
file is to create a variable to store the API key.
// OpenWeatherMap API. Do not share it publicly.
const api = '66869939e0b182ac2d6***********'; //Replace with your API
I am creating a variable called api
and storing my API key there. The next step is to create an event listener that will fire up when the page loads. So, the event we are looking for is load
here. And when the page loads, it will execute some function that we define.
window.addEventListener('load', () => {});
As you can see, we are using an arrow function here. Inside the function, we will create two variables called lat
and long
to store the user’s latitude and longitude. And then, we will use the navigator
object to get the latitude and longitude of the user. We will use an if statement here because many browsers do not allow access to the location. If you want, you can also add an else statement for cases when the location is not available. But for the sake of simplicity, I’ll only use the if statement in this tutorial.
window.addEventListener('load', () => {
let long;
let lat;
// Accessing Geolocation of User
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
});
}
});
The if(navigator.geolocation)
method will check if the object is available in the browser. If it is available, then we will call a method called getCurrentPosition
which is available on geolocation
property. We pass in an argument of position
inside the getCurrentPosition
method. We can name anything for the argument that we are passing. Now, if we console log the position, we will be able to see that we are getting the latitude and longitude. But before showing the values, the browser will ask for our permission to allow the location access.
If you allow your browser to access the location, the console will show your location.
It throws multiple values. But we only need the latitude and longitude values for our app. So, we’ll store these two values inside the variables that we declared before.
window.addEventListener('load', () => {
let long;
let lat;
// Accesing Geolocation of User
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
// Storing Longitude and Latitude in variables
long = position.coords.longitude;
lat = position.coords.latitude;
});
}
});
Every API has a base URL. By giving some arguments to that URL returns the information that we need. For OpenWeatherMap, this URL is https://api.openweathermap.org/data/2.5/weather?, after the question mark(?), we provide some information to the URL, and it returns the values in JSON format. All the API calls are well described in the official documentation of OpenWeatherMap. You can visit their page here. To get the data for a particular latitude and longitude, the below format is used.
https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&appid=${api}&units=metric
Where ${lat}
is the latitude of the user, ${long}
is the longitude of the user, ${api}
is the API key provided by OWM, and at the end, units=metric
is to get the weather data in celsius. We need to store the complete URL inside some variable. For this tutorial, we are storing it inside a variable called base
. After storing it into a variable, if you console log it, you will get a proper URL in return. Now, if you open the URL, you can see all the different information available to you.
Now somehow, we need to extract all these data and show it into our app. Here comes the use of promises and object destructuring. Javascript Promise in itself a vast topic.
Now it is time to use the JavaScript Fetch API. The fetch API enables us to call and get data from API services. We will pass in the base variable inside it. The value that is returned after passing the base URL needs to be converted into JSON format so that we can use it in our app. So, after the first call, we return the response by transforming it to JSON.
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
// Storing Longitude and Latitude in variables
long = position.coords.longitude;
lat = position.coords.latitude;
const base = `https://api.openweathermap.org/data/2.5/weatherlat=${lat}&lon=${long}&appid=${api}&units=metric`;
console.log(base);
fetch(base).then((response) => {
return response.json();
});
});
}
The return response.json();
converts the response to a JSON object. After we get the JSON object, we will extract the values we need for our app. This is done by using JavaScript object destructuring. A brief article about object destructuring can be found here.
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
// Storing Longitude and Latitude in variables
long = position.coords.longitude;
lat = position.coords.latitude;
const base = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&appid=${api}&units=metric`;
// Using fetch to get data
fetch(base)
.then((response) => {
return response.json();
})
.then((data) => {
const { temp } = data.main;
const place = data.name;
const { description, icon } = data.weather[0];
const { sunrise, sunset } = data.sys;
});
});
}
So, after getting the data in JSON format, we extract the values that we are going to use. If you console log the data now, you’ll be able to see we are getting all the data that was previously shown through the base URL. We are extracting the temp
from the main
object and storing it into a variable of the same name temp
. We are getting the name of the place from the name
key of the object. The description and icon code is available in the weather
array inside the object. We only have one array. So, we are accessing that array to get the two values. And finally, the sys
object stores the sunrise and sunset time. We are also storing them into variables of the same name. If you console log the different values now, you’ll be able to see it. But you might get confused about two things, the first one is the sunrise and sunset time and the second one is the icon. Let’s first talk about the icon code. OpenWeatherMap provides icons depending on various weather conditions. And, to show the icons, it gives some icon code. Providing the icon code in a particular URL will return the image. You can see all the icons here. The icon URL is http://openweathermap.org/img/wn/${icon}@2x.png; if we replace the ${icon}
with the icon code, we’ll get the icon according to the weather condition. Now, let’s talk about time. The time that is returned by the API is in epoch format. So, to make it human-readable, we need to convert it to GMT time first. The formula to convert epoch time to GMT using JavaScript is,
const timeInGMT = new Date(epochTime * 1000);
So, we are getting two different times that are to be converted into GMT. Let’s create two variables, one for the sunrise and the other one for the sunset time. And, let’s also create an icon URL that we will put inside the blank img
tag that we created before. And one more thing that we have to do is, convert the Celcius to Fahrenheit because we want to show the temperature in both the degrees. To convert the celsius to Fahrenheit, we use the formula,
fahrenheit = (celcius * 9) / 5 + 32
Now our code will look something like this,
window.addEventListener('load', () => {
let long;
let lat;
// Accesing Geolocation of User
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
// Storing Longitude and Latitude in variables
long = position.coords.longitude;
lat = position.coords.latitude;
const base = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&appid=${api}&units=metric`;
// Using fetch to get data
fetch(base)
.then((response) => {
return response.json();
})
.then((data) => {
console.log(data);
const { temp } = data.main;
const place = data.name;
const { description, icon } = data.weather[0];
const { sunrise, sunset } = data.sys;
const iconUrl = `http://openweathermap.org/img/wn/${icon}@2x.png`;
const fahrenheit = (temp * 9) / 5 + 32;
// Converting Epoch(Unix) time to GMT
const sunriseGMT = new Date(sunrise * 1000);
const sunsetGMT = new Date(sunset * 1000);
});
});
}
});
And we are almost done. We have all the data that we need to show. The only thing that is left, is to access the DOM elements using JavaScript and changing the values. I am pasting the code for selecting the elements below. I think the code do not need any explanation.
const iconImg = document.getElementById('weather-icon');
const loc = document.querySelector('#location');
const tempC = document.querySelector('.c');
const tempF = document.querySelector('.f');
const desc = document.querySelector('.desc');
const sunriseDOM = document.querySelector('.sunrise');
const sunsetDOM = document.querySelector('.sunset');
We are just accessing the DOM elements and storing them into separate variables. We are doing this outside the eventListener
function.
Now, to change the src tag of an image, we access the image element using a selector, here we are selecting using the ID of weather-icon
, now if we use the .src
property over it, we can easily change the image source.
iconImg.src = iconUrl;
We are changing the image URL with the icon URL that we stored before. Rest of the code is very simple.
loc.textContent = `${place}`;
desc.textContent = `${description}`;
tempC.textContent = `${temp.toFixed(2)} °C`;
tempF.textContent = `${fahrenheit.toFixed(2)} °F`;
sunriseDOM.textContent = `${sunriseGMT.toLocaleDateString()}, ${sunriseGMT.toLocaleTimeString()}`;
sunsetDOM.textContent = `${sunsetGMT.toLocaleDateString()}, ${sunsetGMT.toLocaleTimeString()}`;
We are using template literals. The toFixed(2)
method is used so that the degree shows up to two decimal places only. The toLocaleDateString()
and toLocaleTimeString()
methods are used to convert the GMT time and date to local time and date. The .textContent
property sets the inside text with the values passed on the right side. And we are done. The complete JavaScript code will look like this,
// Openweathermap API. Do not share it publicly.
const api = '66869939e0b182ac2d6************'; //Replace with your API
const iconImg = document.getElementById('weather-icon');
const loc = document.querySelector('#location');
const tempC = document.querySelector('.c');
const tempF = document.querySelector('.f');
const desc = document.querySelector('.desc');
const sunriseDOM = document.querySelector('.sunrise');
const sunsetDOM = document.querySelector('.sunset');
window.addEventListener('load', () => {
let long;
let lat;
// Accesing Geolocation of User
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
// Storing Longitude and Latitude in variables
long = position.coords.longitude;
lat = position.coords.latitude;
const base = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&appid=${api}&units=metric`;
// Using fetch to get data
fetch(base)
.then((response) => {
return response.json();
})
.then((data) => {
const { temp } = data.main;
const place = data.name;
const { description, icon } = data.weather[0];
const { sunrise, sunset } = data.sys;
const iconUrl = `http://openweathermap.org/img/wn/${icon}@2x.png`;
const fahrenheit = (temp * 9) / 5 + 32;
// Converting Epoch(Unix) time to GMT
const sunriseGMT = new Date(sunrise * 1000);
const sunsetGMT = new Date(sunset * 1000);
// Interacting with DOM to show data
iconImg.src = iconUrl;
loc.textContent = `${place}`;
desc.textContent = `${description}`;
tempC.textContent = `${temp.toFixed(2)} °C`;
tempF.textContent = `${fahrenheit.toFixed(2)} °F`;
sunriseDOM.textContent = `${sunriseGMT.toLocaleDateString()}, ${sunriseGMT.toLocaleTimeString()}`;
sunsetDOM.textContent = `${sunsetGMT.toLocaleDateString()}, ${sunsetGMT.toLocaleTimeString()}`;
});
});
}
});
The complete source code can be found in this Github repo.
Conclusion
This was our complete weather app from scratch. You can modify it with your styles and preference. This was an attempt to break all the pieces and explain them accordingly. I hope you find it helpful. If you want to build something more using APIs, we have another article about creating a Covid tracker using JavaScript — Create a Javascript Covid 19 Tracker.
Frequently Asked Questions
1. What is JavaScript?
JavaScript is a programming language used to create interactive and dynamic websites.
2. What is a weather API?
A weather API is an interface that provides developers with weather data for a specific location. It typically uses data from weather stations or weather satellites.
3. What are the benefits of building a weather app?
Building a weather app is a great way to improve your JavaScript skills and gain practical experience. It’s also a useful app that can provide valuable information to users.
4. Are there any free weather APIs available?
Yes, there are several free weather APIs available, including OpenWeatherMap, Weather Underground, and AccuWeather.
You may also like:
- Capture Photo using Webcam in Javascript
- JavaScript Text to Speech using SpeechSynthesis Interface
- Adding Iframe to Webpage Dynamically with given HTML Code
- HTML Button with Gradient Background and Shadow using CSS
Информер погоды на сайт
Выберите информер погоды для сайта. Прогноз погоды в HTML информерах предоставляется от 1 до 7 дней. Настройте внешний вид, подходящий вам по цвету и формату, выберите город или населенный пункт, получите код и поместите его на страницах вашего сайта или блога. Использование наших погодных информеров абсолютно бесплатно.
-
ЦветЛюбые цвета и оттенки текста, заголовков и ссылок.
-
РазмерыНастройка произвольного размера.
-
МестоположениеВыбор одного и более городов. 20000 населенных пунктов.
-
КонструкторТемпература, ветер, давление, влажность и другие данные.
Информеры погоды на любой вкус от 1 до 7 дней!
Метеоданные обновляются каждые четыре часа, текущая погода раз в час, курсы валют ЦБ РФ раз в 24 часа.
Адаптивный информер будет подстраиваться под ширину родительского элемента.
Москва
- Пн, 10
сентября+18°C
Ю-В, 1 м/с - Вт, 11
сентября+27°C
С-В, 2 м/с - Ср, 12
сентября+27°C
З, 3 м/с - Чт, 13
сентября+18°C
Ю-В, 1 м/с - Пт, 14
сентября+27°C
С-В, 2 м/с - Сб, 15
сентября+27°C
З, 3 м/с - Вс, 16
сентября+27°C
З, 3 м/с
+28°
Давление: 755 мм
Ветер: С-В, 3 м/с
Влажность: 100%
- Погода сейчас
-
Москва
+24
°
ночью 9°
Ветер: З, 2.4 м/с
Давление: 761 мм
Влажность: 83%Барселона
+9
°
ночью 3°
Ветер: ЮЗ, 3.2 м/с
Давление: 755 мм
Влажность: 21%Париж
+17
°
ночью 11°
Ветер: ЮЗ, 1 м/с
Давление: 750 мм
Влажность: 100%
Сочи
17 сентября
День+21°C3 м/с74540%
Ночь+21°C3 м/с74540%
18 сентября
День+21°C3 м/с74540%
Ночь+21°C3 м/с74540%
Омск+21°CМалооблачно, небольшой дождь, гроза, 2 м/с СЗ, 747 мм рт., ст. 70 % влажн.
Новосибирск+21°Малооблачно, небольшой дождь, гроза, 2 м/с СЗ, 747 мм рт., ст. 70 % влажн.
Челябинск
Ночь+12°C
Утро+18°C
День+24°C
Ветер+21°C
Москва+21°C
-
Анапа +15°C
ЮЗ, 6 м/с, 745 мм
Москва+25°C
ЮЗ, 6 м/с, 745 мм
Как создать погодный информер
Содержание
- 1 Информер погоды своими руками
- 2 Нам поможет Яндекс
- 2.1 id города для информера погоды
- 2.2 Время кеширования скрипта
- 2.3 Картинки для информера погоды
- 3 FIX информера погоды (март 2016 года)
Погода — всегда восстребованная в интернете информация. Мало новостных сайтов обходятся без информеров погоды: читателям обязательно предоставляют такую информацию на сегодня, завтра, послезавтра, реже на больший период времени. Да и каждый по себе сможет посудить о востребованности такой информации: ведь все мы чаще всего получаем прогноз погоды для своего города именно с городского новостного портала.
Прогноз погоды для своих сайтов новостные ресурсы реализовывают по-разному, чаще в виде готовых информеров с сторонних сервисов, которые легко интегрируются на сайт. Основное преимущество таких информеров погоды в том, что вебмастеру не надо беспокоиться об актуальности данных о погоде или работе скрипта информера: поставил на сайт и забыл! Но и минусы такого «взаимовыгодного сотрудничества» очевидны. Среди минусов погодных информеров с других сайтов:
- подгрузка данных на вашем сайте с других серверов;
- зачастую, внешняя ссылка, ведущая на сервис, отдающий погоду для информера;
Это основные, но не все «тормоза», которые обеспечивают веб-сайтам информеры погоды с внешних сервисов. Но так ли все безнадежно в эпоху, когда каждый третий школьник программирует на Р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'=>'↑ ю','n'=>'↓ с','w'=>'→ з','e'=>'← в','sw'=>'↗ юз','se'=>'↖ юв','nw'=>'↘ сз','ne'=>'↙ св'); 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, 952 downloads)
В архиве картинки лежат в папке pogoda и в скрипте (если сам скрипт будет рядом с папкой) подключаются кодом: <img src=»pogoda/… Не забудьте отредактировать этот параметр, если Вами будут внесены изменения в путях к картинкам.
Собственно и все! Информер погоды для сайта готов: скачивайте, внедряйте, пользуйтесь! Информируйте своих посетителей сайта о погодных условиях в Вашем городе, безусловно, те будут вам благодарны!
Ах, да! Пример забыл показать! Вот он (погода на 10 дней для Москвы):
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 файла с погодой на серверах Яндекса и показываем посетителям закешированные данные с нашего сайта.