weatherman или сбор статистики о погоде через METAR

Давно мечтал про скрипт, накапливающий статистику по изменению температуры и давления. Год назад, написал крошечный парсер на питоне, выгребающий из интернета metar-файл для моего города и парсящий из него давление и температуру.

Работает он так:

vik@firefly:~/blog$ python ~/bin/metar.py
на 22:00
-02 °C 1010 гПа

В конки встроен с помощью строки:

${offset 140}За бортом:${color green} ${execi 600 python /home/vik/bin/metar.py | tail -n 1 }${color }

Краткие пояснения по тому, как я пришел к идее (фактически склепал на коленке — питон хорош в том числе тем, что позволяет «думать руками»), я вынес в приложение.

Дальше дело застопорилось. То ли мне не хватило вренмени, то ли что-то еще. Скорее всего, я хотел реализовать весь процесс одним скриптом и в итоге не нашел для этого времени.

Пару дней назад, разбирая conky-систему, нашел этот скрипт и кое-что в нем поправил.

Сегодня меня (после очередного скачка атмосферного давления, на которое мое серое вещество не очень хорошо реагирует) осенило — раз скрипт выдает данные (и справляется неплохо, не смотря на примитивность) — почему бы не перенаправить их в файл и завязать все это на крон? Получится именно такой сборщик статистики, которого мне хотелось. А сам файл, можно будет потом скормить gnuplot’у, ну или libreoffic’у в худшем случае.

Сказано-сделано.

Сначала я обработал вывод так, как мне хотелось:

vik@firefly:/media/EXT/blog$ metar.py
на 20:39
-02 °C 1010 гПа
vik@firefly:/media/EXT/blog$ metar.py | tail -n 1
-02 °C 1010 гПа
vik@firefly:/media/EXT/blog$ metar.py | tail -n 1 | awk '{print $3}'
1010
vik@firefly:/media/EXT/blog$ metar.py | tail -n 1 | awk '{print $1}'
-02

Датастамп я сделал через date… почитал мануал, и нашел в нем два чудесных стампа %F и %R — дата и время в том формате, который я использую везде. Между ними — пробел с экранированием.

vik@firefly:/media/EXT/blog$ date +%F\ %R
2013-03-26 20:56

В итоге получилось следующее:

#!/bin/bash
date +%F\ %R
python metar.py | tail -n 1 | awk '{print $3}'
python metar.py | tail -n 1 | awk '{print $1}'

Мне нужно было, чтобы скрипт печатал все в одну стоку — поэтому, я добавил удаление концов строк:

#!/bin/bash
date +%F\ %R  | tr '\n' ' '
python metar.py | tail -n 1 | awk '{print $3}' | tr '\n' ' '
python metar.py | tail -n 1 | awk '{print $1}'

Итого:

#!/bin/bash
echo `date +%F\ %R  | tr '\n' ' ' & python /home/vik/bin/metar.py | tail -n 1 | awk '{print $3}' | tr '\n' ' ' & python /home/vik/bin/metar.py | tail -n 1 | awk '{print $1}' ` >> ~/weatherman

Ну и в кронтаб ушло:

@hourly /home/vik/bin/weatherman

Сам файл выглядит так:

2013-03-26 21:11 -01 1010
2013-03-26 22:11 -02 1009

Каждый час туда сбрасывается статистика — которую, как я говорил выше можно обработать каким-нибудь визуализатором.

Mission accomplished :)


Приложение

Мои заметки по ходу конструирования скрипта для парсинга METAR. На правах потока сознания :)

2011-10-11 14:34

Нужно собрать данные по погоде за несколько дней и построить из них график. Так же неплохо для conky сделать анализ — текущие данные + прогноз.

Общая идея:

METAR — формат в котором раздаются погодные файлы.

UKOO — аэропорт Одессы — дает хорошее приближение. По давлению во всяком случае — точно.

На сайте http://weather.noaa.gov/weather/metar.shtml лежат (а) быстрые сводки (б) циклофайлы.

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

файл лежит тут:

http://weather.noaa.gov/pub/data/observations/metar/stations/UKOO.TXT

на данный момент:

2011/10/11 11:30
UKOO 111130Z 04003MPS 010V080 9999 FEW023 BKN100 13/09 Q1013 34090060 NOSIG

UKOO — обозначение Одессы
111130Z — число и время наблюдения (почему месяц 11?) Z — Zulu = UTC
04003MPS — направление и скорость ветра (40 градусов, 3 мили в секунду)
010V080 — информация о минимальной видимости у земли
9999 — видимость
FEW023 — облачность
BKN100
13/09 — температура/точка росы
если стоит M — минус
Q1013 — давление 1013 гПаскал
34090060
NOSIG — изменений не ожидается

Odesa, Ukraine (UKOO) 46-26N 030-46E 42M
Oct 11, 2011 - 07:30 AM EDT / 2011.10.11 1130 UTC
Wind: from the NE (040 degrees) at 7 MPH (6 KT) (direction variable):0
Visibility: greater than 7 mile(s):0
Sky conditions: mostly cloudy
Temperature: 55 F (13 C)
Dew Point: 48 F (9 C)
Relative Humidity: 76%
Pressure (altimeter): 29.91 in. Hg (1013 hPa)
ob: UKOO 111130Z 04003MPS 010V080 9999 FEW023 BKN100 13/09 Q1013 34090060 NOSIG
cycle: 11

Обработка:

>>> a = "UKOO 111130Z 04003MPS 010V080 9999 FEW023 BKN100 13/09 Q1013 34090060 NOSIG"
>>> a.split()
['UKOO', '111130Z', '04003MPS', '010V080', '9999', 'FEW023', 'BKN100', '13/09', 'Q1013', '34090060', 'NOSIG']
>>> s = a.split()
>>> len(s)
11

Температура и точка росы

>>> s[7]
'13/09'
>>> s[7].split('/')
['13', '09']
>>> s[7].split('/')[0]
'13'
>>> s[7].split('/')[1]
'09'
>>>

Давление:

>>> s[8][1:]
'1013'

Лучше с поиском:

>>> for i in s:
...     if '/' in i:
...             print i.split('/')[0]
... 
13

Давление:

>>> for i in s:
...     if i[0] == 'Q':
...             print i[1:]
... 
1013

Как получить файл?

>>> import urllib
>>> sock = urllib.urlopen("http://weather.noaa.gov/pub/data/observations/metar/stations/UKOO.TXT")
>>> htmlSource = sock.read()
>>> sock.close()
>>> print htmlSource
2011/10/11 12:00
UKOO 111200Z 01006MPS 9999 -SHRA FEW040CB BKN100 13/09 Q1012 34090060 NOSIG

>>> htmlSource
'2011/10/11 12:00\nUKOO 111200Z 01006MPS 9999 -SHRA FEW040CB BKN100 13/09 Q1012 34090060 NOSIG\n'
>>> htmlSource.split()
['2011/10/11', '12:00', 'UKOO', '111200Z', '01006MPS', '9999', '-SHRA', 'FEW040CB', 'BKN100', '13/09', 'Q1012', '34090060', 'NOSIG']

Итоговый скрипт:

#! /usr/bin/python
# -*- coding: utf8 -*-
""" мой модуль для чтения METAR информации """

import urllib

# получаем данные для Одессы

sock = urllib.urlopen("http://weather.noaa.gov/pub/data/observations/metar/stations/UKOO.TXT")
metar = sock.read()
sock.close()

# print metar

# разбиваем на строки
line = metar.split('\n')

# парсим файл
par = line[1].split()

# находим дату

for i in par:
    if i[-1] == 'Z':
        timeUTC = int(i[2:4])
        timeOD = timeUTC+2
        strtime = str(timeOD)
        print 'на '+strtime+':'+i[4:6]

# находим температуру
for i in par:
    if '/' in i:
        temp = i.replace('M','-')
        temp = temp.split('/')[0]+' °C'
        print temp,

# находим давление
for i in par:
    if i[0] == 'Q':
        print i[1:]+' гПа'
Реклама

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

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: