Парсим данные с GisMeteo в bash’е

Парсим данные с GisMeteo в bash'еЕсли вы вдруг каким-то чудом еще не слышали про сайт gismeteo.ru, то, в двух словах, это сайт, на котором публикуется текущая информация о погоде для различных населенных пунктов. Чтобы посмотреть, что сейчас примерно на улице за погода (с определенной погрешностью, естественно), достаточно открыть сайт и посмотреть. Кроме того, у этого сайта есть возможность получать данные в формате XML.

Но мы не будем пользоваться форматом XML, потому что для корректного разбора xml обычно используются дополнительные программы. Мы воспользуемся другими программами, которые обычно в системе уже присутствуют (за исключением curl, который по умолчанию имеется не во всех системах) — bash, sed и curl. Curl нужен только для получения странички по протоколу https, и вместо него можно воспользоваться любой другой программой, которая может получить страничку по https и вывести ее в терминал (это может сделать и wget, и links), можно использовать ту программу, которая вам больше нравится.

Главная задача этого скрипта — выводить в консоль информацию о погоде в текстовом режиме. Чем этот скрипт может быть еще полезен? Тем что результат его работы можно использовать для отправки себе в качестве SMS, по электронной почте или использовать для отображения на рабочем столе при помощи conky.

Для настройки скрипта потребуется адрес страницы, на которой находятся данные о погоде в соответствующем городе. У меня это будет Санкт-Петербург. Вы можете свой URL найти просто скопировав из браузера адрес страницы и вставив его в скрипт.

#!/bin/bash

CITY_URL="https://www.gismeteo.ru/city/daily/4079/"
curl $CITY_URL 2>/dev/null \
| sed -nre '/section higher/,/мм рт. ст./p' \
| sed -r '/section higher|cloudness|wicon wind|crumb|scity|\/div|value m_temp f|m_wind mih|m_wind kmh|png|\/dl|class="temp|wicon barp|dt/d' \
| sed -r 's/(.*)class="type(.*)>(.*)<\/h2>/Город: \3/' \
| sed -r 's/(.*)<dd(.*)td>(.*)<\/td(.*)\/dd>/Погода: \3/' \
| sed -r 's/(.*)<dd class=(.*)>(.*)<span class="meas(.*)span><\/dd>/Температура воздуха: \3 C/' \
| sed -r 's/(.*)value m_wind ms(.*)>(.*)<span class="unit">(.*)<\/span><\/dd>/Ветер: \3 \4/' \
| sed -r 's/(.*)value m_press torr(.*)>(.*)<(.*)>(.*)<\/span><\/dd>/Давление: \3 \5/'

Если не совсем понятно, немного поясню, что происходит. Скачиваем curl’ом страничку, выводим ее в стандартный потов вывода, а ошибки в /dev/null. Затем удаляем все ненужные строки, оставляем только те, которые содержатся между строкой с подстрокой «section higher» и «мм рт. ст.» включительно. Таким образом удалится информация о температуре воды, но это в моем случае не страшно, потому что Питер не самый курортный город, и о влажности воздуха, что тоже не страшно, потому что влажность обычно не самая низкая. Затем из оставшихся строк снова удаляем ненужные, достаем название города, состояние атмосферы (ясно, пасмурно, облачно), температуру воздуха, скорость ветра и атмосферное давление.

И, собственно, всё. После запуска скрипта получаем такой вот вывод:

$ ./gm.sh
Город: Санкт-Петербург
Погода: Пасмурно
Температура воздуха: +15 C
Ветер: 2 м/с
Давление: 766 мм рт. ст.

 

Парсим данные с GisMeteo в bash’е: 8 комментариев

  1. #kstn

    Пардон, память девичья, не помню с Вами говорил или где-то еще — имейте в виду — гисметео врет. До +\- 5 градусов в сравнении с градусником за окном. Яндех тоже вред, но с погодой на данный момент времени — более-менее честен.

    А для xml люто-бешено рекомендую xmlstarlet — лучшее из того что я видел для связки xml + bash

    1. mnorin Автор записи

      Да-да, здесь говорили :) Он, похоже, не везде врет до 5 градусов.
      xmlstarlet плюсану, хорошая штука.

      1. #kstn

        Ради спортивного интереса — версия с xml

        #!/bin/bash
        
        USER_AGENT="Opera/9.80 (X11; Linux $(uname -m); Ubuntu/14.10) Presto/2.12.388 Version/12.16"
        CITY=27612
        
        if [[ ! $(which "xml" 2>/dev/null) ]]; then
            echo "You need xmlstarlet"
        fi
        
        curl -s -A "${USER_AGENT}" "http://informer.gismeteo.ru/rss/${CITY}.xml" | \
            xml sel -t -m 'rss/channel/item' -v 'title' -n -v 'description' -n
        

        PS на curl без юзерагента — обижается. Ишь какие корыстные.

        1. mnorin Автор записи
          - echo "You need xmlstarlet"
          + echo "You need xmlstarlet"; exit
          

          Иначе curl | xml выполнится всегда

          1. #kstn

            Ваша правда — недопечатал. Ну кто не лабал — тот не лажался :)

  2. #kstn

    Кстати, ИМХО, зря Вы так сразу безапелляционно отметаете XML — иногда их даже sedом удобнее парсить, чем html

  3. vmamaev

    Я слегка допилил этот плагин, теперь он результат обращения на gismeteo пишет в файлик, и показывает содержимое этого файла до тех пока файлик не состарится на 30 минут с момента создания. Как только 30 минут проходит и файл становится «старым», то происходит повторный запрос на сервер gismeteo за актуализацией данных.

    Хотел попробовать что-то написать на bash… можно считать это первой моей попыткой.

    Спасибо вам за скриптик.

    _______________________________

    #!/bin/bash
    
    CITY_URL="https://www.gismeteo.ru/city/daily/4429/"
    TXT_FILE="/home/vmamaev/.conky/wheather/temp"
    
    remote_fetch(){
    	curl $CITY_URL 2>/dev/null \
    	| sed -nre '/section higher/,/мм рт. ст./p' \
    	| sed -r '/section higher|cloudness|wicon wind|crumb|scity|\/div|value m_temp f|m_wind mih|m_wind kmh|png|\/dl|class="temp|wicon barp|dt/d' \
    	| sed -r 's/(.*)class="type(.*)>(.*)/Город: \3/' \
    	| sed -r 's/(.*)(.*)/Погода: \3/' \
    	| sed -r 's/(.*)(.*)/Температура воздуха: \3 C/' \
    	| sed -r 's/(.*)value m_wind ms(.*)>(.*)(.*)/Ветер: \3 \4/' \
    	| sed -r 's/(.*)value m_press torr(.*)>(.*)(.*)/Давление: \3 \5/' > $TXT_FILE
    }
    
    if [ -f "$TXT_FILE" ]
    then
    	# echo "$TXT_FILE found."
    	now_date=$(date +'%Y-%m-%d')
    	file_date=$(date -r $TXT_FILE +%F)
    	if [ "$now_date" = "$file_date" ]
    	then
    		# echo "$TXT_FILE only display."
    		if test `find "$TXT_FILE" -mmin +30`
    		then
    			# echo "File older then 30 min"
    			remote_fetch
    		fi
    		echo "$(cat $TXT_FILE)"
    	else
    		# echo "$TXT_FILE refetch and display"
    		remote_fetch
    		echo "$(cat $TXT_FILE)"
    	fi
    else
    	# echo "$TXT_FILE not found."
    	remote_fetch
    	echo "$(cat $TXT_FILE)"
    fi
    exit 0
  4. Vladimir

    подскажите как этот плагин реализовать на php ?

Обсуждение закрыто.