22時に寝ようと思って2時に寝る。

備忘録や日記を書いてます。きょうは早く寝よう。

Pythonでpywapiを使ってYahoo! Weatherから天気情報を取得してツイートする方法

Pythonで天気予報情報を取得してツイートする

APIを使う練習をしようと思って手始めに天気予報をAPIで取得してツイートするプログラムを思いついた。

現時点では手動でスクリプトファイルを実行して天気予報情報をツイートするだけなのでbotではないけど、ゆくゆくは自動化してサーバーに置いて毎朝自分に天気予報リプライを送りつけたい。実装できたら結構便利だと思った。

便利だとは思ったけどプログラム書いてる途中で「天気ならGoogleNowが毎朝通知で教えてくれるじゃん」と気づいてしまった。

個人サービス開発が続かない理由
「これ作って何になるんだろう」と突然気づく
エンジニア向け絶対に挫折しない個人サービスの作り方 - 17ページ

でも朝起きて、スマホを手に取ってまず何のアプリを立ち上げるかって、冷静に考えたら、通知なんか目もくれずにTwitterクライアントを立ち上げてるんだよなぁ…。だから問題ないのでは。(ほとんどこじつけです)

※この記事では天気予報を取得して、ツイートするという流れを説明しています。自動化(bot化)までは実装していません。

pywapi(Python Weather API)を使ってYahoo! Weatherから天気予報を取得する方法

 pywapiをインストールする

python-weather-api - A python wrapper around the Yahoo! Weather, Weather.com and NOAA APIs - Google Project Hosting

基本的な使い方

  • コード
# -*- coding: utf-8 -*-
import pywapi

result = pywapi.get_weather_from_yahoo('JAXX0085')

weather = '---\n' + \
    result['title'] + '\n現在の' + \
    result['location']['city'] + u'の天気:' + \
    result['condition']['text'] + u'\n' +\
    u'---'

print weather
  • 結果
---
Yahoo! Weather - Tokyo, JA
現在のTokyoの天気:Partly Cloudy
---

レスポンスの中身を調べる

resultでYahoo!Weatherからのレスポンスの受け取っているので、resultをpprintで整然化して出力してみる。

  • コード
# -*- coding: utf-8 -*-
import pywapi
import pprint

result = pywapi.get_weather_from_yahoo('JAXX0085')

pp = pprint.PrettyPrinter(indent=4)

pp.pprint(result)
  • 結果
{   'astronomy': {   'sunrise': u'4:40 am', 'sunset': u'6:34 pm'},
    'atmosphere': {   'humidity': u'53',
                      'pressure': u'982.05',
                      'rising': u'0',
                      'visibility': u'9.99'},
    'condition': {   'code': u'30',
                     'date': u'Sun, 10 May 2015 11:00 am JST',
                     'temp': u'22',
                     'text': u'Partly Cloudy',
                     'title': u'Conditions for Tokyo, JA at 11:00 am JST'},
    'forecasts': [   {   'code': u'34',
                         'date': u'10 May 2015',
                         'high': u'26',
                         'low': u'11',
                         'text': u'Mostly Sunny'},
                     {   'code': u'34',
                         'date': u'11 May 2015',
                         'high': u'23',
                         'low': u'16',
                         'text': u'Mostly Sunny'},
                     {   'code': u'12',
                         'date': u'12 May 2015',
                         'high': u'22',
                         'low': u'19',
                         'text': u'Rain/Wind'},
                     {   'code': u'39',
                         'date': u'13 May 2015',
                         'high': u'26',
                         'low': u'17',
                         'text': u'AM Showers'},
                     {   'code': u'34',
                         'date': u'14 May 2015',
                         'high': u'28',
                         'low': u'18',
                         'text': u'Mostly Sunny'}],
    'geo': {   'lat': u'35.55', 'long': u'139.77'},
    'html_description': u'\n<img src="http://l.yimg.com/a/i/us/we/52/30.gif"/><br />\n<b>Current Conditions:</b><br />\nPartl
y Cloudy, 22 C<BR />\n<BR /><b>Forecast:</b><BR />\nSun - Mostly Sunny. High: 26 Low: 11<br />\nMon - Mostly Sunny. High: 23
Low: 16<br />\nTue - Rain/Wind. High: 22 Low: 19<br />\nWed - AM Showers. High: 26 Low: 17<br />\nThu - Mostly Sunny. High: 2
8 Low: 18<br />\n<br />\n<a href="http://us.rd.yahoo.com/dailynews/rss/weather/Tokyo__JA/*http://weather.yahoo.com/forecast/J
AXX0085_c.html">Full Forecast at Yahoo! Weather</a><BR/><BR/>\n(provided by <a href="http://www.weather.com" >The Weather Cha
nnel</a>)<br/>\n',
    'link': u'http://us.rd.yahoo.com/dailynews/rss/weather/Tokyo__JA/*http://weather.yahoo.com/forecast/JAXX0085_c.html',
    'location': {   'city': u'Tokyo', 'country': u'JA', 'region': u''},
    'title': u'Yahoo! Weather - Tokyo, JA',
    'units': {   'distance': u'km',
                 'pressure': u'mb',
                 'speed': u'km/h',
                 'temperature': u'C'},
    'wind': {   'chill': u'22', 'direction': u'40', 'speed': u'11.27'}}

プロパティの中身(分かる限り)

プロパティ名 入ってるもの
astronomy sunrise:日出時刻,
sunset:日没時刻
atmosphere humidity:湿度,
pressure:気圧
condition code:天気コード
date:取得時刻,
temp:現在気温,
text:天気予報,
title:タイトル
forecasts code:天気コード,
date:予報日付,
high:予報最高気温,
low:予報最低気温,
text:天気予報
location city:地域名
country:国名
units 各種単位(km,℃など)

地域コードの調べ方

pywapi.get_weather_from_yahoo('地域コード')

取得する際に天気情報を取得したい地域のコードを指定してあげる必要がある。

この調べ方についてはこちらのブログで詳細が説明されているので参考になる。

inside-my-box.hatenablog.com

具体的な使い方

  • コード
# -*- coding: utf-8 -*-
import pywapi

result = pywapi.get_weather_from_yahoo('JAXX0085')

tomorrow = '---\n' + \
            u'明日(' + result['forecasts'][1]['date'] + u')の' + \
            result['location']['city'] + u'の天気をお知らせします。\n' + \
            u'天気は' + result['forecasts'][1]['text'] + u'で、\n' + \
            u'最高気温は' + result['forecasts'][1]['high'] + u'℃、\n' + \
            u'最低気温は' + result['forecasts'][1]['low'] + u'℃です。\n' + \
            '---' 

print tomorrow
  • 結果
---
明日(11 May 2015)のTokyoの天気をお知らせします。
天気はMostly Sunnyで、
最高気温は23℃、
最低気温は16℃です。
---

11 May 2015を整形して分かりやすくする方法

result['forecasts'][1]['date']には、天気予報の日付が入っているんだけど、それが「11 May 2015」という表記。

日 + 月 + 年 こうなってるので、日本的に見やすく「年月日」に整形する。

Python標準ライブラリの datetime の strftime() と strptime() を使えば、10 May 2015→2015年5月10日 という感じに整形することができる。

詳しいドキュメントはこちら。

8.1. datetime — 基本的な日付型および時間型 — Python 2.7ja1 documentation

  • コード
# -*- coding: utf-8 -*-
import pywapi
import datetime

result = pywapi.get_weather_from_yahoo('JAXX0085')

print unicode(datetime.datetime.strptime(result['forecasts'][1]['date'],"%d %b %Y").strftime("%Y年%m月%d日"), 'utf-8')
  • 結果
2015年05月11日

分かりやすくなりました。

天気予報取得結果をツイートする方法

TwitterAPIとPythonのあれこれはこちらが分かりやすい。

qiita.com

上記の「ツイートを投稿」のコードを少しだけいじって、ツイートだけ出来るモジュールみたいなのを用意した。

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

from requests_oauthlib import OAuth1Session

def do_Tweet(content):
    CK = '**************'   # Consumer Key
    CS = '**************'   # Consumer Secret
    AT = '****-**********'  # Access Token
    AS = '**************'   # Accesss Token Secert

    # ツイート投稿用のURL
    url = "https://api.twitter.com/1.1/statuses/update.json"

    # ツイート本文
    tweet = {"status": content}

    # OAuth認証で POST method で投稿
    twitter = OAuth1Session(CK, CS, AT, AS)
    req = twitter.post(url, params = tweet)

    # レスポンスを確認
    if req.status_code == 200:
        print ("OK")
    else:
        print ("Error: %d" % req.status_code)

これを、さっき作ったスクリプトにインポートする

  • weather.py
# -*- coding: utf-8 -*-
import pywapi
import datetime
from tweet import do_Tweet

result = pywapi.get_weather_from_yahoo('JAXX0085')

date =  unicode(datetime.datetime.strptime(result['forecasts'][1]['date'],"%d %b %Y").strftime("%Y年%m月%d日"), 'utf-8')


tomorrow = '---\n' + \
            u'明日(' + date + u')の' + \
            result['location']['city'] + u'の天気をお知らせします。\n' + \
            u'天気は' + result['forecasts'][1]['text'] + u'で、\n' + \
            u'最高気温は' + result['forecasts'][1]['high'] + u'℃、\n' + \
            u'最低気温は' + result['forecasts'][1]['low'] + u'℃です。\n' + \
            '---' 

do_Tweet(tomorrow)

これで、ツイートが出来るようになる。

まとめ

今回はpywapiを使ってYahoo!WeatherのAPIを利用しました。

外部からリアルタイムに情報を取得すること自体が初めて(?)だったので、無事取得して出力できた時は「おぉ・・・!」って少し感動しました。

取得した天気は英語なので、Mostly Sunny → おおむね晴れ のように日本語へ変換してみようと、 ルックアップテーブルを作って一つ一つ英単語を日本語へ置換するコードも書いてみました。 けど、Yahoo!Weatherのドキュメントを参照するとドキュメントがどうも最新ではないらしく、どのような値が返ってくるのか正確に把握できない等の問題もあり日本語への置換は断念しました。取得した天気を文章っぽく整形して翻訳APIに通せば日本語の天気予報が出来るんじゃないかと考えてMicrosoft Translator API by Pythonを使ってみたりしたけど、不自然過ぎる感じに翻訳されるので(分かってたけど!)こちらも断念。

いろいろ考えて、いまは別の天気予報API(日本語)を使ってみてます。

いい感じに出来たらまた、記事にしたいと思います。

参考

天気情報を取得する(Python weather API) - ロボットと趣味と自堕落と