花粉症 bot

花粉予報を tweet する bot を作ったのでメモ。
花粉症に苦しむ様をつぶやく bot じゃない。

データソース

花粉飛散情報 2019 - 日本気象協会 tenki.jp

とりあえずこのサイトから東京と神奈川のデータを取ってくる。


取得

urlopen2 で取得して BeautifulSoup を使おうと思ったら、 parse に失敗するらしく、肝心の花粉情報が取れなかった。
他に何か無いかと探してみると、 lxml がよさげだったので早速導入。

http://codespeak.net/lxml/

lxml.html.parse に url を渡すと、一気に etree 互換のオブジェクトにして返してくれる。
あとは適当に抜き出して取得完了。

つぶやく

python twitter でググったらトップに出てきた

Google Code Archive - Long-term storage for Google Code Project Hosting.

を使用してつぶやいてみた。

import twitter

api = twitter.Api(uname, passwd)
api.PostUpdate(msg)

こでだけでつぶやけるので楽ちん。

完成品

できたのは以下の通り。
これを cron で適当に回せばつぶやいてくれる。
ここまで一時間半。ちょっとかかりすぎかも。

とりあえず http://twitter.com/kahunchan_bot でつぶやき中。

あとは mention の反応するようにしたらとりあえず完成かなあ。

#-*- coding:utf-8 -*-

import urllib2
import lxml.html
import StringIO
import twitter
import time


class PollenForecast(object):

    def __init__(self, area, date, forecasts):

        self.area = area
        self.forecasts = zip(date, forecasts)

        
    def getForecastText(self):
        
        fp = StringIO.StringIO()

        print >> fp, self.area

        for i in self.forecasts[:2]:        
            print >> fp, '%s/%s' % i

        return fp.getvalue()


        

def parseUrl(url):

    obj = lxml.html.parse(url)

    # テーブル取得
    table = obj.find('//table[@id="AreaWeathers"]')
    trs = table.findall('tr')
    head = trs[0].findall('th')

    # 日付
    dates = [x.text_content() for x in head[1:]]

    areas = []

    # 予報一覧
    for tr in trs[2:]:
        areaname = tr.find('th').text_content().splitlines()[1].strip()
        forecasts = [x.find('img').get('title') for x in tr.findall('td')]
        areas.append(PollenForecast(areaname, dates, forecasts))


    return areas



def postTwitter(area, data, usr, passwd):

    api = twitter.Api(usr, passwd)

    fp = StringIO.StringIO()

    print >> fp, u'%sの花粉予報' % area

    for datum in data:
        print >> fp, '\t', datum.getForecastText()
    print >> fp, '#kafun #kahun #pollen'
    
    
    api.PostUpdate(fp.getvalue())
    


if __name__ == '__main__':

    import sys

    for area, url in [(u'東京', 'http://tenki.jp/pollen/pref-16.html'),
                      (u'神奈川', 'http://tenki.jp/pollen/pref-17.html')]:
        data = parseUrl(url)
        postTwitter(area, data, *sys.argv[1:3])

        time.sleep(5)