Juliaで気象庁のホームページの情報を取得してファイルに保存する

# この記事について
Juliaに関して知識不足ですが、Qiitaにそもそも記事が少ないので書きました。
アドバイスがありましたらドシドシください。

Pythonを使って気象庁の震源リストデータを取得しようとしていたところ、後輩が先に作ってしまったのでせっかくだからJuliaでクローラーを作成しました。
アクセス先は気象庁の以下のページです。
http://www.data.jma.go.jp/svd/eqev/data/daily_map/

ホームページの構造としてはこのページの下に日毎のHTMLがつながっている感じです。
そのHTMLの名称がyyyymmdd.htmlなので、ループが簡単そうですね。

# 環境
### PC環境
Windows10

### ソフトウェア
Julia 1.0.3
***※注意※***
Julia 1.1.0では上手く動作しないと報告を受けています。ご注意ください。

### 使用パッケージ
HTTP
Dates

# 関連記事
[JuliaをインストールしてPlotsでグラフを表示する](https://qiita.com/yokotate/items/8366c2bbb750b46947d0)

# 参考サイト
Dates（英語）
https://docs.julialang.org/en/v1/stdlib/Dates/index.html
HTTP（英語）
https://github.com/JuliaWeb/HTTP.jl

GithubなどはREADMEをちょっと読んだだけです。

# 実装開始！！！

```julia:EarthQuake.jl
# パッケージの宣言
using HTTP
using Dates

# 検索のベースURL
BaseURL = "http://www.data.jma.go.jp/svd/eqev/data/daily_map/"
# 保存先のパス（任意のパス）
PATH = "C:\\user\\user_name\\Desktop\\Julia\\"
# 開始日と終了日を指定
# 形式は yyyyMMdd（例：20170101＝2017年1月1日）
# StartDate（開始日）が20170501なのはWebサービス上で最も古いデータがこの日付のため
StartDate = "20170501"
EndDate = "20170505"
```
ここまでは特に特徴的なものではなく、ほかの言語と同じように設定できると思います。
次に日付を指定していきます。

```julia:EarthQuake.jl
# Juliaで取り扱う日付のフォーマットに設定
df = DateFormat("yyyymmdd")
sd = Date(StartDate,df)
ed = Date(EndDate,df)
```
Datesパッケージを使用して開始日と終了日を日付に変更していきます。
ここで一つ問題がありまして、Date関数を使用するとすべてyyyy-mm-ddの形式に変換されてしまいます。
yyyymmdd形式に戻す方法を知っている方がいましたら教えてください。

次がメインの接続部分です。

```julia:EarthQuake.jl
# 差分日数の取得
d = ed - sd
days = Dates.value(d)

# 差分日数の分だけループを回す
for day in 0:days
    try
        # DATE型のデータをyyyymmddの形式に戻す
        SearchDay = sd + Dates.Day(day)
        year      = Dates.year(SearchDay)
        month     = Dates.month(SearchDay)
        day       = Dates.day(SearchDay)   
        # 月と日の0付け（桁合わせのため）
        if month <= 9
            month = string("0",month)
        end
        if day <= 9
            day = string("0",day)
        end
        # 検索用日付を作成（例：20170101）
        SearchDate = year
        SearchDate = string(SearchDate,month)
        SearchDate = string(SearchDate,day)
        
        # 検索日付が開始日以降であり、終了日以前であること
        # 強制終了条件として前日までの日付であること（基本的に当日のデータは整備されていない）
        if StartDate <= SearchDate && SearchDate <= EndDate && today() > SearchDay
            # 検索用のHTMLファイル名を生成
            SearchHTML = string(SearchDate,".html")
            # URL生成
            URL = string(BaseURL, SearchHTML)
            # URLを使用してリクエストを投げる
            r = HTTP.request("GET", URL)
            # 取得情報を保存
            f = open(string(PATH,string(SearchDate,".html")), "w")
            redirect_stdout(f)
            println(String(r.body))
            close(f)
            
            # 高速接続をしないために待機１秒を置く
            sleep(1)
        end
    catch e
        nothing
    end
end
```

Date型の引き算によって日付の差分を取得します。
これによって取得される値はDay型ですので、***【days = Dates.value(d)】***を使用して数値に直す必要があります。
このDay型をそのまま出力すると下の画像のように表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296240/a56f9780-bf3c-d979-db90-6c8b699b6cc7.png)

さきほども書きましたが、Date型のフォーマットをyyyymmddに直す方法が見つからなかったので、年月日を分解してくっつけています。
見た目がダサいのでどうにかしたいのですが、知っている方がいらっしゃいましたら教えてください。


```
HTTP.request("GET", URL)
```
重要なのはこの部分ですね。
ここでアクセスをしています。
注意事項としては、アクセス先が存在しない場合、ステータスコードが返ってくるわけではなく、エラーとしてプログラムが終了します。
ですので必ずTry文で囲ってください。

取得してきた内容を保存します。

```
f = open(string(PATH,string(SearchDate,".html")), "w")
redirect_stdout(f)
println(String(r.body))
close(f)
```
openで開いてredirect_stdoutでファイルに出力をさせます。
後は通常のprintln関数で出力していけば大丈夫です。

これを実行すると最初にPATHに設定した場所にHTMLファイルが作成されていると思います。

# 次回
次回は今回取得してきたHTMLから要素を取り出してCSVにして保存をしてみたいと思います。
手探り状態ですの時間がかかると思いますが、次回もよろしくお願いします。

# 全コード
```Julia:EarthQuake.jl
#---------------------------------------------------------------------------------------------------------------------------------------------------------------------
# このプログラムは気象庁の震源リストにアクセスをして日別のHTMLデータを取得してくるものです
# 開始日と終了日を指定してその間の日付のデータを取得してきますが、気象庁のシステムに対応しているものが2017年5月1日からのものしか存在しません。ご注意ください
# これよりも過去のデータに関しては別プログラムを用意します 
# 
# 使用パッケージ
# 1. HTTTP  Webページアクセスのためのパッケージ
# 2. Dates  日付操作用のパッケージ
#---------------------------------------------------------------------------------------------------------------------------------------------------------------------

using HTTP
using Dates

# 検索のベースURL
BaseURL = "http://www.data.jma.go.jp/svd/eqev/data/daily_map/"
# 検索用日付
SearchDate = ""
# 保存先のパス（任意のパス）
PATH = "C:\\user\\user_name\\Desktop\\Julia\\"
# 開始日と終了日を指定
# 形式は yyyyMMdd（例：20170101＝2017年1月1日）
# StartDate（開始日）が20170501なのはWebサービス上で最も古いデータがこの日付のため
StartDate = "20170501"
EndDate = "20170505"

# Juliaで取り扱う日付のフォーマットに設定
df = DateFormat("yyyymmdd")
sd = Date(StartDate,df)
ed = Date(EndDate,df)

# 差分日数の取得
d = ed - sd
days = Dates.value(d)

# 差分日数の分だけループを回す
for day in 0:days
    try
        # 検索する日付を算出する
        SearchDay  = sd + Dates.Day(day)
        # DATE型のデータをyyyymmddの形式に戻す
        # 検索用日付を作成（例：20170101）
        SearchDate = Dates.format(SearchDay,df)
        
        # 検索日付が開始日以降であり、終了日以前であること
        # 強制終了条件として前日までの日付であること（基本的に当日のデータは整備されていない）
        if StartDate <= SearchDate && SearchDate <= EndDate && today() > SearchDay
            # 検索用のHTMLファイル名を生成
            SearchHTML = string(SearchDate,".html")
            # URL生成
            URL = string(BaseURL, SearchHTML)
            # URLを使用してリクエストを投げる
            r = HTTP.request("GET", URL)
            # 取得情報を保存
            f = open(string(PATH,string(SearchDate,".html")), "w")
            redirect_stdout(f)
            println(String(r.body))
            close(f)
            
            # 高速接続をしないために待機１秒を置く
            sleep(1)
        end
    catch e
        nothing
    end
end
```

# 修正履歴
以下のソースコードを修正しました

```julia:
        # 検索する日付を算出する
        SearchDay  = sd + Dates.Day(day)
        # DATE型のデータをyyyymmddの形式に戻す
        # 検索用日付を作成（例：20170101）
        SearchDate = Dates.format(SearchDay,df)
        # 月と日の0付け（桁合わせのため）
        if month <= 9
            month = string("0",month)
        end
        if day <= 9
            day = string("0",day)
        end
        # 検索用日付を作成（例：20170101）
        SearchDate = year
        SearchDate = string(SearchDate,month)
        SearchDate = string(SearchDate,day)
```
↓修正後

```julia:
        # 検索する日付を算出する
        SearchDay  = sd + Dates.Day(day)
        # DATE型のデータをyyyymmddの形式に戻す
        # 検索用日付を作成（例：20170101）
        SearchDate = Dates.format(SearchDay,df)
```

また、Dates.DateFormatを関数と表現しておりましたが、正確にはそれは型であり、Date型への変換を行っているのはDate関数でした。
こちらも併せて修正いたしました。