Last active
April 1, 2016 10:24
-
-
Save punytan/4017e8aff64126ffe7ac to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use strict; | |
use warnings; | |
use utf8; | |
package Weather; | |
use DateTime; | |
use Web::Scraper; | |
use URI; | |
our $AREA = { | |
千代田区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13101.html', | |
中央区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13102.html', | |
港区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13103.html', | |
新宿区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13104.html', | |
文京区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13105.html', | |
台東区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13106.html', | |
墨田区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13107.html', | |
江戸川区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13108.html', | |
品川区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13109.html', | |
目黒区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13110.html', | |
大田区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13111.html', | |
世田谷区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13112.html', | |
渋谷区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13113.html', | |
中野区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13114.html', | |
杉並区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13115.html', | |
豊島区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13116.html', | |
北区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13117.html', | |
荒川区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13118.html', | |
板橋区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13119.html', | |
練馬区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13120.html', | |
足立区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13121.html', | |
葛飾区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13122.html', | |
江戸川区 => 'http://weather.yahoo.co.jp/weather/jp/13/4410/13123.html', | |
}; | |
sub get_yahoo_weather { | |
my $area = shift; | |
my $scraper = scraper { | |
process "div#yjw_pinpoint_today", today => scraper { | |
process h3 => "date" => "TEXT"; | |
process "table", "rows[]" => scraper { | |
process "tr:nth-child(1) td" => "time[]" => "TEXT"; | |
process "tr:nth-child(2) td" => "weather[]" => scraper { | |
process "img" => img => '@src'; | |
process "small" => text => 'TEXT'; | |
}; | |
process "tr:nth-child(3) td" => "temperature[]" => "TEXT"; | |
process "tr:nth-child(4) td" => "humidity[]" => "TEXT"; | |
process "tr:nth-child(5) td" => "rainfall_precipitation[]" => "TEXT"; | |
process "tr:nth-child(6) td" => "wind_direction[]" => "TEXT"; | |
}; | |
}; | |
process "div#yjw_pinpoint_tomorrow", tomorrow => scraper { | |
process h3 => "date" => "TEXT"; | |
process "table", "rows[]" => scraper { | |
process "tr:nth-child(1) td" => "time[]" => "TEXT"; | |
process "tr:nth-child(2) td" => "weather[]" => scraper { | |
process "img" => img => '@src'; | |
process "small" => text => 'TEXT'; | |
}; | |
process "tr:nth-child(3) td" => "temperature[]" => "TEXT"; | |
process "tr:nth-child(4) td" => "humidity[]" => "TEXT"; | |
process "tr:nth-child(5) td" => "rainfall_precipitation[]" => "TEXT"; | |
process "tr:nth-child(6) td" => "wind_direction[]" => "TEXT"; | |
}; | |
}; | |
process "div#yjw_week", week => scraper { | |
process h2 => "date" => "TEXT"; | |
process "table.yjw_table", "rows[]" => scraper { | |
process "tr:nth-child(1) td" => "dates[]" => "TEXT"; | |
process "tr:nth-child(2) td" => "weather[]" => scraper { | |
process "img" => img => '@src'; | |
process "small" => text => 'TEXT'; | |
}; | |
process "tr:nth-child(3) td" => "temperature[]" => scraper { | |
process "small" => label => "TEXT"; | |
process "font" => "highlow[]" => "TEXT"; | |
process "font:nth-child(2)" => low => "TEXT"; | |
}; | |
process "tr:nth-child(4) td" => "rainfall_ratio[]" => "TEXT"; | |
}; | |
process "table.yjw_table tr:nth-child(2)", "weather[]" => scraper { | |
process td => "columns[]" => "TEXT" | |
}; | |
}; | |
}; | |
$scraper->scrape(URI->new($AREA->{$area})); | |
} | |
sub get_amesh_time { | |
my $now = DateTime->now(time_zone => "Asia/Tokyo"); | |
my $current = join "", | |
$now->ymd(""), | |
map { sprintf "%02d", $_ } $now->hour, $now->minute; | |
$current - ($now->minute % 5) | |
} | |
package main; | |
use Plack::Request; | |
use Text::Xslate; | |
use Data::Section::Simple 'get_data_section'; | |
use Encode; | |
my $xslate = Text::Xslate->new; | |
sub { | |
my $req = Plack::Request->new(shift); | |
my $area = decode_utf8([split /\//, $req->path_info]->[-1] // ''); | |
if ($AREA->{$area}) { | |
my $body = $xslate->render_string(get_data_section('template.tt'), { | |
amesh_time => Weather::get_amesh_time, | |
yahoo_weather => Weather::get_yahoo_weather($area || '千代田区'), | |
}); | |
return do { | |
my $res = $req->new_response(200); | |
$res->body(encode_utf8 $body); | |
$res->finalize; | |
}; | |
} else { | |
my $body = $xslate->render_string(get_data_section('list.tt'), { areas => [ keys %$AREA ] }); | |
return do { | |
my $res = $req->new_response(404); | |
$res->body(encode_utf8 $body); | |
$res->finalize; | |
}; | |
} | |
} | |
__DATA__ | |
@@ list.tt | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<meta http-equiv="refresh" content="300"> | |
<style> | |
body { width: 100%; margin-top: 0; margin-bottom: 0; line-height: 1em; } | |
</style> | |
</head> | |
<body> | |
<ul> | |
: for $areas -> $key { | |
<li><a href="/<:$key:>"><: $key :></a> | |
: } | |
</ul> | |
</body> | |
</html> | |
@@ template.tt | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<meta http-equiv="refresh" content="300"> | |
<style> | |
body { width: 100%; margin-top: 0; margin-bottom: 0; line-height: 1em; } | |
</style> | |
<style> | |
div#yahoo-weather { width: 770px; margin:0 auto; } | |
div#yahoo-weather table { width: 100%; } | |
div#yahoo-weather table td { text-align: center; font-size: small; vertical-align: middle; } | |
div#yahoo-weather table td.foo { background-color: #efefef; } | |
</style> | |
<style> | |
div#amesh { width: 770px; height: 480px; margin: 0 auto; } | |
div#amesh img { width: 770px; height: 480px; display: block; } | |
div#amesh img#background-map { position: absolute; } | |
div#amesh img#rainfall-mesh { position: absolute; } | |
div#amesh img#foreground-map { position: absolute; } | |
</style> | |
</head> | |
<body> | |
<div id="yahoo-weather"> | |
<table> | |
<tr> | |
<td colspan="9" class="foo"><: $yahoo_weather.today.date :></td> | |
</tr> | |
: for $yahoo_weather.today.rows -> $row { | |
<tr> | |
: for $row.time -> $col { | |
<td><: $col :></td> | |
: } | |
</tr> | |
<tr> | |
: for $row.weather -> $col { | |
<td><: if $col.img { :><img src="<: $col.img :>"><br><: } else { :> | |
<: $col.text :> | |
: } | |
</td> | |
: } | |
</tr> | |
<tr> | |
: for $row.temperature -> $col { | |
<td><: $col :></td> | |
: } | |
</tr> | |
<tr> | |
: for $row.humidity -> $col { | |
<td><: $col :></td> | |
: } | |
</tr> | |
<tr> | |
: for $row.rainfall_precipitation -> $col { | |
<td><: $col :></td> | |
: } | |
</tr> | |
<tr> | |
: for $row.wind_direction -> $col { | |
<td><: $col :></td> | |
: } | |
</tr> | |
: } | |
<tr> | |
<td colspan="9" class="foo"><: $yahoo_weather.tomorrow.date :></td> | |
</tr> | |
: for $yahoo_weather.tomorrow.rows -> $row { | |
<tr> | |
: for $row.time -> $col { | |
<td><: $col :></td> | |
: } | |
</tr> | |
<tr> | |
: for $row.weather -> $col { | |
<td><: if $col.img { :><img src="<: $col.img :>"><br><: } else { :> | |
<: $col.text :> | |
: } | |
</td> | |
: } | |
</tr> | |
<tr> | |
: for $row.temperature -> $col { | |
<td><: $col :></td> | |
: } | |
</tr> | |
<tr> | |
: for $row.humidity -> $col { | |
<td><: $col :></td> | |
: } | |
</tr> | |
<tr> | |
: for $row.rainfall_precipitation -> $col { | |
<td><: $col :></td> | |
: } | |
</tr> | |
<tr> | |
: for $row.wind_direction -> $col { | |
<td><: $col :></td> | |
: } | |
</tr> | |
: } | |
</table> | |
<table> | |
<tr> | |
<td colspan="7" class="foo"><: $yahoo_weather.week.date :></td> | |
</tr> | |
: for $yahoo_weather.week.rows -> $row { | |
<tr> | |
: for $row.dates -> $col { | |
<td><: $col :></td> | |
: } | |
</tr> | |
<tr> | |
: for $row.weather -> $col { | |
<td><: if $col.img { :><img src="<: $col.img :>"><: } else { :> | |
<: $col.text :> | |
: } | |
</td> | |
: } | |
</tr> | |
<tr> | |
: for $row.temperature -> $col { | |
: if $col.highlow { | |
<td><: $col.highlow[0] :> / <: $col.highlow[1] :></td> | |
: } else { | |
<td> | |
<div><: $col.label :><div> | |
</td> | |
: } | |
: } | |
</tr> | |
: for [ "rainfall_ratio"] -> $key { | |
<tr> | |
: for $row[$key] -> $col { | |
<td><: $col :></td> | |
: } | |
</tr> | |
: } | |
: } | |
</table> | |
</div> | |
<div id="amesh"> | |
<img id="background-map" src="http://tokyo-ame.jwa.or.jp/map/map000.jpg"> | |
<img id="rainfall-mesh" src="http://tokyo-ame.jwa.or.jp/mesh/000/<: $amesh_time :>.gif" > | |
<img id="foreground-map" src="http://tokyo-ame.jwa.or.jp/map/msk000.png"> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment