leopardgeckoのブログ

Macの関連事項など

GeekToolでお天気表示

注:ここの記事は新たに書き直しました。
GeekToolでお天気表示 改訂版を参照してください。

追記:
2016年12月12日:天気の表示に「&」が含まれていると表示がおかしくなる問題を修正。
2017年 7月26日:httpsを指定しないと表示できなくなったようなのでスクリプトを修正。プロキシについての記述追加。

Mac用デスクトップカスタマイズソフトのGeekToolスクリプト次第でほぼ何でもできる優れものです。ただしスクリプトをいちいち書かなければいけないという難点があります。単純なものであれば良いのですが、例えば天気を表示しようと思えば天気予報サイトをソースから解析しなければなりませんし、せっかくスクリプトを書いても仕様が変更されればまた解析からやり直さなければなりません。

それを自分で一から全てやるのは結構な手間ですから、今回は天気予報サイトのAccuWeatherから取得した天気を表示させるスクリプトをいくつかご紹介します。

例えば下の画像のような感じで表示させるとします。上段が本日の最高・最低気温と現在の気温・天気です。中段が時間単位の天気予報でとりあえず16時間後まで表示。下段が明日と週末の天気予報です。

f:id:leopardgecko:20161025133927p:plain

 

現在の気温と天気を表示してリアルな画像の天気アイコンを取得するスクリプトは以下の通りです。GeelToolの「Shell」をデスクトップの好きなところに貼り付けて「Command」にコピペしてください。スクリプトの「https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230」の部分は、https://www.accuweather.com/en/jp/japan-weatherにアクセスしてお住いの市や区の名前をローマ字で検索し、出てきたURLに変更してください。この例では東京都江東区の天気が表示されます。また、ここでの「koto-ku」と「221230」にあたる文字と数値は他のスクリプトの書き換えにも使いますので記録しておいてください。

天気アイコンの画像は「/tmp/weather_now.png」に保存されるので、GeekToolの「Image」でURLを「file://localhost/private/tmp/weather_now.png」と指定してください。

画像をリアルではなく他と同じシンプルなものにしたい場合は、スクリプトの最後の方の「https://vortex.accuweather.com/adc2010/images/icons-numbered/」のところを「https://vortex.accuweather.com/adc2010/images/slate/icons/」に変えてください。 

社内での使用などでプロキシを指定する必要がある場合は、「curl」の後に「--proxy http://hogehoge:8080」のような形で指定してください。例えば「# 元データ取得」のところであれば、「weather_data=`curl --proxy http://hogehoge:8080 --silent "https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230"`」のような記述になります。一番最後の行で「curl」が出てくるところも同じように記述を追加してください。他のスクリプトでも「curl」のところは全て追加が必要です。

# 現在の天気
# 元データ取得 weather_data=`curl --silent "https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230"` # 現在の温度と天気を取得して表示 echo "$weather_data" | grep -A 8 'Current Weather' | grep -e 'large-temp\|cond' | sed -e 's/<[^>]*>//g' | sed -e 's/&deg;/°/g' -e 's/^ *//' | tr "\r\n" " " # 天気アイコンのナンバーを取得し二桁でゼロパディングする icon_cur=`echo "$weather_data" | grep -A 2 'Current Weather' | grep 'icon' | sed -e 's/[^"]*"\([^"]*\)".*/\1/' | tr -cd '0123456789' | awk '{printf "%02d", $1}'` # 天気アイコンナンバーをURLに変換して画像を保存 echo "https://vortex.accuweather.com/adc2010/images/icons-numbered/"$icon_cur"-xl.png" | xargs curl --silent -o /tmp/weather_now.png

 

最高気温と最低気温の表示は以下の通りです。AccuWeatherでは夜になると最低気温のみの表示に変わるのですが、それにも対応させてあります。

「koto-ku」と「221230」と書いてあるところは上と同じ要領でお住いの地域に適宜変更してください。以下のスクリプトも同様です。

# 最高気温と最低気温
# 元データ取得 weather_today=`curl --silent "https://www.accuweather.com/en/jp/koto-ku/221230/daily-weather-forecast/221230?day=1"` # 今日の最高温度と最低温度を取得して表示 echo "$weather_today" | grep -A 6 'Today\|Tonight' | grep -e 'large-temp\|small-temp\|temp-label tonight selected' | sed -e 's/<[^>]*>//g' | sed -e 's/&deg;/°/g' -e 's/^ *//' | tr "\r\n" " "

 

 以下は現在時刻から8時間後までと、9時間後から16時間後までのスクリプトです。これは等幅フォントを指定しないと表示がずれますのでご注意を。(上の画像ではRicty Discordというプログラミング用の等幅フォントを使っています)

天気アイコンの画像は「/tmp/weather_hour_0.png」から連番で「/tmp/weather_hour_7.png」まで保存されるので、上の応用で画像を一つずつ貼り付けて並べてください。

視認性を上げるためにamとpmの色を変えていますが、色を変えたくない場合は「時刻を左揃え8桁で表示」のところの「 | sed -e s/am/`echo "\033[0;31mam\033[0m"`/g -e s/pm/`echo "\033[0;34mpm\033[0m"`/g」をごそっと削除してください。(「printf "%-8s" ${current_time[*]}」だけ残す)

まず一つ目、現在時刻から8時間後までのスクリプトはこんな感じです。

# 現在時刻から8時間後までの天気
# 元データ取得 my_hour=`date +%H` curl_data=`curl --silent "https://www.accuweather.com/en/jp/koto-ku/221230/hourly-weather-forecast/221230?hour=$my_hour"` # 8時間分の時刻を取得(後で配列変数として使う。以下同様) current_time=(`echo "$curl_data" | grep -A 37 "overview-hourly" | grep -A 29 "first-col" | sed -e 's/<[^>]*>//g' -e 's/^ *//' | tr -d "\r"`) # 8時間分の天気を取得(スペースを含んだデータをIFSを使って配列に格納) _IFS="$IFS";IFS="_" current_weather=(`echo "$curl_data" | grep -A 67 "overview-hourly" | grep -A 23 "Forecast" | sed -e 's/<[^>]*>//g' -e 's/^ *//' -e '1,2d' -e 's/ \&amp;/\&/g' | tr -s '\r\n' '_'`) IFS="$_IFS" # 8時間分の天気アイコンのナンバーを取得 current_icon=(`echo "$curl_data" | grep -A 38 "overview-hourly" | grep 'icon' | sed -e 's/[^"]*"\([^"]*\)".*/\1/' | tr -cd '0123456789\n'`) # 時刻を左揃え8桁で表示 printf "%-8s" ${current_time[*]} | sed -e s/am/`echo "\033[0;31mam\033[0m"`/g -e s/pm/`echo "\033[0;34mpm\033[0m"`/g # 天気を左揃え8桁かつ2段で表示 for (( i=0; i < ${#current_weather[@]}; ++i)) do echo "${current_weather[$i]}" | awk '{printf "%-8s", $1}' done echo for (( i=0; i < ${#current_weather[@]}; ++i)) do echo "${current_weather[$i]}" | awk '{printf "%-8s", $2}' done # 天気アイコンを取得して保存(URLに使うアイコンのナンバーはゼロパディングする) for (( i=0; i < ${#current_icon[@]}; ++i)) do current_icon[$i]=`printf "%02d" ${current_icon[$i]}` echo "https://vortex.accuweather.com/adc2010/images/slate/icons/${current_icon[$i]}-s.png" | xargs curl --silent -o /tmp/weather_hour_$i.png done

 

9時間後から16時間後まではこんな感じ。上のスクリプトの応用ですから内容はほとんど同じです。「later=」の後の数値を「16」にすれば17時間後から24時間後の表示にすることもできます。天気アイコンの画像は「/tmp/weather_hour_8.png」から連番で「/tmp/weather_hour_15.png」まで保存されます。

# 9時間後から16時間後までの天気
# 何時間後? later=8 # 元データ取得 my_hour=`date +%H` ; my_hour=`expr $my_hour + $later` curl_data=`curl --silent "https://www.accuweather.com/en/jp/koto-ku/221230/hourly-weather-forecast/221230?hour=$my_hour"` # 時刻を取得 current_time=(`echo "$curl_data" | grep -A 37 "overview-hourly" | grep -A 29 "first-col" | sed -e 's/<[^>]*>//g' -e 's/^ *//' | tr -d "\r"`) # 天気を取得(スペースを含んだデータをIFSを使って配列に格納) _IFS="$IFS";IFS="_" current_weather=(`echo "$curl_data" | grep -A 67 "overview-hourly" | grep -A 23 "Forecast" | sed -e 's/<[^>]*>//g' -e 's/^ *//' -e '1,2d' -e 's/ \&amp;/\&/g' | tr -s '\r\n' '_'`) IFS="$_IFS" # 天気アイコンのナンバーを取得 current_icon=(`echo "$curl_data" | grep -A 38 "overview-hourly" | grep 'icon' | sed -e 's/[^"]*"\([^"]*\)".*/\1/' | tr -cd '0123456789\n'`) # 時刻を左揃え8桁で表示 printf "%-8s" ${current_time[*]} | sed -e s/am/`echo "\033[0;31mam\033[0m"`/g -e s/pm/`echo "\033[0;34mpm\033[0m"`/g # 天気を左揃え8桁かつ2段で表示 for (( i=0; i < ${#current_weather[@]}; ++i)) do echo "${current_weather[$i]}" | awk '{printf "%-8s", $1}' done echo for (( i=0; i < ${#current_weather[@]}; ++i)) do echo "${current_weather[$i]}" | awk '{printf "%-8s", $2}' done # 天気アイコンを取得して保存(取得するアイコンのナンバーはゼロパディングする) for (( i=0; i < ${#current_icon[@]}; ++i)) do current_icon[$i]=`printf "%02d" ${current_icon[$i]}` echo "https://vortex.accuweather.com/adc2010/images/slate/icons/${current_icon[$i]}-s.png" | xargs curl --silent -o /tmp/weather_hour_`expr $i + $later`.png done

 

明日の天気は以下の通り。AccuWeatherでは深夜を過ぎるとその日の早朝の天気に表示が変わりますが、それにも対応させてあります。天気アイコンは「/tmp/weather_tomorrow.png」に保存されます。

# 明日の天気取得・表示
weather_data=`curl --silent "https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230"`

echo "$weather_data" | grep -e 'Tomorrow\|Early' | sed -e 's/<[^>]*>//g' -e 's/^ *//' 
echo "$weather_data" | grep -A 9 'Tomorrow\|Early' | grep -e 'large-temp\|cond' | sed -e 's/<[^>]*>//g' | sed -e 's/&deg;/°/g' -e 's/^ *//' | tr "\r\n" " "

# 明日の天気アイコンのナンバーを取得しゼロパディングする
icon_data=`echo "$weather_data" | grep -A 2 'Tomorrow\|Early' | grep 'icon' | sed -e 's/[^"]*"\([^"]*\)".*/\1/' | tr -cd '0123456789' | awk '{printf "%02d", $1}'`

# 天気アイコン保存 echo "https://vortex.accuweather.com/adc2010/images/slate/icons/"$icon_data"-l.png" | xargs curl --silent -o /tmp/weather_tomorrow.png

 

週末の天気は以下の通り。天気アイコンの場所は土曜日が「/tmp/weather_sat.png」、日曜日が「/tmp/weather_sun.png」です。

# 土日の天気取得・表示
weather_weekend=`curl --silent "https://www.accuweather.com/en/jp/koto-ku/221230/weekend-weather/221230"`

echo "\033[0;34mSaturday\033[0m"
echo "$weather_weekend" | grep -A 9 'Saturday' | grep -e 'large-temp\|cond' | sed -e 's/<[^>]*>//g' | sed -e 's/&deg;/°/g' -e 's/^ *//' | tr "\r\n" " "
echo "\n\033[0;31mSunday\033[0m"
echo "$weather_weekend" | grep -A 9 'Sunday' | grep -e 'large-temp\|cond' | sed -e 's/<[^>]*>//g' | sed -e 's/&deg;/°/g' -e 's/^ *//' | tr "\r\n" " "

# 土日の天気アイコン取得
icon_sat=`echo "$weather_weekend" | grep -A 2 'Saturday' | grep 'icon' | sed -e 's/^ *//' -e s/'<div class=\"icon '//g -e s/' \"><\/div>'//g -e s/i-//g -e 's/\([0-9]*\).*/\1/' | tr -d '\n' | tr -d '\r'`
icon_sat=`printf "%.2d\n" $icon_sat`
icon_sun=`echo "$weather_weekend" | grep -A 2 'Sunday' | grep 'icon' | sed -e 's/^ *//' -e s/'<div class=\"icon '//g -e s/' \"><\/div>'//g -e s/i-//g -e 's/\([0-9]*\).*/\1/' | tr -d '\n' | tr -d '\r'`
icon_sun=`printf "%.2d\n" $icon_sun`

# 天気アイコン保存 echo "https://vortex.accuweather.com/adc2010/images/slate/icons/"$icon_sat"-l.png" | xargs curl --silent -o /tmp/weather_sat.png echo "https://vortex.accuweather.com/adc2010/images/slate/icons/"$icon_sun"-l.png" | xargs curl --silent -o /tmp/weather_sun.png

 

他にもAccuWeatherには色々な予報がありますので、これまでに挙げたスクリプトの仕組みがわかれば様々な応用が可能でしょう。要はHTMLソースの中から欲しい情報をゲットするためのキーワードを拾ってHTMLタグを除去してテキストを整形しているだけですから、キーワードを確実に拾えるパターンを見つけさえすればOKです。