【Python3】WebAPIを叩く【requests】

# Pythonによるスクレイピング&機械学習
[Pythonによるスクレイピング&機械学習 開発テクニック BeautifulSoup,scikit-learn,TensorFlowを使ってみよう](https://www.amazon.co.jp/Python%E3%81%AB%E3%82%88%E3%82%8B%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0-%E9%96%8B%E7%99%BA%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF-BeautifulSoup-scikit-learn-TensorFlow%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86/dp/4802610793)より
学習ログ。
# 前回
[2-2](http://qiita.com/shunyooo/items/09cc636344212112a6fc)では

- ブラウザを経由したスクレイピング

を行いました。
主にjsが動いてるサイトでもスクレイプができるようになりました。
[2-3](http://qiita.com/shunyooo/private/132a1c9fa4f0af024c52)では、自分で題材を決めてスクレイプの実践的に行いました。限定公開にしているのは、大学サイトのスクレイピングは大学から怒られるんじゃないかと思ったのでフィードには載せないようにするためです、ごめんなさい。。

# この章で得られるもの
2-4では、**WebAPIからのデータ取得**を行っていきます。
ただ、API系は僕自身結構扱ってきているので、すごく浅くやらせていただきます。
また、自分なりの意見が多いので、流し読みでお願いいたします。

# 環境
Python 3.6.0

# WebAPIとは
通常Webページというのは、HTTP通信により、

1. クライアント(ブラウザ)からサーバに特定のページをリクエスト
2. HTMLやCSS、JSなどのViewファイルがレスポンス
3. レスポンスをブラウザ側でレンダー

という流れで表示されています。
WebAPIも取得に関しては同じ感覚です。
**違う点はクライアントの規格、レスポンスの規格と、レスポンスの扱いです。**
およそ以下の通りです。

1. クライアントからサーバに特定の情報をリクエスト
2. JSONなどの情報がレスポンス
3. レスポンスをなんかごにょごにょして扱う。

APIではクライアントは必ずhtmlをレンダーしなければならないわけではないので、http通信が行えれば、ブラウザでなくてもなんでもよいです。
また、情報の形式として、主にJSONが使われます。これはデータが記述してあるテキストになり、Webでのデータのやり取りする際の規格になっているものです。
クライアントでは、このJSONを受け取り、言語それぞれで扱いたいデータに変換してごにょごにょするわけです。

# WebAPIの提供一覧
「WebAPI 一覧」とかでググればムッチャ出てきます。
[API一覧まとめのまとめサイト](https://matome.naver.jp/odai/2141467922357348301)があったので載せておきます。

# 実際に使ってみる
教科書では[OpenWeatherMap](https://openweathermap.org/)という天気予報APIを使っています。[公式APIドキュメント](https://openweathermap.org/api)

実際の使い方は[こちら](http://qiita.com/nownabe/items/aeac1ce0977be963a740)を参考にすればだいじょうぶだと思います。

実装は以下

```py
import requests
import json

# APIキーの指定
apikey = "{あなたのAPIKEYを入れてください}"

# 天気を調べたい都市の一覧 
cities = ["Tokyo,JP", "London,UK", "New York,US"]
# APIのひな型
api = "http://api.openweathermap.org/data/2.5/weather?q={city}&APPID={key}"

# 温度変換(ケルビン→摂氏)
k2c = lambda k: k - 273.15

# 各都市の温度を取得する
for name in cities:
    # APIのURLを得る
    url = api.format(city=name, key=apikey)
    # 実際にAPIにリクエストを送信して結果を取得する
    r = requests.get(url)
    # 結果はJSON形式なのでデコードする
    data = json.loads(r.text)    
    # 結果を出力
    print("+ 都市=", data["name"])
    print("| 天気=", data["weather"][0]["description"])
    print("| 最低気温=", k2c(data["main"]["temp_min"]))
    print("| 最高気温=", k2c(data["main"]["temp_max"]))
    print("| 湿度=", data["main"]["humidity"])
    print("| 気圧=", data["main"]["pressure"])
    print("| 風向き=", data["wind"]["deg"])
    print("| 風速度=", data["wind"]["speed"])
    print("")
```

実行結果

```text
+ 都市= Tokyo
| 天気= broken clouds
| 最低気温= 15.0
| 最高気温= 19.0
| 湿度= 77
| 気圧= 1018
| 風向き= 110
| 風速度= 3.6

+ 都市= London
| 天気= light intensity shower rain
| 最低気温= 14.0
| 最高気温= 19.0
| 湿度= 55
| 気圧= 1008
| 風向き= 210
| 風速度= 8.2

+ 都市= New York
| 天気= mist
| 最低気温= 14.0
| 最高気温= 17.0
| 湿度= 88
| 気圧= 1008
| 風向き= 70
| 風速度= 1.5
```

とれました。

# 余談
このOpenWeatherMap、昔、JSでAPIを触っていた頃に使ったことがあります。
その頃は、GoogleMap,wiki,OpenWeatherMapのAPIを用いて、**GoogleMapでプロットした地理情報を動的に取得するページ**を作成しました。
一応まだ[動きます](http://syunyooo.webcrow.jp/GeoPlotSearch/)。(GoogleChrome推奨)
コードも[公開](https://github.com/shunyooo/GeoPlotSearch)しています（非常に汚いので参考にはあれですが）。

APIは動的なページでは、必ずと言っていいほど用いられています。
郵便番号からの住所補完や、GoogleMapの読み込みなどなど、、
その一例として、こんなものがつくれるよ、という感じです。

動作例
![Weather](https://cloud.githubusercontent.com/assets/17490886/24073279/7872e44e-0c38-11e7-9f81-172351f02d27.gif)

![wiki](https://cloud.githubusercontent.com/assets/17490886/24073326/4c3cc448-0c39-11e7-9b3f-26480dcca12d.gif)

動的なページはユーザビリティの向上に大きく役に立ちますが、SEOの観点ではリスクが発生します。
GoogleのSEO botは同一リンクに対してそのページのコンテンツを紐づけています。つまり、**URLとコンテンツが一意である前提でクロールを行うので、ページが動的であると、正しい紐付けができなくなるのです**。その回避策として、動的に読み込むごとにリンクを変更するなどがあるようです（URLはjsで動的に変更することができます）。

なので、実際に運用を考えると、ユーザビリティを向上させるか、SEOをとるかのトレードオフがあるかもしれませんね。