コラボでGO!(3)退屈なことはPythonにやらせよう!ダウンロードの自動化

コラボでGO! Vol.3

ダウンロードの自動化を考えよう

この章では、ボートレース(競艇)のデータをダウンロードするやり方を紹介します。

「いやいや、ダウンロードって日付を選んでボタンを押すだけでしょ」

「その通り!(笑)」

いやいやいやいや! 確かに1つ1つのファイルを手作業でダウンロードすることも可能ですが、数ヶ月や数年分ともなれば骨の折れる作業ですよ。

ここではPythonを利用してダウンロードの自動化を考えてみましょう。

今では貴重な築古サイト

まずはボートレースの公式サイトを開いてください。

上のメニューから「データを調べる」→「ダウンロード・他」に進み、下の各種ダウンロードにある「競争成績ダウンロード」をクリックします。

すると、、、「ひえっ!」

これは貴重ですよ。Netscapeはボタンを押してって、何年前の話やねん!(笑)

月を選択するプルダウンメニューを開くと1996年7月から選ぶことができますが、その頃からこのページは存在し、レイアウトも変わっていないのでしょう。

表示域が狭いことから、当時のモニターの解像度が小さかった(恐らく640*480を想定している)ことがうかがえます。

1996年と言うことは、Windows 95が登場したのが1995年ですから、インターネットの黎明期からボートレースのデータが提供されていたことになります。担当者の熱意が感じられますね。

ページのソースをチェックしよう

ダウンロードを自動化するには、ファイルの住所であるURLを調べる必要があります。

ソースを見ると分かるのですが、このページでは今どき珍しいことにフレームが使われています。フレームとは、1つのページの中に複数のページを同時に表示させる機能のことです。

ここではフレームを使ってページを上下に分割し、上側で年月を選択すると下側に日にちのラジオボタン(を持つページ)が表示される仕組みになっています。

ダウンロードするファイルのURLを調べるには、「ダウンロード開始」ボタンがある下側のフレームに表示されているページのソース(htmlファイルの中身)を確認します。

ソースを見るには、下側のページ上で右クリックし「フレームのソースを表示」をクリックします。Chromeの場合は「検証」でも結構です。

ダウンロードするファイルのURLは、ソースの上部に書かれているJava Scriptが生成しています。その部分を見てみましょう。

コメントはテイモンがスクリプトの解説として追記しました。

<SCRIPT LANGUAGE="JavaScript">
<!--
    // 変数dirにベースとなるURLを代入。location.hostはドメイン名
    var dir="http://"+location.host+"/od2/K/202009/k2009";

    // ダウンロードボタンを押下したときに実行される関数
    function download(t){
        var i,m;
        // 日にちが選択されていない場合
        if(t.form.MDAY.length==null){
            m = t.form.MDAY.value;
        }
        // 日にちが選択されている場合
        else{
            for(i = 0; i < t.form.MDAY.length; i++){
                if(t.form.MDAY[i].checked){
                    // 変数mに選択した日付のvalue(2桁の日付)を代入
                    m = t.form.MDAY[i].value;
                    break;
                }
            }
        }
    // 変数locationにダウンロードするファイルのURLを代入
    location= dir +  m + ".lzh";
    }
//-->
</SCRIPT>

結論としては、上のスクリプトから生成されるURLは次の通りです。

http://www1.mbrace.or.jp/od2/K/202009/k2009 + 2桁の日付 + .lzh

年月の部分は、フレームの上部で選択した年月によって変わります。したがって、ダウンロードするファイルのURLのルールは次のようになると考えらえます。

http://www1.mbrace.or.jp/od2/K/YYYYMM/kYYMMDD.lzh

YYYY: 西暦4桁
YY: 西暦下2桁
MM: 月2桁
DD: 日2桁

例えば、2020年9月6日のURLは次の通りです。

http://www1.mbrace.or.jp/od2/K/202009/k200906.lzh

試しに、このURLをブラウザのURLボックスに貼り付けて実行してみてください。同日の競争成績がダウンロードできますね。

Pythonスクリプトを書いてみよう

URLのルールが分かったところで、いよいよダウンロードを自動化するためのスクリプトを考えてみましょう。ここで紹介するスクリプトは大きく分けて2つの作業をします。

  1. 指定された期間の日付リストを生成
  2. リストから日付を取り出してURLを生成しダウンロード

Pythonで日付を扱うには専用のモジュールをインポートする必要があります。ここではdatetimeを使いました。timedeltaと呼ばれる日付型を用いることで、期間を計算することができます。

初心者の人はこの辺りの説明を気にする必要はありません。テイモンのスクリプトには多くのコメントを入れていますので、それらをよく読みスクリプトの流れを理解するようにしましょう。

下のスクリプトの使い方は簡単です。コラボで作成したノートブックのセルに丸っと全部コピペして実行するだけです。コラボについては前の章を参照してください。

スクリプトの上部で期間を指定できるので、そこだけ任意の値に変更しましょう。コラボではなくローカル環境で実行する場合は、保存先も任意の場所に変更してください。それでは動かしてみましょう!

# 開始日と終了日を指定(YYYY-MM-DD)
START_DATE = "2020-09-01"
END_DATE = "2020-09-07"

# ファイルの保存先を指定 ※コラボでGoogleドライブをマウントした状態を想定
SAVE_DIR = "drive/My Drive/results_lzh/"

# リクエスト間隔を指定(秒) ※サーバに負荷をかけないよう3秒以上を推奨
INTERVAL = 3

# URLの固定部分を指定
FIXED_URL = "http://www1.mbrace.or.jp/od2/K/"

# 時間を制御する time モジュールをインポート
from time import sleep

# HTTP通信ライブラリの requests モジュールをインポート
from requests import get

# 日付を扱うための datetime モジュールをインポート
from datetime import datetime as dt
from datetime import timedelta as td

# フォルダ(ディレクトリ)を作成する makedirs モジュールをインポート
from os import makedirs

# 開始合図
print("作業を開始します")

# ファイルを格納するフォルダを作成
makedirs(SAVE_DIR, exist_ok=True)

# 開始日と終了日を日付型に変換して格納
start_date = dt.strptime(START_DATE, '%Y-%m-%d')
end_date = dt.strptime(END_DATE, '%Y-%m-%d')

# 日付の差から期間を計算
days_num = (end_date - start_date).days + 1

# 日付リストを格納する変数
date_list = []

# 日付リストを生成
for i in range(days_num):
    # 開始日から日付を順に取得
    target_date = start_date + td(days=i)

    # 日付型を文字列に変換してリストに格納(YYYYMMDD)
    date_list.append(target_date.strftime("%Y%m%d"))

# URL生成とダウンロード
for date in date_list:

    # URL生成
    yyyymm = date[0:4] + date[4:6]
    yymmdd = date[2:4] + date[4:6] + date[6:8]

    variable_url = FIXED_URL + yyyymm + "/k" + yymmdd + ".lzh"
    file_name = "k" + yymmdd + ".lzh"

    # ダウンロード
    r = get(variable_url)

    # 成功した場合
    if r.status_code == 200:
        f = open(SAVE_DIR + file_name, 'wb')
        f.write(r.content)
        f.close()
        print(variable_url + " をダウンロードしました")

    # 失敗した場合
    else:
        print(variable_url + " のダウンロードに失敗しました")

    # 指定した間隔をあける
    sleep(INTERVAL)

# 終了合図
print("作業を終了しました")

コラボで実行したとして、うまくいった場合は次のようになります。

1つ1つのファイルを手作業でダウンロードするよりも圧倒的に効率が良いですね!これで退屈なことをPythonにやらせることができました。

ダウンロードしたファイルはlzh形式で圧縮されていますので、次回はファイルの解凍を自動化することを考えてみましょう。

タイトルとURLをコピーしました