個人的なメモを記していくためのページです。
自宅の玄箱で次のようなスクリプトを定期的に実行するようにします。
1 #!/bin/sh
2
3
4 LOC=44132
5
6 cd $HOME/public_html/amedas/ || exit
7
8 HOUR=`date +%H`
9
10 case $HOUR in
11 00)
12 wget -q -N http://www.jma.go.jp/jp/amedas_h/yesterday-${LOC}.html
13 perl update-amedas.pl yesterday-${LOC}.html | sh
14 ;;
15 *)
16 wget -q -N http://www.jma.go.jp/jp/amedas_h/today-${LOC}.html
17 perl update-amedas.pl today-${LOC}.html | sh
18 ;;
19 esac
20
21 sh ./make-graph-2.sh ${LOC}
22 scp foo.png ${HOST}:${WWW_PATH}/qmd/files/amedas-${LOC}.png
このスクリプトは以下のことをします。
23 * * * * /home/tito/public_html/amedas/fetch-amedas.sh >/dev/null 2>&1update-amedas.plは以下のperlスクリプトです。表中の最近のデータを取得しrrdtoolのコマンドラインを生成します。生成されたコマンドはfetch-amedas.sh でパイプラインでつながったシェルに渡され実行されています。しかしこれはセキュリティ的に問題が発生しやすいのでperlで適当なモジュールを使ってrrdtoolを起動するべきでしょう。一応以下のスクリプト中でもデータのサニタイズ等に気は使ったつもりですが。
1 #!/usr/local/bin/perl
2
3 use utf8;
4
5 use strict;
6 use Data::Dumper;
7 use HTML::TreeBuilder;
8
9 use Time::Local;
10
11 binmode STDOUT, ":encoding(euc-jp)";
12 binmode STDERR, ":encoding(euc-jp)";
13
14 our %wd;
15 our $location_code;
16 our( $year,$month,$day, $location, $location_yomi);
17 our $hour;
18 our $last_hour;
19 our $time_0 ;
20 our @dp_hour;
21
22
23 my $i = 0;
24 foreach ("北", "北北東", "北東", "東北東",
25 "東", "東南東", "南東", "南南東",
26 "南", "南南西", "南西", "西南西",
27 "西", "西北西", "北西", "北北西"){
28 $wd{$_}=$i++;
29 utf8::encode( $wd{$_});
30 }
31
32
33 foreach my $file (grep( -f $_, @ARGV)) {
34 ($location_code) = $file=~ /-([0-9]+).html/;
35
36
37 open FH, "<:encoding(Shift_JIS)", $file || die;
38 my @c = <FH>;
39 my $contents = join('', @c);
40 close(FH);
41 my $h = HTML::TreeBuilder->new;
42 utf8::encode( $contents );
43 $h->parse($contents);
44
45 my @title = $h->look_down( "_tag", "table",
46 "id", "tbl_title" );
47 my @tr = $title[0]->look_down( "_tag", "tr" );
48
49 my $title=$tr[1]->as_text();
50 utf8::decode($title);
51 ( $year,$month,$day, $location, $location_yomi) =
52 $title =~ /(.*)年(.*)月(.*)日 (.*)\((.*)\)/;
53 $hour=0;
54 $time_0 = timelocal( 0,0,0, $day, $month-1, $year );
55
56
57 my @table = $h->look_down( "_tag", "table",
58 "id", "tbl_list");
59
60 @tr = $table[0]->look_down( "_tag", "tr" );
61
62 my @dp= $tr[0]->look_down( "_tag", "td" );
63 my @dp_name = ();
64 foreach (@dp){
65 my $cc = $_->as_text();
66 utf8::decode( $cc );
67 push( @dp_name, $cc );
68 }
69
70 $hour =0;
71 @dp_hour=();
72
73 foreach my $j( @tr[2..$#tr] ){
74 my @td = $j->look_down( "_tag", "td" );
75
76 my $i = 0;
77 $hour = $td[0]->as_text();
78 $hour =~ y/^0-9//;
79
80 $dp_hour[ $hour ]={};
81 my $dp_count=0;
82 foreach (@td){
83 my $c = $_->as_text();
84 $c =~ s/\x{00a0}//;
85 if( $c ne ""){
86 $dp_hour[$hour]->{ $dp_name[ $i ] } = $c;
87 $dp_count++;
88 }
89 $i++;
90 # print " $c";
91 }
92 if( $dp_count > 1){
93 $last_hour = $hour;
94 # rrd_update( $last_hour );
95
96 }
97 # print "\n";
98
99 }
100 rrd_update( $last_hour );
101
102
103 $h = $h->delete(); # nuke it!
104 }
105 exit;
106
107 sub sanitize
108 {
109 my($v) = @_;
110 $v =~ y/0-9.//cd;
111 return $v;
112 }
113
114 sub rrd_update
115 {
116
117 my($last_hour) = @_;
118 print STDERR "$year-$month-${day}T${last_hour}:00:00 $location($location_yomi) $location_code\n";
119
120 my $d = $dp_hour[ $last_hour ];
121 my $cmd;
122 $cmd = "rrdtool update $location_code.rrd ";
123 $cmd .= join( ':',
124 sprintf("%d",$time_0+$last_hour*3600),
125 &sanitize($d->{気温}),
126 &sanitize($d->{降水量}),
127 $wd{$d->{風向}},
128 &sanitize($d->{風速}),
129 &sanitize($d->{日照時間}),
130 &sanitize($d->{積雪深}),
131 &sanitize($d->{湿度}),
132 &sanitize($d->{気圧}));
133
134 print "$cmd\n";
135
136 $cmd = "rrdtool update $location_code-y.rrd ";
137 $cmd .= join( ':',
138 sprintf("%d",$time_0+$last_hour*3600+24*3600 ),
139 &sanitize($d->{気温}),
140 &sanitize($d->{降水量}),
141 $wd{$d->{風向}},
142 &sanitize($d->{風速}),
143 &sanitize($d->{日照時間}),
144 &sanitize($d->{積雪深}),
145 &sanitize($d->{湿度}),
146 &sanitize($d->{気圧}));
147
148 print "$cmd\n";
149
150
151 }
152
153
154 __END__
ところどころ utf8::decode、utf8::encodeが入っているのが魔法的ですが私もよく判っていません。別の環境ではこれが無くても動作しました。(入れると動かない)
amedasによって得られるデータの種類は地点によって違います。気象台がある地点以外では種類が少なく降水量しかなかったりします。一応他の地点でも使えるようにデータの種類も表中から得るようにしています。
rrdupdateサブルーチンではrrdtool update行を2行出力していますがこれは一つのグラフに今日のデータと一日前のデータと両方を出すためのトリックです。(RRDtoolの使い方のp.52) 例えば 44132.rrd と 44132-y.rrd というデータベースを用意して 44132-y.rrdには時間をずらしてデータを入れます。
グラフを生成するスクリプトです。rrdtool graphを呼び出しているだけです。
1 #!/bin/sh
2
3 LOC=$1
4
5 cat <<EOF | rrdtool -;
6 graph foo.png \
7 -s `date +%s -d '1 day ago'` \
8 -e `date +%s` \
9 -a PNG \
10 DEF:temp=${LOC}.rrd:temp:AVERAGE \
11 GPRINT:temp:LAST:"temp %3.1lf\r" \
12 DEF:rh=${LOC}.rrd:rh:AVERAGE \
13 CDEF:rh1=rh,100,/,10,* \
14 GPRINT:rh:LAST:"rh %3.1lf\r" \
15 DEF:tempy=${LOC}-y.rrd:temp:AVERAGE LINE1:tempy#ff8888:"temp-y" \
16 LINE1:temp#ff0000:temp \
17 DEF:rhy=${LOC}-y.rrd:rh:AVERAGE \
18 CDEF:rh2=rhy,100,/,10,* LINE1:rh2#88ccff:"rh-y" \
19 LINE1:rh1#0033cc:rh \
20 --width=400 --height=120 \
21 --title "Tokyo Temp/RH (derive from AMEDAS)"
22 EOF
rrdtoolのデータベースを作るスクリプト。 以上のスクリプトのためには1地点について二つのrrdファイルが必要です。
$ ./createrrd 44132 $ ./createrrd 44132-y
1 rrdtool create $1.rrd --step 3600 \
2 --start 1195189900 \
3 DS:temp:GAUGE:7000:-50:50 \
4 DS:prec:GAUGE:7000:0:100 \
5 DS:wd:ABSOLUTE:7000:U:U \
6 DS:ws:GAUGE:7000:0:30 \
7 DS:dl:GAUGE:7000:0:1 \
8 DS:sg:GAUGE:7000:0:U \
9 DS:rh:GAUGE:7000:0:100 \
10 DS:ap:GAUGE:7000:900:1100 \
11 RRA:AVERAGE:0.5:1:48 \
12 RRA:AVERAGE:0.5:24:30 \
13 RRA:MIN:0.5:12:63 \
14 RRA:MAX:0.5:12:63 \
15 RRA:LAST:0.5:1:48
debianならば rrdtool と libhtml-tree-perl をaptやaptitude でインストールします。手動でインストールする場合は perl のモジュールは HTML::TreeBuilder です。 rrdtoolも最新版だと グラフィックスがcairoベースできれいになってたりするので そちらを入れてもよいでしょう。debian sargeのパッケージでは1.0.49ですが別マシンではrrdtool-1.2.99908020600を入れて使っています。その場合のグラフはこんな感じです。
クラシック・ドーム
ソフト・ドーム
ソフト・リム