この記事について
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
関連記事
参考サイト
Dates(英語)
https://docs.julialang.org/en/v1/stdlib/Dates/index.html
HTTP(英語)
https://github.com/JuliaWeb/HTTP.jl
GithubなどはREADMEをちょっと読んだだけです。
実装開始!!!
# パッケージの宣言
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で取り扱う日付のフォーマットに設定
df = DateFormat("yyyymmdd")
sd = Date(StartDate,df)
ed = Date(EndDate,df)
Datesパッケージを使用して開始日と終了日を日付に変更していきます。
ここで一つ問題がありまして、Date関数を使用するとすべてyyyy-mm-ddの形式に変換されてしまいます。
yyyymmdd形式に戻す方法を知っている方がいましたら教えてください。
次がメインの接続部分です。
# 差分日数の取得
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)
# 高速接続をしないために待機1秒を置く
sleep(1)
end
catch e
nothing
end
end
Date型の引き算によって日付の差分を取得します。
これによって取得される値はDay型ですので、【days = Dates.value(d)】を使用して数値に直す必要があります。
このDay型をそのまま出力すると下の画像のように表示されます。
さきほども書きましたが、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にして保存をしてみたいと思います。
手探り状態ですの時間がかかると思いますが、次回もよろしくお願いします。
全コード
#---------------------------------------------------------------------------------------------------------------------------------------------------------------------
# このプログラムは気象庁の震源リストにアクセスをして日別の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)
# 高速接続をしないために待機1秒を置く
sleep(1)
end
catch e
nothing
end
end
修正履歴
以下のソースコードを修正しました
# 検索する日付を算出する
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)
↓修正後
# 検索する日付を算出する
SearchDay = sd + Dates.Day(day)
# DATE型のデータをyyyymmddの形式に戻す
# 検索用日付を作成(例:20170101)
SearchDate = Dates.format(SearchDay,df)
また、Dates.DateFormatを関数と表現しておりましたが、正確にはそれは型であり、Date型への変換を行っているのはDate関数でした。
こちらも併せて修正いたしました。