Python3でJSONデータを解析する
ググって出てくるJSON解析の方法はPython2系ばっかりなので、Python3系でのやり方をまとめます。 JSONデータは「 pythonのurllib2でjsonを取得して解析する - 文系プログラマによるTIPSブログ 」でも使われているお天気Webサービスを使います。
APIから読み込む
JSON形式のデータはWEBAPIから呼ぶことが多いかと思います。Pythonの標準ライブラリurllibとjsonを使ってAPI経由でデータを取りに行きます。
import urllib import json url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=400040' html = urllib.request.urlopen(url) jsonfile = json.loads(html.read().decode('utf-8'))
これで変数jsonfile内にデータが格納されました。jsonfileを呼び出してやるとそれっぽいデータが返ってきます。 以下はiPython環境での出力サンプルです。
In [1]jsonfile Out[1]: {'copyright': {'image': {'height': 26, 'link': 'http://weather.livedoor.com/', 'title': 'livedoor 天気情報', 'url': 'http://weather.livedoor.com/img/cmn/livedoor.gif', 'width': 118}, 'link': 'http://weather.livedoor.com/', 'provider': [{'link': 'http://tenki.jp/', 'name': '日本気象協会'}], 'title': '(C) LINE Corporation'}, 'description': {'publicTime': '2016-04-30T16:32:00+0900', 'text': ' 九州北部地方は、高気圧に覆われ、晴れています。\n\n 30日の九州北部地方は、高気圧に覆われ、晴れでしょう。\n\n 5月1日の九州北部地方は、高気圧に覆われ、晴れでしょう。\n\n 波の高さは、対馬海峡では30日と5月1日は2メートルでしょう。九州\n西海上では30日と5月1日は1.5メートルでしょう。豊後水道では30\n日と5月1日は1メートルでしょう。\n 福岡県の内海では、30日と5月1日は0.5メートルでしょう。\n\n<天気変化等の留意点>\n 特にありません。'}, 'forecasts': [{'date': '2016-04-30', 'dateLabel': '今日', 'image': {'height': 31, 'title': '晴れ', 'url': 'http://weather.livedoor.com/img/icon/1.gif', 'width': 50}, 'telop': '晴れ', 'temperature': {'max': None, 'min': None}}, {'date': '2016-05-01', 'dateLabel': '明日', 'image': {'height': 31, 'title': '晴れ', 'url': 'http://weather.livedoor.com/img/icon/1.gif', 'width': 50}, 'telop': '晴れ', 'temperature': {'max': {'celsius': '26', 'fahrenheit': '78.8'}, 'min': {'celsius': '12', 'fahrenheit': '53.6'}}}, {'date': '2016-05-02', 'dateLabel': '明後日', 'image': {'height': 31, 'title': '晴のち曇', 'url': 'http://weather.livedoor.com/img/icon/5.gif', 'width': 50}, 'telop': '晴のち曇', 'temperature': {'max': None, 'min': None}}], 'link': 'http://weather.livedoor.com/area/forecast/400040', 'location': {'area': '九州', 'city': '久留米', 'prefecture': '福岡県'}, 'pinpointLocations': [{'link': 'http://weather.livedoor.com/area/forecast/4020200', 'name': '大牟田市'}, {'link': 'http://weather.livedoor.com/area/forecast/4020300', 'name': '久留米市'}, {'link': 'http://weather.livedoor.com/area/forecast/4020700', 'name': '柳川市'}, {'link': 'http://weather.livedoor.com/area/forecast/4021000', 'name': '八女市'}, {'link': 'http://weather.livedoor.com/area/forecast/4021100', 'name': '筑後市'}, {'link': 'http://weather.livedoor.com/area/forecast/4021200', 'name': '大川市'}, {'link': 'http://weather.livedoor.com/area/forecast/4021600', 'name': '小郡市'}, {'link': 'http://weather.livedoor.com/area/forecast/4022500', 'name': 'うきは市'}, {'link': 'http://weather.livedoor.com/area/forecast/4022800', 'name': '朝倉市'}, {'link': 'http://weather.livedoor.com/area/forecast/4022900', 'name': 'みやま市'}, {'link': 'http://weather.livedoor.com/area/forecast/4044700', 'name': '筑前町'}, {'link': 'http://weather.livedoor.com/area/forecast/4044800', 'name': '東峰村'}, {'link': 'http://weather.livedoor.com/area/forecast/4050300', 'name': '大刀洗町'}, {'link': 'http://weather.livedoor.com/area/forecast/4052200', 'name': '大木町'}, {'link': 'http://weather.livedoor.com/area/forecast/4054400', 'name': '広川町'}], 'publicTime': '2016-04-30T17:00:00+0900', 'title': '福岡県 久留米 の天気'}
要素ごとにアクセスしようとおもったら、パースした後の変数に引数を渡します。
In [1]:jsonfile['description'] Out[1]: {'publicTime': '2016-04-30T16:32:00+0900', 'text': ' 九州北部地方は、高気圧に覆われ、晴れています。\n\n 30日の九州北部地方は、高気圧に覆われ、晴れでしょう。\n\n 5月1日の九州北部地方は、高気圧に覆われ、晴れでしょう。\n\n 波の高さは、対馬海峡では30日と5月1日は2メートルでしょう。九州\n西海上では30日と5月1日は1.5メートルでしょう。豊後水道では30\n日と5月1日は1メートルでしょう。\n 福岡県の内海では、30日と5月1日は0.5メートルでしょう。\n\n<天気変化等の留意点>\n 特にありません。'}
はまりどころ
Python2系のurllib2ではエンコーディング処理までやってくれていたような気がします。 Python3のurllibではデコードしないとエラーが出ます。JSONのパース時にdecode('utf-8')でデコードします。
やりたいこと
これ使って総務省API(Ver2)を上手くたたく方法模索中。
追記
Pythonの2系ではurllib2を使ってURLを読み込むのが通例でした。
import urllib import urllib2 url = urllib2.urlopen('http://www.hogehoge.com')
python3系ではurllib2の持っていた機能がurllibに統合され、urllib.requestから呼び出せるようになっているようです。