OpenWeatherMap APIで取得したXMLを整形して表示。

　こんにちは、クイックイタレート株式会社の加藤　義也と申します。
　現在「[始めるならpythonをおすすめする理由](https://m.amebaownd.com/#/sites/233191/posts/editor/2559673)」というブログ記事を書いています。

# やりたい事

**事務所の天気予報をXMLで取得して整形して表示してみます。**

# 環境
- Windows10 Home
- anaconda navigator 4.4.0
- python 3.6.1
    - urllib  --URLを指定してコンテンツを取得するライブラリ）
    - ElementTree  --XMLファイルを解釈・変更するライブラリ


#構成要素を考えて見ます。

- 十分な情報を提供してくれるサービスを探す。
- サービスの使い方を調査する。
- リクエストを作る。
- 取得したXMLから必要な情報を抽出する。
- 抽出した情報をきれいに表示する。

#お天気APIサービスの候補
「天気予報 API フリー」で検索してみると
以下のサービスが存在していることが分かりました。
- [Livedoor お天気Webサービス](http://weather.livedoor.com/weather_hacks/webservice)
- [OpenWeatherMap](https://openweathermap.org/api)
今回は「[OpenWeatherMap](https://openweathermap.org/api)」を使ってみたいと思います。


#API概要

[OpenWeatherMap](https://openweathermap.org/)は様々な方法で詳細な情報が取得出来る様に構成されています。
抜粋して表にしてみます。

| パラメータ |       意味                                     |       値例       |       必須       |
|:-----------|:----------------------|:----------------:|:----------------:|
| URL        |リクエストを送付する宛先 |http://api.openweathermap.org/data/2.5/forcast?|       必須       |
| appid      |割りあてられたID        |       必須 *1      |       必須       |
| name       |都市固有の名称    |   tokyo-to   |     オプション*2 |
| id         |都市固有のID(cityid)    |   1850144   |     オプション*2 |
| lat        |10進数表記の緯度        |   35.78   |     オプション*2 |
| lon        |10進数表記の緯度        |   139.83      |     オプション*2       |
| zip        |郵便番号               |     1210053       |     オプション*2       |
| country    |国名略称（zip指定時）|  jp        |    オプション*2     |
| unites     |表記単位 *1       |metric or imperial or 無し |オプション*2|
| mode       |取得形式の指定       |xml or json or html |オプション*2|


*1 appidは[こちら](https://home.openweathermap.org/users/sign_up)からユーザー登録後、[こちら](https://home.openweathermap.org/api_keys)で取得出来ます。
*2 「name」「id」 か 「lat & lon」 か 「zip & contry」 で場所を指定する必要があります。
値例には弊社事務所の[所在地](http://www.quickiterate.com/pages/753180/page_201602191746)を設定しておりますが実際には必要な場所をご指定ください。
cityid、countryの詳細な指定方法は[こちら](http://bulk.openweathermap.org/sample/)に記載されています。
APIの詳細は[こちら](https://openweathermap.org/api)(英語です。^^;)に記載されています。

| リクエストURLのイメージ（Cityidを使った場合)  |
|:-------------------------|
|http://api.openweathermap.org/data/2.5/forecast?id=1850144&APPID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&units=metric&mode=xml |

| リクエストURLのイメージ（緯度・経度を使った場合)  |
|:-------------------------|
|http://api.openweathermap.org/data/2.5/forecast?lon=139.83&lat=35.78&APPID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&units=metric&mode=xml |

#pythonのコード

では情報が整ったところで早速pythonを使って情報を取得し、整形されたXMLの形で表示してみたいと思います。

```py:openweathermap.py
#ライブラリのインポート
import urllib.request
import urllib.parse
import xml.etree.ElementTree as et
import xml.dom.minidom as md
url='http://api.openweathermap.org/data/2.5/forecast?' #基底URLの設定
query = {
        'id'    : '1850144' ,
        'APPID' : 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', #あなたが取得したappid
        'units'  : 'metric',
        'mode'  : 'xml'}#クエリに設定する値群
url = url + urllib.parse.urlencode(query) #リクエストURLの生成
response = urllib.request.urlopen(url) #httpリクエスト
root = et.fromstring(response.read()) #取得したコンテンツをXML Elementに格納
```

リクエストに使用したurlの中身を確認します。

```text:生成されるurlを確認
print(url) #urlの中身を表示
http://api.openweathermap.org/data/2.5/forecast?id=1850144&APPID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&units=metric&mode=xml
```



```py:xmlを表示するコード
document = md.parseString(et.tostring(root, 'utf-8')) #minidomモジュールが XML Elementをパース
print(document.toprettyxml(indent="  ")) #パースされたXML情報をインデント付きで文字列に変換して表示
```

リクエストで帰ってきた値を実際に整形されて出力されたXMLです。

```xml:result.xml
<?xml version="1.0" ?>
<weatherdata>
  <location>
    <name>Tōkyō-to</name>
    <type/>
    <country>JP</country>
    <timezone/>
    <location altitude="0" geobase="geonames" geobaseid="1850144" latitude="35.6895" longitude="139.6917"/>
  </location>
  <credit/>
  <meta>
    <lastupdate/>
    <calctime>0.0129</calctime>
    <nextupdate/>
  </meta>
  <sun rise="2017-06-23T19:26:28" set="2017-06-24T10:00:54"/>
  <forecast>
    <time from="2017-06-24T06:00:00" to="2017-06-24T09:00:00">
      <symbol name="broken clouds" number="803" var="04d"/>
      <precipitation/>
      <windDirection code="SSE" deg="148.001" name="South-southeast"/>
      <windSpeed mps="2.41" name="Light breeze"/>
      <temperature max="24.68" min="23.88" unit="celsius" value="23.88"/>
      <pressure unit="hPa" value="1015.57"/>
      <humidity unit="%" value="66"/>
      <clouds all="56" unit="%" value="broken clouds"/>
    </time>
    ・・（途中省略）・・
  </forecast>
</weatherdata>

```

次回はXMLの内容を抽出して加工してみたいと思います。

#記事を書いた際、参考にさせて頂いたサイト等
- [Livedoor お天気Webサービス](http://weather.livedoor.com/weather_hacks/webservice)
- [OpenWeatherMap](https://openweathermap.org/)
- [ElementTree XML API](https://docs.python.jp/3/library/xml.etree.elementtree.html)
- [URL を開くための拡張可能なライブラリ](https://docs.python.jp/3/library/urllib.request.html#module-urllib.request)
- [Python による XML の操作](http://www.geocities.jp/penguinitis2002/computer/programming/Python/xml.html)
- [pythonの内部表現からxmlへの出力](http://kensuke-mi.hatenablog.com/entry/20130929/1380419861)
- [PythonのElementTreeを使ってXMLをパースする方法](https://remotestance.com/blog/136/)

ありがとうございます。