プログラミング素人のArduino

技術屋の末端。プログラミングは専門外。 電気回路も専門外です。 コードに間違いなど見つけられたら、気軽にコメントください。 VC#、ラズパイ始めました。

JSON形式からのData取得と辞書書式

APIの使い方を調べていくと、Twitterのようにライブラリ(CoreTweetやtweepyなど)が用意されているものはそれをインストールして使うことができますが、かならずしもライブラリがすべてあるとは限りません。一方で"JSON"という共通の方式で提供されているものがたくさん見つけられます。

これも、APIの一種?といっていいとおもいますが、JSONの扱い方がわかると応用も効きそうなので調べてみました。

JSONは"辞書オブジェクト"でDataが提供されています。

辞書オブジェクトは↓のような形式です。

score = {"math":75, "science":82,"english":"98"}
print(score)

とすると、

{"math":75, "science":82,"english":"98"}

と表示され、

print(score["math"])

とすると、

75

と表示されます。

実際のJSON形式を見てみると、データを取得する基本形が↓です。

import urllib
import json

url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=130010'
html = urllib.request.urlopen(url)
jsonfile = json.loads(html.read().decode('utf-8'))

これで、辞書形式で jsonfile にデータが取り込まれました。

ここではLivedoorのお天気情報を例にとりました。
weather.livedoor.com

APIのリクエスト例を参考にここでは東京を指定しました。

(例)「福岡県・久留米の天気」を取得する場合
下記URLにアクセスしてJSONデータを取得します。
基本URL + 久留米のID(400040)
http://weather.livedoor.com/forecast/webservice/json/v1?city=400040

実際にJSONを取得すると↓のようになります。形式が分かるように中身一部省略。

{'pinpointLocations': ['**省略**'],
'description':
 {'text': ' ※※tex省略※※', 'publicTime': '2017-10-29T10:49:00+0900'}
}

辞書が入れ子になっているようです。
ここでほしいのは、JSONの中の、descriptionキーの中のtextになります。

これは下のように記述します。

text =jsonfile['description']['text']

これで、下のように取得できます。

 前線が日本の南にあって、ゆっくり北上しています。また、台風第22号
が四国の南にあって北東へ進んでいます。

【関東甲信地方】
 関東甲信地方は雨となっており、伊豆諸島では雷を伴い激しく降っている
所があります。
 
 29日は、前線や台風の接近により雨で、伊豆諸島や関東地方南部では雷
を伴い非常に激しく降る所があるでしょう。

 30日は、冬型の気圧配置となるため、おおむね晴れますが、長野県や関
東地方北部の山沿いは、曇りで雨や雷雨となる所があり、標高の高い所では
次第に雪に変わる見込みです。

 関東近海では、30日にかけてうねりを伴い大しけとなるでしょう。船舶
は高波に警戒してください。

【東京地方】
 29日は、雨で、夜は雷を伴い激しく降る所があるでしょう。
 30日は、晴れる見込みです。

台風が来ていますね。(2017/10/29 11時現在)
これではすこし長いので、「東京地方」から後ろだけを取得します。

def weather():
    tdatetime = dt.now()
    url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=130010'
    html = urllib.request.urlopen(url)
    jsonfile = json.loads(html.read().decode('utf-8'))
    weather_txt = jsonfile['description']['text']
    try:
        index = weather_txt.find("【東京地方】")
        weather_txt = (weather_txt)[index:]
        weather_txt = '◆ラズパイ天気予報 ' + weather_txt
        api.update_status(weather_txt)  # tweet
    except:
        pass