livedoorの天気予報情報の取得サンプル
bonlifeです。id:faw:20080206:1202308711 の記事を見て、「ちょ、何でlivedoorの天気予報の情報を取得するのにWeather HacksのXML使わないの!」って思ったら細かい地域の天気予報には対応してないんですね…orz
ということで、私もWeather Hacksを使わずに情報を取得するPythonスクリプトを書いてみました。明らかにオリジナルより機能縮小の劣化版です。大事な大事なメール送信機能を省いちゃってますし、なんとなく大阪市北区のURLをスクリプト中に固定で埋め込み。lxmlの練習ということで、勘弁してください。XpathのクエリにUnicode文字列を渡す方法で悩んだりしたのは秘密です。(というより、Xpathの書き方で、何箇所もつまづいたのは秘密です。)
出力イメージはこんな感じ。
02/07 0 3 6 912151821 曇晴晴晴晴曇雨曇 5 4 4 5 7 8 5 3 0 0 0 0 0 0 0 0 02/08 0 3 6 912151821 曇曇曇晴曇晴晴晴 3 3 2 4 7 7 5 3 0 0 0 0 0 0 0 0
スクリプトは以下の通り。
- livedoor_weather_check.py
# -*- coding: utf8 -*- import urllib2 import re from lxml import etree def get_date(e_strong): date_string = [ i for i in e_strong.getparent().itertext() ][1] m = re.search(r'(\d{1,2}).*?(\d{1,2})', date_string) if m: return "%02d/%02d" % (int(m.groups(0)[0]),int(m.groups(0)[1])) else: return '' def get_weather_info(e_table): weather_list = list() ts = e_table.xpath("tr/td/small/div[@style='margin-top:5px;']") for i in ts: weather_list.append(i.text[0]) return weather_list def get_temperature_info(e_table): temperature_list = list() target = u'気温' xpath_string = "tr/th[@class='thline'][small/text()='%s']" % target e_th = e_table.xpath(xpath_string) e_tr = e_th[0].getparent() for e in e_tr.xpath('td/small'): temperature_list.append(e.text.rstrip(u'℃')) return temperature_list def get_rain_info(e_table): rain_list = list() target = u'降水量' xpath_string = "tr/th[@class='thline'][small/text()='%s']" % target e_th = e_table.xpath(xpath_string) e_tr = e_th[0].getparent() for e in e_tr.xpath('td/small'): rain_list.append(e.text.rstrip(u'mm')) return rain_list def get_all_weather_info(target_url): result_dict = dict() et = etree.parse(urllib2.urlopen(target_url),etree.HTMLParser()) ts = et.xpath('//table/tr/td/small/strong') for i in ts: e_table = i.getparent().getparent().getparent().getparent() if i.text.strip() == u'今日の天気': result_dict['today'] = {'date':get_date(i)} result_dict['today'].update({'weather':get_weather_info(e_table)}) result_dict['today'].update({'temperature':get_temperature_info(e_table)}) result_dict['today'].update({'rain':get_rain_info(e_table)}) elif i.text.strip() == u'明日の天気': result_dict['tomorrow'] = {'date':get_date(i)} result_dict['tomorrow'].update({'weather':get_weather_info(e_table)}) result_dict['tomorrow'].update({'temperature':get_temperature_info(e_table)}) result_dict['tomorrow'].update({'rain':get_rain_info(e_table)}) return result_dict def print_weather_info(result_dict): width = 16 hour_header = ''.join([ "%2s" % i for i in range(0,24,3) ]) def print_one_day_info(d): print d.get('date').center(width) print hour_header print ''.join(d.get('weather')) print ''.join([ "%2s" % i for i in d.get('temperature') ]) print ''.join([ "%2s" % i for i in d.get('rain') ]) print_one_day_info(result_dict.get('today')) print_one_day_info(result_dict.get('tomorrow')) if __name__ == "__main__": result_dict = get_all_weather_info('http://weather.livedoor.com/point/city/1655.html') print_weather_info(result_dict)
itertext()が思い出せずに苦労したのは数度目…orz 私もそのうち改訂して、携帯にメール送れるようにしてみようっと。
後、あらためて見ると、関数名に _info とか付いてますが、情報を取ってくるに決まってるので、 _info は不要ですね…。get_date() とか _info なしの関数もあるし。あぁ、適当に命名するとこうなるから怖い!