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

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

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

---

この記事 ([Pythonで天気予報をLINE通知する](https://qiita.com/kutsurogi194/items/6b9c8d37b2b83fc2ce87)) に触発されて、ちょこっとお天気の通知をやってみました。

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

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

# 地域IDを取得する
じゃあ早速 [WeatherHacks](http://weather.livedoor.com/weather_hacks/webservice) から天気予報を、、、と思ったんですが。
せっかくだから地域IDを固定じゃなくて、こっちも自動で取得してみようかな、と思い立ちました。

## XMLをダウンロードして変換する
http://weather.livedoor.com/forecast/rss/primary_area.xml
のXML :dizzy_face: の中の `rss/channel/ldWeather:source/pref/city` と辿って取得できる数字が地域IDだそうです。

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

```python
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でインストールしてください。

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

```python
# 市クラス
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):
        # リストじゃないのは１件だけの辞書として扱う
        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
```

```python
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)
```

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

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

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

```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
```

```python
# 検索してみる
city = searchCity("大阪")

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

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

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