pandasで気象庁のアメダスデータをスクレイピング

気象庁ホームページのの過去のアメダスデータから、Pythonでデータを取り出すことを考える。例として[福岡県八幡の1983年の月ごとの値のページ](https://www.data.jma.go.jp/obd/stats/etrn/view/monthly_a1.php?prec_no=82&block_no=0780&year=1983&month=&day=&view=)の合計降水量を取得してみる。
![JMA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77672/65e349ca-412f-770a-b459-fdd91e0c3cf3.png)

Pythonでデータを取り出す(スクレイピングする)方法は色々あるが、ここでは[pandas](https://pandas.pydata.org/)の[read_html](https://pandas.pydata.org/docs/reference/api/pandas.read_html.html)を使って簡単にやってしまおう。HTMLを解析する必要はない。

padasを読み込む。

```python
import pandas as pd
```
URLはこれ。

```python
url="https://www.data.jma.go.jp/obd/stats/etrn/view/monthly_a1.php?prec_no=82&block_no=0780&year=1983&month=&day=&view="
```

read_htmlを使う。これでWeb内のテーブルが読み込める。

```python
table=pd.read_html(url)
```

出力はリストで2つ内容が入っていることがわかる。

```python
print(type(table))
print(len(table))
```

    <class 'list'>
    2


1番目の中身。

```python
print(table[0])
```

         月 降水量(mm)               気温(℃)                                 風向・風速(m/s)  \
         月      合計  日最大  最大         平均                      最高      最低       平均風速   
         月      合計  日最大 1時間 10分間   日平均     日最高     日最低      最高      最低       平均風速   
    0    1      65   22   9  ///   5.9     9.1     2.6    15.9    -1.0        2.4   
    1    2      84   22  10  ///   5.0   8.2 )   1.3 )  14.1 )  -3.9 )        2.4   
    2    3     250   47  19  ///   9.0    12.2     5.7    20.3    -0.4        1.9   
    3    4     205   59  12  ///  15.3  19.1 )  10.7 )  27.7 )   3.9 )        2.3   
    4    5     154   64  20  ///  18.4    22.7    14.2    28.2     9.6        1.8   
    5    6     216   77  13  ///  21.5  25.4 )  17.8 )  29.2 )  13.9 )        1.8   
    6    7     280  125  20  ///  25.6    28.8    22.8    33.6    17.8        2.6   
    7    8     192  110  30  ///  27.2    30.7    24.2    35.1    20.9        2.1   
    8    9     212   60  32  ///  24.0    27.4    21.3    31.8    15.6        1.9   
    9   10      88   22   7  ///  17.8    21.7    13.9    26.9     7.1        1.5   
    10  11      37   23   5  ///  11.3    15.4     7.4    20.1     1.9        2.1   
    11  12      45   13   5  ///   6.4   9.2 )   3.0 )  16.1 )  -1.7 )        2.6   
    
                             日照時間(h) 雪(cm)              
       最大風速      最大瞬間風速      日照時間(h) 降雪の合計 日降雪の最大 最深積雪  
         風速   風向     風速   風向 日照時間(h) 降雪の合計 日降雪の最大 最深積雪  
    0     6  西北西    ///  ///   146.6   ///    ///  ///  
    1     9  西北西    ///  ///   152.5   ///    ///  ///  
    2     7    西    ///  ///   150.7   ///    ///  ///  
    3     8  西南西    ///  ///   186.4   ///    ///  ///  
    4     8  南南西    ///  ///   246.1   ///    ///  ///  
    5     9   南東    ///  ///   220.4   ///    ///  ///  
    6     7  南南西    ///  ///   220.8   ///    ///  ///  
    7     7  南南西    ///  ///   275.3   ///    ///  ///  
    8     7    北    ///  ///   185.5   ///    ///  ///  
    9     5  南南西    ///  ///   205.6   ///    ///  ///  
    10    7  西北西    ///  ///   188.1   ///    ///  ///  
    11    7  西北西    ///  ///   160.5   ///    ///  ///  


2番目の中身。

```python
print(table[1])
```

             0            1          2           3
    0  利用される方へ  よくある質問（FAQ）  気象観測統計の解説  年・季節・各月の天候

ということで、1番目の中身が欲しいテーブルだ。そこで、リストの1番目から中身を取りだして、typeを確かめて見れば、pandasのDataFrameになっていることがわかる。

```python
df=table[0]
print(type(df))
```

    <class 'pandas.core.frame.DataFrame'>

コラムの内容を見てみる。

```python
df.columns
```




    MultiIndex([(         '月',       '月',       '月'),
                (   '降水量(mm)',      '合計',      '合計'),
                (   '降水量(mm)',     '日最大',     '日最大'),
                (   '降水量(mm)',      '最大',     '1時間'),
                (   '降水量(mm)',      '最大',    '10分間'),
                (     '気温(℃)',      '平均',     '日平均'),
                (     '気温(℃)',      '平均',     '日最高'),
                (     '気温(℃)',      '平均',     '日最低'),
                (     '気温(℃)',      '最高',      '最高'),
                (     '気温(℃)',      '最低',      '最低'),
                ('風向・風速(m/s)',    '平均風速',    '平均風速'),
                ('風向・風速(m/s)',    '最大風速',      '風速'),
                ('風向・風速(m/s)',    '最大風速',      '風向'),
                ('風向・風速(m/s)',  '最大瞬間風速',      '風速'),
                ('風向・風速(m/s)',  '最大瞬間風速',      '風向'),
                (   '日照時間(h)', '日照時間(h)', '日照時間(h)'),
                (     '雪(cm)',   '降雪の合計',   '降雪の合計'),
                (     '雪(cm)',  '日降雪の最大',  '日降雪の最大'),
                (     '雪(cm)',    '最深積雪',    '最深積雪')],
               )


マルチインデックスのコラム名になってややこしいようであるが、ようはつなげていけば、細目に降りていく。

```python
df["降水量(mm)"]
```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead tr th {
        text-align: left;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr>
      <th></th>
      <th>合計</th>
      <th>日最大</th>
      <th colspan="2" halign="left">最大</th>
    </tr>
    <tr>
      <th></th>
      <th>合計</th>
      <th>日最大</th>
      <th>1時間</th>
      <th>10分間</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>65</td>
      <td>22</td>
      <td>9</td>
      <td>///</td>
    </tr>
    <tr>
      <th>1</th>
      <td>84</td>
      <td>22</td>
      <td>10</td>
      <td>///</td>
    </tr>
    <tr>
      <th>2</th>
      <td>250</td>
      <td>47</td>
      <td>19</td>
      <td>///</td>
    </tr>
    <tr>
      <th>3</th>
      <td>205</td>
      <td>59</td>
      <td>12</td>
      <td>///</td>
    </tr>
    <tr>
      <th>4</th>
      <td>154</td>
      <td>64</td>
      <td>20</td>
      <td>///</td>
    </tr>
    <tr>
      <th>5</th>
      <td>216</td>
      <td>77</td>
      <td>13</td>
      <td>///</td>
    </tr>
    <tr>
      <th>6</th>
      <td>280</td>
      <td>125</td>
      <td>20</td>
      <td>///</td>
    </tr>
    <tr>
      <th>7</th>
      <td>192</td>
      <td>110</td>
      <td>30</td>
      <td>///</td>
    </tr>
    <tr>
      <th>8</th>
      <td>212</td>
      <td>60</td>
      <td>32</td>
      <td>///</td>
    </tr>
    <tr>
      <th>9</th>
      <td>88</td>
      <td>22</td>
      <td>7</td>
      <td>///</td>
    </tr>
    <tr>
      <th>10</th>
      <td>37</td>
      <td>23</td>
      <td>5</td>
      <td>///</td>
    </tr>
    <tr>
      <th>11</th>
      <td>45</td>
      <td>13</td>
      <td>5</td>
      <td>///</td>
    </tr>
  </tbody>
</table>
</div>




```python
df["降水量(mm)"]["合計"]
```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>合計</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>65</td>
    </tr>
    <tr>
      <th>1</th>
      <td>84</td>
    </tr>
    <tr>
      <th>2</th>
      <td>250</td>
    </tr>
    <tr>
      <th>3</th>
      <td>205</td>
    </tr>
    <tr>
      <th>4</th>
      <td>154</td>
    </tr>
    <tr>
      <th>5</th>
      <td>216</td>
    </tr>
    <tr>
      <th>6</th>
      <td>280</td>
    </tr>
    <tr>
      <th>7</th>
      <td>192</td>
    </tr>
    <tr>
      <th>8</th>
      <td>212</td>
    </tr>
    <tr>
      <th>9</th>
      <td>88</td>
    </tr>
    <tr>
      <th>10</th>
      <td>37</td>
    </tr>
    <tr>
      <th>11</th>
      <td>45</td>
    </tr>
  </tbody>
</table>
</div>

```python
df["降水量(mm)"]["合計"]["合計"]
```




    0      65
    1      84
    2     250
    3     205
    4     154
    5     216
    6     280
    7     192
    8     212
    9      88
    10     37
    11     45
    Name: 合計, dtype: int64








最後の出力のtypeを確認すると、pandasのSeries形式になっている。

```python
type(df["降水量(mm)"]["合計"]["合計"])
```




    pandas.core.series.Series


後は、インデックスを日付形式にしたり、年でforループを回して連結したり、他の地点に変えたりと、いかようにも扱えるはず。