気象庁の紫外線画像をスクレイピングしてグラフにしてみる

1年くらい前に紫外線情報をスクレイピングしてCSVにしてグラフにするのをやってみました。最近、Pythonを勉強しなおす機運が高まったので振り返りも兼ねて記事にまとめました。
画像→CSVの過程で数値化した紫外線情報の正確さはあまり保証できぬ。

# 目次

1. スクレイピング
2. 画像からCSVに変換する
3. グラフ化

## Github

[リポジトリはこちら](https://github.com/scrpgil/uv-scraping/)


# スクレイピング
## 気象庁から過去12年間分の紫外線情報をスクレイピングする
まず、気象庁から紫外線情報を取得します。
気象庁は紫外線情報を__画像__の形で公開しているのでそれをひたすら取得します。
[例：2015年1月1日の紫外線情報](http://www.data.jma.go.jp/gmd/env/uvhp/ana/201501/A20150101_max.png)

以下は、当時書いたスクレイピングのシェル。2005年から2017年までの紫外線画像を30秒おきに取得しています。

```shell
#!/bin/sh
URL=http://www.data.jma.go.jp/gmd/env/uvhp/ana/
#201501/A20050101_max.png
DEST=list.txt
EXT="_max.png"
PNG=".png"

rm *.txt
echo "ID, RESULT, URL" > $DEST

for year in $(seq 2005 2017)
do
    FOLDER=$year
    mkdir $year
    for month in $(seq 1 12)
    do
        if [ $year = 2017 ]
        then
            if [ $month -ge 4 ]
            then
                echo "break"
                break
            fi
        fi
        month=`printf %02d $month`
        for day in $(seq 1 31)
        do
            day=`printf %02d $day`
            result=`curl -L $URL$year$month/A$year$month$day$EXT -o $FOLDER/$year$month$day$PNG -w '%{http_code}\n'`
            echo "$year$month$day, $result, $URL$year$month/A$year$month$day$EXT" >> $DEST
            if [ $result != 200 ]
            then
                rm $FOLDER/$year$month$day$PNG
            fi
            sleep 30
        done
    done
done
```

取得後は以下のようにフォルダに格納されます。
<img width="402" alt="Screen Shot 2018-06-08 at 15.59.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/165335/19e651aa-53e8-033e-0720-37caa46b5e00.png">


# 画像からCSVに変換する
紫外線情報は画像です。JSONとかだったら良かったんですけどね...。
画像なのでそのままでは扱えず一旦CSV形式に変換します。

## 方針
紫外線情報は色で示してあるので紫外線を取得したい箇所の色を調べれば紫外線情報が取得できるはず...。

## 画像に各都道府県の位置をマッピングする
まずは、画像の日本地図に各都道府県をマッピングします。
マッピングすると下のような感じ。黒い点が紫外線情報を取得する各都市。
<img width="984" alt="Screen Shot 2018-06-08 at 17.32.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/165335/9b41b365-13b8-40a5-5eed-95aefd0ebb56.png">

以下はマッピング情報を利用して画像からCSVに変換するプログラム。各ピクセルのRGBを取得して最も近い紫外線の色に変換しています。

```python
import cv2
import pandas as pd
import numpy as np
import os


w = np.genfromtxt('w.csv', delimiter=',')
w = w[1:, 4:]
area = w.astype(np.int64)
np.savetxt("area.csv", area, fmt='%.1f', delimiter=",")
for year in range(2005, 2018):
    ret = pd.read_csv("w.csv")
    uvDir = "uv-scrape/"
    y = str(year)
    files = os.listdir(uvDir + y)
    dir = "result_pd/" + y + "/"
    for f in files:
        st = uvDir + y + "/" + f
        img = cv2.imread(st)
        tmp = img[area[:, 0], area[:, 1]]
        uv = [[255, 255, 255],
              [255, 217, 217],
              [255, 203, 153],
              [190, 255, 255],
              [150, 250, 250],
              [0,   246, 250],
              [0,   200, 255],
              [0,   140, 255],
              [0,   90,  250],
              [0,   20,  255],
              [33,  0,   165],
              [91,  0,   181],
              [106, 0,   204],
              [204, 0,   204]]

        csv = np.zeros(142)
        for j in range(142):
            tako = []
            for i in range(14):
                tako.append(np.linalg.norm(tmp[j] - uv[i]))
                csv[j] = int(tako.index(min(tako)))
        csv = csv.T
        name, ext = os.path.splitext(f)
        # print(pd.to_datetime(name))
        ret[pd.to_datetime(name)] = csv.T
    ret.to_csv("result_pd/" + y + '.csv' )
    print("Finish: " + y + ".csv")
print("Finish!!!!!!")
```

```text(w.csv)
No,都市名,Y(緯度）,X(経度),Yのピクセル,Xのピクセル
1,北海道 稚内,45.4156641,141.6730822,17,255
2,北海道 旭川,43.7706355,142.364819,41,263
3,北海道 留萌,43.9409868,141.6370119,38,255
4,北海道 札幌,43.0620958,141.3543763,51,251
5,北海道 岩見沢,43.1962055,141.7759331,49,256
6,北海道 倶知安,42.9018294,140.7586977,53,243
7,北海道 網走,44.0206319,144.2733983,38,287
8,北海道 北見,43.8040314,143.8958758,40,282
9,北海道 紋別,44.3564842,143.3545032,34,276
10,北海道 根室,43.3300759,145.5827903,47,303
11,北海道 釧路,42.9848542,144.3813556,52,288
12,北海道 帯広,42.9238989,143.1961031,53,274
13,北海道 室蘭,42.3152306,140.9737991,62,246
14,北海道 浦河,42.1685159,142.7681204,64,268
15,北海道 函館,41.7687933,140.7288103,70,243
16,北海道 江差,41.8691558,140.12746,69,236
17,青森県 青森,40.8243077,140.7399984,84,243
18,青森県 むつ,41.2927457,141.1834755,77,249
19,青森県 八戸,40.5122839,141.4883986,88,252
20,秋田県 秋田,39.7186135,140.1023643,100,235
21,秋田県 横手,39.3137816,140.5666488,106,241
22,岩手県 盛岡,39.702053,141.1544838,101,248
23,岩手県 宮古,39.6414202,141.9571395,102,257
24,岩手県 大船渡,39.0819011,141.70853,110,255
25,宮城県 仙台,38.268215,140.8693558,122,245
26,宮城県 白石,38.0024779,140.6198605,126,242
27,山形県 山形,38.2404355,140.3636333,123,238
28,山形県 米沢,37.9222401,140.1167811,127,235
29,山形県 酒田,38.9147858,139.8365708,113,233
30,山形県 新庄,38.7650154,140.3016084,115,238
31,福島県 福島,37.7608337,140.4747282,129,240
32,福島県 小名浜,36.9468923,140.9218616,142,245
33,福島県 若松,37.4947611,139.9298096,134,233
34,茨城県 水戸,36.3665027,140.4709965,151,240
35,茨城県 土浦,36.0782972,140.2043331,155,237
36,栃木県 宇都宮,36.5551124,139.8828072,149,233
37,栃木県 大田原,36.871484,140.0174187,144,234
38,群馬県 前橋,36.3894816,139.0634281,151,222
39,群馬県 みなかみ,36.6786996,138.9990639,147,222
40,埼玉県 さいたま,35.8617292,139.6454822,159,230
41,埼玉県 熊谷,36.1473097,139.3886446,155,226
42,埼玉県 秩父,35.9920551,139.0848169,157,223
43,東京都 東京,35.7090259,139.7319925,161,231
44,東京都 大島,34.7500396,139.3555791,182,225
45,東京都 八丈島,33.1030212,139.8035566,203,230
46,東京都 父島,27.0750533,142.2116025,298,261
47,千葉県 千葉,35.6050574,140.1233063,168,236
48,千葉県 銚子,35.7346813,140.8266406,161,244
49,千葉県 館山,34.9965057,139.8699653,172,232
50,神奈川県 横浜,35.4437078,139.6380256,166,229
51,神奈川県 小田原,35.2645639,139.1521538,168,223
52,長野県 長野,36.6485829,138.1947709,148,211
53,長野県 松本,36.2380381,137.9720341,153,209
54,長野県 飯田,35.5149777,137.8214466,164,207
55,山梨県 甲府,35.66228,138.5682015,162,216
56,山梨県 河口湖,35.4973137,138.7550838,164,218
57,静岡県 静岡,34.9771201,138.3830845,172,214
58,静岡県 網代,35.0484388,139.0915361,171,223
59,静岡県 三島,35.1184025,138.9185126,170,221
60,静岡県 浜松,34.7108344,137.7261258,176,206
61,愛知県 名古屋,35.1814464,136.906398,170,195
62,愛知県 豊橋,34.7691995,137.3914662,176,201
63,岐阜県 岐阜,35.4232984,136.7606537,166,194
64,岐阜県 高山,36.1461236,137.2521729,155,200
65,三重県 津,34.718596,136.5056975,176,190
66,三重県 尾鷲,34.0707989,136.1909953,186,186
67,新潟県 新潟,37.9025518,139.0230946,129,222
68,新潟県 長岡,37.4462652,138.8512772,134,220
69,新潟県 高田,37.1042625,138.2560998,147,212
70,新潟県 相川,37.179519,138.250289,144,212
71,富山県 富山,36.6952907,137.2113383,151,199
72,富山県 伏木,36.78994,137.0569881,150,197
73,石川県 金沢,36.5613254,136.6562051,154,192
74,石川県 輪島,37.3905901,136.8991957,138,195
75,福井県 福井,36.0651779,136.2215269,158,187
76,福井県 敦賀,35.6452443,136.0554408,162,185
77,滋賀県 大津,35.0178929,135.8546074,172,182
78,滋賀県 彦根,35.274461,136.2596226,168,187
79,京都府 舞鶴,35.4747971,135.3859918,170,176
80,京都府 京都,35.0212466,135.7555968,172,181
81,大阪府 大阪,34.6862971,135.5196609,177,178
82,兵庫県 神戸,34.690083,135.1955112,177,174
83,兵庫県 豊岡,35.5445754,134.8201814,164,169
84,奈良県 奈良,34.6850869,135.8050002,178,182
85,奈良県 風屋,34.043805,135.7817794,187,181
86,和歌山県 和歌山,34.2305113,135.1708083,184,174
87,和歌山県 潮岬,33.4479784,135.7614191,196,181
88,岡山県 岡山,34.6617511,133.9344057,178,158
89,岡山県 津山,35.0691155,134.0045428,171,159
90,広島県 広島,34.3965603,132.4596225,181,139
91,広島県 庄原,34.8577316,133.0172775,175,147
92,島根県 松江,35.4680595,133.048375,172,147
93,島根県 浜田,34.8993025,132.0797833,173,135
94,島根県 西郷,35.4343758,132.8078732,166,144
95,鳥取県 鳥取,35.5038906,134.2377356,169,162
96,鳥取県 米子,35.4280717,133.3309447,166,150
97,徳島県 徳島,34.0702703,134.5548438,191,163
98,徳島県 日和佐,33.728915,134.530537,196,163
99,香川県 高松,34.3427879,134.046574,189,160
100,愛媛県 松山,33.8391574,132.7655752,193,143
101,愛媛県 新居浜,33.9602895,133.2833512,188,150
102,愛媛県 宇和島,33.2233404,132.5605575,199,141
103,高知県 高知,33.5595867,133.5292788,195,153
104,高知県 室戸岬,33.2680092,134.1641616,199,151
105,高知県 清水,32.7816335,132.9549889,210,143
106,山口県 下関,33.9578307,130.941459,189,120
107,山口県 山口,34.1859563,131.4706493,185,127
108,山口県 柳井,33.9638333,132.1015969,190,133
109,山口県 萩,34.4081155,131.3990849,182,126
110,福岡県 福岡,33.5903547,130.4017155,199,113
111,福岡県 八幡,33.869238,130.795365,195,118
112,福岡県 飯塚,33.6459075,130.6915113,200,117
113,福岡県 久留米,33.3192865,130.5083735,198,115
114,大分県 大分,33.2381718,131.6126189,204,128
115,大分県 中津,33.5982211,131.1883247,201,123
116,大分県 日田,33.3213327,130.9409659,198,120
117,大分県 佐伯,32.959806,131.9000575,204,132
118,長崎県 長崎,32.7502856,129.877667,213,107
119,長崎県 佐世保,33.1799153,129.7151101,205,106
120,長崎県 厳原,34.202646,129.287521,188,100
121,長崎県 福江,32.7018615,128.7577605,207,93
122,佐賀県 佐賀,33.2494416,130.2997942,200,112
123,佐賀県 伊万里,33.2645856,129.880269,199,107
124,熊本県 熊本,32.789827,130.7416672,206,118
125,熊本県 阿蘇乙姫,32.9434447,131.0434341,204,122
126,熊本県 牛深,32.1906829,130.0262228,222,111
127,熊本県 人吉,32.2100405,130.7625544,216,118
128,宮崎県 宮崎,31.9110956,131.4238934,223,124
129,宮崎県 延岡,32.5822723,131.6650094,210,129
130,宮崎県 都城,31.7195903,131.0616214,223,122
131,宮崎県 高千穂,32.71169,131.3077866,209,125
132,鹿児島県 名瀬,28.367285,129.500979,278,99
133,鹿児島県 鹿児島,31.5965535,130.5571158,229,113
134,鹿児島県 鹿屋,31.3782921,130.8520774,229,119
135,鹿児島県 種子島,30.609558,130.9788775,248,117
136,沖縄県 那覇,26.2123124,127.6791568,312,76
137,沖縄県 名護,26.5915465,127.9773162,303,83
138,沖縄県 久米島,26.3503959,126.7711774,309,66
139,沖縄県 南大東島,25.8288983,131.2318762,318,124
140,沖縄県 宮古島,24.80549,125.2811486,331,48
141,沖縄県 石垣島,24.4064027,124.1754442,342,34
142,沖縄県 与那国町,24.4679685,123.0044532,342,19
```
w.csvには各都道府県と画像のX、Y軸がマッピングされています(計算式は探したけど見つからず。どこかに残しておくべきだった。)

先程のプログラムを実行すると以下のようにresultフォルダにCSVが作成されます。
<img width="412" alt="Screen Shot 2018-06-08 at 17.35.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/165335/34403dd9-12f2-acc0-2886-d2523748f357.png">

# グラフ化
CSV化できたらグラフ化は楽です。

## 2006年の東京の紫外線情報のグラフ化（日ごと）

```python
import pandas as pd
%matplotlib inline

src = pd.read_csv("result_pd/2006.csv")
csv = src.drop(["Unnamed: 0", "No", "都市名", "Y(緯度）", "X(経度)", "Yのピクセル", "Xのピクセル"], axis=1)
csv = csv.T
#print(csv)

csv = csv.loc[:, [42]]
# csv.columns =  csv.rename(columns=src["都市名"])

# print(csv)
csv.index = pd.to_datetime(csv.index)
# csv.head()
csv.plot(figsize=(12,5), ylim=(0, 13), grid=1, yticks=[0,1,2,3,4,5,6,7,8,9,10,11,12,13])
```

<img width="728" alt="Screen Shot 2018-06-08 at 17.39.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/165335/809dfac9-919e-8616-87c8-f8e05a58fe1b.png">

## 2005年5月17日から2017年3月24日までの東京と沖縄の紫外線量

```python
import pandas as pd
%matplotlib inline

for year in range(2005, 2018):
    src = pd.read_csv("result_pd/" + str(year) + ".csv")
    csv = src.drop(["Unnamed: 0", "No", "都市名", "Y(緯度）", "X(経度)", "Yのピクセル", "Xのピクセル"], axis=1)
    csv = csv.T
    #print(csv)

    csv = csv.loc[:, [42, 141]]
    # csv.columns =  csv.rename(columns=src["都市名"])
    
    csv = csv.rename(columns={42: src["都市名"][42], 141: src["都市名"][141]})
    csv.index = pd.to_datetime(csv.index)
    csv.plot(title=str(year),figsize=(12,5), ylim=(0, 13), grid=1, yticks=[0,1,2,3,4,5,6,7,8,9,10,11,12,13])
```

<img width="721" alt="Screen Shot 2018-06-08 at 17.40.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/165335/500811e7-f86c-4929-7288-d588c06f4dcb.png">

## 2006年から2017年までの各都市の紫外線量

```python
import pandas as pd
%matplotlib inline


# No = [3, 16, 42, 60, 80, 109, 132, 135]

No = [3, 37, 40, 42, 48, 50, 80,132, 135]
for year in range(2006, 2017):
    src = pd.read_csv("result_pd/" + str(year) + ".csv")
    csv = src.drop(["Unnamed: 0", "No", "都市名", "Y(緯度）", "X(経度)", "Yのピクセル", "Xのピクセル"], axis=1)
    csv = csv.T
    #print(csv)

    csv = csv.loc[:, No]
    # csv.columns =  csv.rename(columns=src["都市名"])
    #  csv = csv.rename(columns={3: src["都市名"][3], 42: src["都市名"][42], 109: src["都市名"][109]})
    for i in No:
        csv = csv.rename(columns={i: src["都市名"][i]})
    csv.index = pd.to_datetime(csv.index)
    csv = csv.resample('M').mean()
    csv.index = ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
    csv.plot.bar(title=str(year),figsize=(12,5), ylim=(0, 13), grid=1, yticks=[0,1,2,3,4,5,6,7,8,9,10,11,12,13])
```

<img width="712" alt="Screen Shot 2018-06-08 at 17.41.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/165335/fb437362-f7bf-43ab-bb8b-3ff04b3df0ba.png">


# まとめ
今見ると画像に各都市の位置情報をマッピングするところが怪しいですね...。
あと、少し触らないと忘れてしまいますね。

最近、colaboratoryの存在を知ったので記憶をたどりながらPythonをもう一度勉強し直したいと思います。