Skip to content

Instantly share code, notes, and snippets.

@shenqi
Created August 18, 2010 04:57
Show Gist options
  • Save shenqi/533487 to your computer and use it in GitHub Desktop.
Save shenqi/533487 to your computer and use it in GitHub Desktop.
fetch livedoor weather and growl it!
#!/usr/bin/env ruby -Ku
require 'net/http'
require 'rubygems'
require 'rmagick'
include Magick
class Kakumaru
def initialize(iconurl)
@image = Magick::Image.read(iconurl.to_s.sub(/(.*\..*)\?.*/) {$1}).first
@size = @image.columns < @image.rows ? @image.columns : @image.rows #短い方のピクセル数を代入
@magsize = @size > 75 ? @size : @size * (75.div(@size) + 1) #75未満の場合拡大するサイズを指定
@fill_in_color = 'white'
end
def resize(x = 0, y = 0)
#ToDo: crop時の設定をもっと詰める。わざわざcropを使っているので。
image = @image.border(x, y, @fill_in_color).crop(CenterGravity,@size,@size)
image.resize!(@magsize,@magsize,filter=LanczosFilter) unless @size == @magsize
return image
end
def shori(image)
image.alpha = ActivateAlphaChannel
bg = Magick::Image.new(@magsize, @magsize) {self.background_color = 'none'}
tn = (@magsize * 0.07).round
Magick::Draw.new {self.fill = 'white'}.roundrectangle(0,0,@magsize,@magsize,tn,tn).draw(bg)
image.composite!(bg, 0, 0, CopyOpacityCompositeOp)
return image
end
def convert(iconsize = nil, x = 0, y = 0)
image = resize(x, y)
if iconsize then
return shori(image).resize(iconsize, iconsize, filter=LanczosFilter)
else
return shori(image)
end
end
end
#!/usr/bin/env ruby -Ku
require 'net/http'
require 'open-uri'
require 'tempfile'
require File.dirname(__FILE__) + '/seikei.rb'
require 'rubygems'
require 'meow'
require 'nokogiri'
#notify forecast for livedoor
#notify current status for bbc
urls = ['http://weather.livedoor.com/area/34/90.html', 'http://news.bbc.co.uk/weather/forecast/2199']
def growl(title, message, icon, url)
growl = Meow.new("天気予報")
opt = { :icon => icon , :sticky => 'true'}
growl.notify(title, message.chomp, opt) do
system("open '#{url}'")
end
end
def gicon(iconurl)
temp = Tempfile::new('growlicon', '/tmp')
image = Kakumaru.new(iconurl).convert
image.write('png:' + temp.path)
temp.close
icon = Meow.import_image(temp.path)
temp.close(true) #closeしてtempfileを消す
return icon
end
def fetch_livedoor(url)
page = Nokogiri::HTML(open(url))
results = []
probs = []
for n in 1..4
probs << [page.xpath('//table[@class="normal"][1]/tr[1]/td')[n].text, page.xpath('//table[@class="normal"][1]/tr[2]/td')[n-1].text]
end
for n in 1..4
probs << [page.xpath('//table[@class="normal"][2]/tr[1]/td')[n].text, page.xpath('//table[@class="normal"][2]/tr[2]/td')[n-1].text]
end
prob = probs.delete_if{|prob| prob[1] == '---'}.collect{|prob| prob.join('時: ')}
gaiyo = page.xpath('//div[@class="telopbox-etc"]/p').text
for t in 1..2
if t == 1 then
location = page.xpath('//li[@class="bdno on"]').text
location = page.xpath('//div[@class="title-outer"][1]/h2').text.sub(/.*\ (.*)の天気/) { $1 } if location.empty?
title = location + ': ' + page.xpath('//table[@class="normal"][1]//img/@alt').to_s
else
title = '明日の天気: ' + page.xpath('//table[@class="normal"][2]//img/@alt').to_s
end
kaze = page.xpath("//table[@class=\"normal\"][#{t}]/tr[3]/td").text
max = page.xpath("//table[@class=\"normal\"][#{t}]//span[@class=\"maxtemp\"]")
maxtemp = max[1].text + ' ' + max[3].text if max[3]
min = page.xpath("//table[@class=\"normal\"][#{t}]//span[@class=\"mintemp\"]")
mintemp = min[1].text + ' ' + min[3].text if min[3]
iconurl = page.xpath("//table[@class=\"normal\"][#{t}]//img/@src").to_s
if t == 1 then
message = "降水確率 - #{prob[0]}\n"
else
message = ''
end
message << "最高気温 - #{maxtemp}\n" if max[3]
message << "最低気温 - #{mintemp}\n" if min[3]
if t == 2 then
message << "\n降水確率\n"
n = prob.map{|item| item.split('').length}.sort.last
prob.length.times do |i|
message << (prob[i].ljust(n) + "\n") #rjustにしたいがなぜかgrowl時にずれる…
end
message << "\n"
end
message << "風 - #{kaze}\n"
message << "\n#{gaiyo}" if t == 1
results << [title, message, gicon(iconurl)]
end
return results
end
def fetch_bbc(url)
page = Nokogiri::HTML(Net::HTTP.get(URI(url)))
location = page.xpath('//h2[@id="Forecast"]').text.split(',').first
current = page.xpath('//div[@id="ob_V_node"]')
iconurl = current.xpath('.//img/@src').to_s
weather = current.xpath('.//img/@alt').to_s
title = location + ': ' + weather
temp = 'Temperature: ' + current.xpath('.//li[@class="obstemp"]/span[3]/span[@class="cent"]').text + "\n"
kaze = 'Wind: ' + current.xpath('.//span[@title="SW"]/span[@class="blq-hide"]').text + ' ' + current.xpath('.//span[@title="SW"]/span[@class="kph hide"]').text + "\n"
extra = current.xpath('.//ul[@class="humpresvis"]').text.delete("\t")
message = temp + kaze + extra
icon = gicon(iconurl)
results = []
results << [title, message, icon]
return results
end
def notify(urls)
urls.each do |url|
results = fetch_livedoor(url) if url =~ /weather\.livedoor\.com/
results = fetch_bbc(url) if url =~ /bbc\.co\.uk/
results.each do |result|
growl(result[0], result[1], result[2], url)
end
end
end
notify(urls)
@shenqi
Copy link
Author

shenqi commented Sep 23, 2010

全体的に綺麗にした。

@shenqi
Copy link
Author

shenqi commented Oct 1, 2010

bbcのcurrent statusをfetchするようにした。天気予報は…お察しください

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment