end0tknr's kipple - 新web写経開発

http://d.hatena.ne.jp/end0tknr/ から移転しました

電力会社から提供されている電力使用状況CSVデータを取得し、jsonで保存

関西電力だけは、やや書式が異なるようですが、次のように書けば良さそう。

#!/usr/local/bin/perl
use strict;
use utf8;
use Encode;
use HTTP::Request::Common;
use JSON qw/encode_json/;
use LWP::UserAgent;

#各電力会社から提供されている電力使用状況csvを取得し、保存します。
#30分間隔?のcron jobにすると良いと思います。

my $OUT_DIR = '../html/data';	#使用状況data(json)の保存先
my @AREAS =
    ({name=>'tokyo',
      site_url=>'http://www.tepco.co.jp/forecast/index-j.html',
      data_url=>'http://www.tepco.co.jp/forecast/html/images/juyo-j.csv',
     },
     {name=>'tohoku',
      site_url=>'http://setsuden.tohoku-epco.co.jp/graph.html',
      data_url=>'http://setsuden.tohoku-epco.co.jp/common/demand/juyo_tohoku.csv',
     },
     {name=>'chubu',
      site_url=>'http://denki-yoho.chuden.jp/index.html',
      data_url=>'http://denki-yoho.chuden.jp/denki_yoho_content_data/juyo_cepco.csv',
     },
     {name=>'kansai',
      site_url=>'http://www.kepco.co.jp/setsuden/graph/index.html',
      data_url=>'http://www.kepco.co.jp/yamasou/juyo1_kansai.csv',
     }
    );
my $HTTP_TIMEOUT = 10;
my $HTTP_MAX_RETRY = 5;


main();
exit(0);


sub main {

    for my $area (@AREAS){
	my $pow_info = get_pow_info($area);
	next unless($pow_info);

	my $save_path =  "$OUT_DIR/$area->{name}.json";
	open(my $fh,">",$save_path) or die "can't open $save_path :$!";
	print $fh encode_json($pow_info);
	close($fh) or die "can't close $save_path :$!";
    }
}

sub get_pow_info {
    my ($area) = @_;

    my $ua = LWP::UserAgent->new();
    $ua->timeout($HTTP_TIMEOUT);

    my $req = HTTP::Request->new(GET=>$area->{data_url});

    my $i = 0;
    while( $i++ < $HTTP_MAX_RETRY ){
        my $res = $ua->request($req);
        if($res->is_success){
	    if ($area->{name} eq 'kansai'){
		return parse_csv_data_kansai($res->content);
	    } else {
		return parse_csv_data_common($res->content,$area->{name});
	    }
	}
        print STDERR $res->status_line,"\n";
    }
    print STDERR "exceeded HTTP_MAX_RETRY\n";
    return undef;
}

sub parse_csv_data_common {
    my ($csv_lines_str,$area_name) = @_;

    my @csv_lines = split("\n",decode('utf8',$csv_lines_str));

    my $ret = {};

    #更新日時の取得
    if($csv_lines[0] =~ /^(\d+)\D(\d+)\D(\d+) (\d+)\D(\d+) UPDATE/o ){
	$ret->{Update} = sprintf("%04d-%02d-%02d %02d:%02d",$1,$2,$3,$4,$5);
    } else {
	print STDERR "can't parse csv(update) $area_name at $csv_lines[0]";
	return undef;
    }

    #ピーク時供給力(万kW)
    if($csv_lines[2] =~ /^(\d+)/o ){
	$ret->{Capacity} = $1;
    } else {
	print STDERR "can't parse csv(capacity) $area_name at $csv_lines[2]";
	return undef;
    }
    #電力使用量の取得
    my $i = 31;
    while($i >= 8 ){
	my $csv_line = $csv_lines[$i];

	if ($csv_line =~ /^(\d+)\D(\d+)\D(\d+),(\d+):\d+,(\d+)/o ){
	    my $date = sprintf("%04d-%02d-%02d",$1,$2,$3);
	    my $hour = $4;
	    my $usage = $5;
	    if ($usage>0){
		$ret->{Date} = $date;
		$ret->{Hour} = $hour;
		$ret->{Usage} = $usage;
		last;
	    }
	} else {
	    print STDERR "can't parse csv(usage) $area_name at $csv_line";
	    return undef;
	}
	$i--;
    }
    return $ret;
}
sub parse_csv_data_kansai {
    my ($csv_lines_str) = @_;

    my $area_name = 'kansai';

    my @csv_lines = split("\n",decode('cp932',$csv_lines_str));

    my $ret = {};

    #更新日時の取得
    if($csv_lines[0] =~ /^(\d+)\D(\d+)\D(\d+) (\d+)\D(\d+) UPDATE/o ){
	$ret->{Update} = sprintf("%04d-%02d-%02d %02d:%02d",$1,$2,$3,$4,$5);
    } else {
	print STDERR "can't parse csv(update) $area_name at $csv_lines[0]";
	return undef;
    }

    #ピーク時供給力(万kW)
    if($csv_lines[2] =~ /^(\d+)/o ){
	$ret->{Capacity} = $1;
    } else {
	print STDERR "can't parse csv(capacity) $area_name at $csv_lines[2]";
	return undef;
    }
    #電力使用量の取得
    my $i = 34;
    while($i >= 11 ){
	my $csv_line = $csv_lines[$i];

	if ($csv_line =~ /^(\d+)\D(\d+)\D(\d+),(\d+):\d+,(\d+)/o ){
	    my $date = sprintf("%04d-%02d-%02d",$1,$2,$3);
	    my $hour = $4;
	    my $usage = $5;
	    if ($usage>0){
		$ret->{Date} = $date;
		$ret->{Hour} = $hour;
		$ret->{Usage} = $usage;
		last;
	    }
	} else {
	    print STDERR "can't parse csv(usage) $area_name at $csv_line";
	    return undef;
	}
	$i--;
    }
    return $ret;
}