leopardgeckoのブログ

Macの関連事項など

GeekToolでお天気表示 改訂版

この記事は必要に応じて適宜更新します。下の更新履歴も参照してください。最終更新日:2018/12/12

はじめに

GeekToolとはMacのデスクトップをカスタマイズできるソフトです。デスクトップに色々なものを表示できて便利なのですが、スクリプトが公開されているものでなければ自分でスクリプトを書かなければなりません。
天気を表示するスクリプトはネットで公開されているものは情報が古くて今では使えないものが多い上に自力で作るとなるとHTMLソースを解析する必要があるなど結構大変な作業が必要になります。そこでこちらではAccuWeatherという天気予報サイトを利用したスクリプトをご紹介します。私自身も使っているものなので、天気予報サイトの仕様変更などがあった場合にはそれに対応すべく適宜更新していく予定です。
(GeekTool自体の使い方は他の入門用サイトを参照してください)

例えば下の画像のような感じで表示させるとします。一番上の小さめの文字が本日の最高・最低気温。その右が直近2時間くらいの変化を教えてくれる予報。一番大きな文字が現在の気温・天気、その左が現在の天気の画像です。中段のずらっと並んだ画像と文字が時間単位の天気予報で、とりあえず16時間後まで表示しています。下段が明日と週末の天気予報です。それぞれ別のスクリプトなので、どれか好きなものだけ表示させることもできます。

f:id:leopardgecko:20171124123511p:plain

<各スクリプトの説明>

現在の気温と天気

現在の気温と天気を表示してリアルな画像の天気アイコンを取得するスクリプトを下に示します。Propertiesウインドウの「Refresh every 〜s」のところで表示を更新する秒数を設定するのを忘れないでください。

このままでは東京都江東区の天気が表示されてしまうので、スクリプトを書き換える必要があります。まずhttps://www.accuweather.com/en/jp/japan-weatherにアクセスして、天気を表示したい市や区の名前をローマ字で入力して検索すると、その地域の天気が表示されるようになります。その段階でWebブラウザに表示されているURLを記録してください。「https://www.accuweather.com/en/jp/場所/数字/weather-forecast/数字」のような形式になっているはずです。下のスクリプトの「# 場所のURL」の下に「weather_url="https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230"」という記述がありますが、この赤い文字で示した部分が表示したい場所のURLなので、ここを上で記録したURLに書き換えてください。このURLは他のスクリプトでも使います。

(社内での使用などでプロキシを指定する必要がある場合は、「# プロキシ」の次の行の「weather_proxy=""」を「weather_proxy="--proxy http://hogehoge:8080"」のように適宜書き換えてください)

天気アイコンの画像は「/tmp/weather_now.png」に保存されるので、GeekToolの「Image」をデスクトップにドラッグ&ドロップしてURLを「file://localhost/private/tmp/weather_now.png」と指定してください。上のスクリプトと同じようにRefreshの秒数設定も忘れずに。

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

# 現在の気温と天気のスクリプト

# 場所のURL
weather_url="https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230"

# プロキシ
weather_proxy=""

# 元データ取得
weather_data=`curl -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X)' $weather_proxy --silent $weather_url`

# 現在の温度と天気を取得して表示
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 $weather_proxy --silent -o /tmp/weather_now.png

最高気温と最低気温

最高気温と最低気温の表示は以下の通りです。AccuWeatherでは夜になると最低気温のみの表示に変わるのですが、それにも対応させてあります。「場所のURL」は上と同じように天気を表示したい地域のURLに書き換えて、必要がある方はプロキシも書き換えてください。以下のスクリプトも全て同様です。

# 最高気温と最低気温のスクリプト

# 場所のURL
weather_url="https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230"

# プロキシ
weather_proxy=""

# 元データ取得
weather_today=`curl -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X)' $weather_proxy --silent ${weather_url/weather-forecast/daily-weather-forecast}"?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" " "

直近の天気予報 NEW!!

直近2時間くらいの天気の変化を教えてくれます。AccuWeatherではこの予報を「minute cast」と呼んでいるようです。上の画像では46分後に雨が降ってくる予報になっています。一時的な雨のときは時間単位の予報に表示されないこともあるので、これもチェックしておくと安心でしょう。
天気に変化があるときは分単位で表示が変わるので、Refreshは60秒くらいに設定しておくのがお勧めです。スクリプトは以下の通りです。

# MINUTECASTのスクリプト

# 場所のURL
weather_url="https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230"

# プロキシ
weather_proxy=""

# 元データ取得
weather_data=`curl -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X)' $weather_proxy --silent ${weather_url/weather-forecast/minute-weather-forecast}`

# MINUTECASTを取得して表示
echo "$weather_data" | grep -A 2 'mc-summary' | grep '<p>' | sed -e 's/<[^>]*>//g' | tr -s ' ' ' ' | grep -v -e 'No precipitation' -e 'temporarily unavailable'

時間単位

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

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

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

# 現在時刻から7時間後までのスクリプト

# 場所のURL
weather_url="https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230"

# プロキシ
weather_proxy=""

# amとpmの色 (30 黒、31 赤、32 緑、33 黄、34 青、35 マゼンタ、36 シアン、37 白、0 デフォルト)
AM_COLOR=31
PM_COLOR=34

# 元データ取得
my_hour=`date +%H`
curl_data=`curl -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X)' $weather_proxy --silent ${weather_url/weather-forecast/hourly-weather-forecast}"?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;${AM_COLOR}mam\033[0m"`/g -e s/pm/`echo "\033[0;${PM_COLOR}mpm\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 $weather_proxy --silent -o /tmp/weather_hour_$i.png
done

視認性を上げるためにamとpmの色を変えています。他の色に変えたい場合は「# amとpmの色」のところで「AM_COLOR」と「PM_COLOR」をそれぞれ指定してください。色と数値の対応はそこのコメントに書いてある通りです。色を変えたくない場合は「0」を指定してください。


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

# 8時間後から15時間後までのスクリプト

# 場所のURL
weather_url="https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230"

# プロキシ
weather_proxy=""

# amとpmの色 (30 黒、31 赤、32 緑、33 黄、34 青、35 マゼンタ、36 シアン、37 白、0 デフォルト)
AM_COLOR=31
PM_COLOR=34

# 何時間後?
later=8

# 元データ取得
my_hour=`date +%H` ; my_hour=`expr $my_hour + $later`
curl_data=`curl -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X)' $weather_proxy --silent ${weather_url/weather-forecast/hourly-weather-forecast}"?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="_"
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;${AM_COLOR}mam\033[0m"`/g -e s/pm/`echo "\033[0;${PM_COLOR}mpm\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 $weather_proxy --silent -o /tmp/weather_hour_`expr $i + $later`.png
done

明日の天気

明日の天気は以下の通り。AccuWeatherでは深夜を過ぎるとその日の早朝の天気に表示が変わりますが、それにも対応させてあります。時間単位のスクリプトと同じような感じで、Tomorrow(またはEarly)の文字色を変えることができます。ちなみに黒は「30」ですが十の位を4にする、つまり「40」を指定すると文字色ではなく背景色を黒にすることもできます。天気アイコンは「/tmp/weather_tomorrow.png」に保存されます。

# 明日の天気のスクリプト

# 場所のURL
weather_url="https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230"

# プロキシ
weather_proxy=""

# TomorrowまたはEarlyの色 (30 黒、31 赤、32 緑、33 黄、34 青、35 マゼンタ、36 シアン、37 白、0 デフォルト)
T_COLOR=40

# 元データ取得
weather_data=`curl  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X)' $weather_proxy --silent $weather_url`

# 明日(または早朝)の天気を表示
echo "$weather_data" | grep -e 'Tomorrow\|Early' | sed -e 's/<[^>]*>//g'  -e 's/^ *//' | awk -v t_color="$T_COLOR" '{print "\x1b["t_color"m"$0"\x1b[0m"}'
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 $weather_proxy --silent -o /tmp/weather_tomorrow.png

週末の天気

週末の天気は以下の通り。時間単位のスクリプトと同じような感じで、土曜日と日曜日の文字色を変えることができます。ちなみに赤は「31」ですが十の位を4にする、つまり「41」を指定すると例で挙げた画像のように文字色ではなく背景色を赤にすることもできます。天気アイコンの場所は土曜日が「/tmp/weather_sat.png」、日曜日が「/tmp/weather_sun.png」です。

# 土日の天気のスクリプト

# 場所のURL
weather_url="https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230"

# プロキシ
weather_proxy=""

# 土曜日と日曜日の色 (30 黒、31 赤、32 緑、33 黄、34 青、35 マゼンタ、36 シアン、37 白、0 デフォルト)
SAT_COLOR=34
SUN_COLOR=31

# 元データ取得
weather_weekend=`curl -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X)' $weather_proxy --silent ${weather_url/weather-forecast/weekend-weather}`

# 土日の天気を表示
echo "\033[0;${SAT_COLOR}mSaturday\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;${SUN_COLOR}mSunday\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 $weather_proxy --silent -o /tmp/weather_sat.png
echo "https://vortex.accuweather.com/adc2010/images/slate/icons/"$icon_sun"-l.png" | xargs curl $weather_proxy --silent -o /tmp/weather_sun.png

Geekletのダウンロード NEW!!

ここで紹介したスクリプトをGeekletとして一括してダウンロードできます。
スクリプトの見出しと同じファイル名をつけておきましたので、必要なものだけダブルクリックして使ってください。
[Geekletのダウンロード]

さいごに

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

ここのスクリプトの転載や改造などは自由にしていただいて構いませんが、公開するならばこのブログへの言及をお願いします。

更新履歴

2018/12/12 直近の天気予報(MUNITECAST)の変化がない時とサービス停止中には表示しないように仕様変更。
2018/5/9 AccuWeatherの仕様変更(User-Agent関係)に合わせてスクリプトを若干修正。(それぞれのスクリプトの「# 元データ取得」のところだけコピペで書き直せばOKです)
2018/3/14 Geekletの配布開始。
2017/11/21 AccuWeatherの仕様変更に合わせてスクリプト修正。カラー設定の変更をやりやすいように記述追加。