13
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Pythonで少し詳しいお天気情報をLINEに通知する (1)

Last updated at Posted at 2018-03-16

ご注意
以下のURLにあるように、WeatherHacksは2020/7/31でサービスを終了したようです。
https://help.livedoor.com/weather/index.html
残念です :cry:

本記事は残しますが、記事中のサイトには接続できない状態なので、あくまでプログラミングの参考としてご使用ください。


この記事 (Pythonで天気予報をLINE通知する) に触発されて、ちょこっとお天気の通知をやってみました。

天気アプリとか入れててもいまいち使えてないので、LINEで通知されたら見るんかなあ?というのが動機のひとつです。

ちなみに、私は Python 2.7.14 を使ってます。
Mac標準からあんまり環境いじっておりません。

地域IDを取得する

じゃあ早速 WeatherHacks から天気予報を、、、と思ったんですが。
せっかくだから地域IDを固定じゃなくて、こっちも自動で取得してみようかな、と思い立ちました。

XMLをダウンロードして変換する

http://weather.livedoor.com/forecast/rss/primary_area.xml
のXML :dizzy_face: の中の rss/channel/ldWeather:source/pref/city と辿って取得できる数字が地域IDだそうです。

まず直接アクセスして、XML->辞書型に変換してみます。

url = "http://weather.livedoor.com/forecast/rss/primary_area.xml"

primary_area = urllib2.urlopen(url)

primary_area_dict = xmltodict.parse(primary_area)

# 県情報だけ抜き出し
pref_list = primary_area_dict["rss"]["channel"]["ldWeather:source"]["pref"]

XMLの変換ライブラリは xmltodict を使ってます。pipでインストールしてください。

せっかくなので、クラス作ってさらに必要な部分だけ選り分けます。

# 市クラス
class City(object):
    def __init__(self, pref_name, name, city_id):
        self.pref_name = pref_name
        self.name = name
        self.city_id = city_id

# 県クラス
class Pref(object):
    def __init__(self, name, city_list):
        self.name = name
        self.city_list = city_list

def searializeCity(pref_name, city_dict):
    # 県名
    pref_name_trans = pref_name
    if pref_name in ["道北", "道東", "道南", "道央", "道西"]:
        # 北海道はいっぱいある
        pref_name_trans = "北海道"

    # 名前
    name = ""
    if city_dict["@title"]:
        name = city_dict["@title"].encode("utf-8")

    # ID
    city_id = ""
    if city_dict["@id"]:
        city_id = city_dict["@id"].encode("utf-8")

    # 市
    city = City(pref_name_trans, name, city_id)
    return city

def serializePref(pref_dict):
    # 名前
    pref_name = ""
    if pref_dict["@title"]:
        pref_name = pref_dict["@title"].encode("utf-8")

    # 市リスト
    city_list = []
    if not isinstance(pref_dict["city"], list):
        # リストじゃないのは1件だけの辞書として扱う
        city_dict = pref_dict["city"]
        city = searializeCity(pref_name, city_dict)
        city_list.append(city)
    else:
        for city_dict in pref_dict["city"]:
            city = searializeCity(pref_name, city_dict)
            city_list.append(city)

    if len(city_list) > 0:
        # 県
        pref = Pref(pref_name, city_list)
        return pref
    else:
        return None
url = "http://weather.livedoor.com/forecast/rss/primary_area.xml"

primary_area = urllib2.urlopen(url)

primary_area_dict = xmltodict.parse(primary_area)

# 県情報だけ抜き出し
pref_list = primary_area_dict["rss"]["channel"]["ldWeather:source"]["pref"]

# 変換してみる
pref_list = []
for pref_dict in pref_dict_list:
    pref = serializePref(pref_dict)
    if pref is not None:
        pref_list.append(pref)

辞書に変換する間に、キーがいつのまにか @ 付きになってたり、1件だけの場合はリストじゃなくて、いきなり単体の値になってたり、など諸々問題ありましたがなんとかやりました。
そもそもORマッパーとか探して使えよですが、まだまだPythonシロートなので許してください。

ちなみに、北海道だけ東西南北で別れてるので、県名を変換してあります。

市名から検索できるようにする

上記で変換した内容を使って、市名から検索かけれるようにしてみます。

def getPrefList():

    # primary_areaのxmlファイルURL
    url = "http://weather.livedoor.com/forecast/rss/primary_area.xml"

    try:
        # ファイル情報取得
        primary_area = urllib2.urlopen(url)

        # 辞書に変換
        primary_area_dict = xmltodict.parse(primary_area)

        # 県情報だけ抜き出し
        pref_list = primary_area_dict["rss"]["channel"]["ldWeather:source"]["pref"]
        if pref_list:
            return pref_list
        else:
            return []

    except Exception as e:
        raise e
        return []

def searchCity(city_name):

    # 県情報を取得
    pref_dict_list = getPrefList()

    # 変換
    pref_list = []
    for pref_dict in pref_dict_list:
        pref = serializePref(pref_dict)
        if pref is not None:
            pref_list.append(pref)

    # 対象の市を検索する
    for pref in pref_list:
        for city in pref.city_list:
            if city.name == city_name:
                return city

    return None
# 検索してみる
city = searchCity("大阪")

# 大阪府
print city.pref_name
# 大阪
print city.name

市名で検索するとか使いやすいのか謎ですけど、とりあえずはできました。

長くなってきたので、続きはまた後日!

13
7
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?