前々からロト6の当選番号を機械学習で予測してみたいと思っており、やっと作業に着手し始めたので予測方法をまとめていきます。

機械学習で予測するには過去の当選番号を学習データとして収集する必要があるので、この記事ではみずほ銀行のページからPythonでスクレイピングを行い、過去の当選番号を自動的に収集する方法を説明していきます。



事前準備


今回スクレイピングをするにあたり、以下の3つの技術要素を利用します。
  • BeautifulSoup(スクレイピングを行うライブラリ)
  • Selenium(ブラウザの自動操作を行うツール)
  • PhantomJS(ヘッドレスブラウザ)
最初はBeautifulSoupだけを使用してスクレイピングをしようと思ったのですが、第461回目以降の当選番号が掲載されているページではJavascriptを使ってページが書かれており、BeautifulSoupだけでは集めることができなかったのでSeleniumとPhantomJSを使用することにしました。

以下インストール方法を説明していきます。


1. BeautifuSoupのインストール


BeautifulSoupはpipで導入する場合、以下のコマンドでインストールすることができます。
pip install beautifulsoup4
Anacondaを使っていてpipが使えない場合、以下のコマンドでインストールすることができます。
conda install -c anaconda beautifulsoup4


2. Seleniumのインストール


Seleniumはpipで導入する場合、以下のコマンドでインストールすることができます。
pip install selenium
Anacondaでインストールする場合、以下のコマンドでインストールすることができます。
conda install -c conda-forge selenium


3. PhantomJSのインストール


Windowsで導入する場合の手順は以下の通りになります。
  1. http://phantomjs.org/にアクセスしてサイトからダウンロード
  2. ダウンロードしたファイルを解凍し、c:\の直下に置く
  3. Pathを通す
よくわからない方は以下のページが参考になると思います。
https://gist.github.com/maechabin/7632c460ceede823cbde


Anacondaを使っている場合はPhantomJSもコマンド一つでインストールすることができます。
conda install -c conda-forge phantomjs
このコマンドはWindowsでも使えるため、WindowsでPythonを使うならばAnacondaを使った方が色々と便利そうですね。




過去の当選番号をスクレイピングしていく


環境構築ができたらスクレイピングをしています。今回コードを書く前に当選番号が掲載されているページのURLのパターンと、各ページでの当選番号の取得方法について考えていきます。


当選番号が掲載されているページのURLのパターン


ロト6の過去の当選番号はみずほ銀行のホームページで20回ごとにページを分けて掲載されています。そのためスクレイピングをする際に自動的にページを遷移させる必要があります。ここで一つ問題があり、第1回~第460回までの結果がのっているページのURLと第461回目以降の結果がのっているページのURLはパターンが違うため収集する際に注意しなければなりません。

第1回~第460回までのURLは以下のようになっています。(第1回目~第20回目の例)
https://www.mizuhobank.co.jp/retail/takarakuji/loto/backnumber/loto60001.html

ページごとに赤字で書いている部分が変更しており、
第1回目~第20回目の場合は0001、第21回目~第40回目は0021、第41回目~第60回目までは0041となっており値が20ずつ増えていきます。


第461回目以降のURLは以下のようになっています。(第461回目~第480回目の例)
https://www.mizuhobank.co.jp/retail/takarakuji/loto/backnumber/detail.html?fromto=461_480&type=loto6

これも先ほどと同様に赤字の部分が掲載されている当選番号の回数に伴い変化しています。
第461回目~第480回目の場合は461_480第481回目~第500回目の場合は481_500第501回目~第520回目の場合は501_520となっている。


当選番号の取得


全てのページで過去の当選番号はtableタグの中にあります。そのため最初に
table = soup.find_all("table")
と書いてtableタグないの全ての要素を取得します。取得したtableは以下のようになっています。(第501回目の例)
<table class="typeTK js-lottery-backnumber-temp-sp">
<tbody>
<tr>
<th class="bgf7f7f7 wdt33p">回</th>
<td>第501回</td>
</tr>
<tr>
<th class="bgf7f7f7 wdt33p">抽せん日</th>
<td>2010年6月17日</td>
</tr>
<tr>
<th class="bgf7f7f7 wdt33p">本数字</th>
<td>03 17 21 23 36 38</td>
</tr>
<tr>
<th class="bgf7f7f7 wdt33p">ボーナス数字</th>
<td class="green">07</td>
</tr>
</tbody>
</table>
3番目のtrタグ内のtdタグに当選番号が記載されている(赤字の部分)のでこの部分を抽出するコードは以下のようになります。
main_num = table[1].find_all("tr")[2].find("td")

またボーナス番号も取得したい場合、4番目のtrタグ内のtdタグにボーナス番号が記載されている(青字の部分)のでこの部分を抽出しましょう。



ソースコード


ロト6の当選番号を自動的に収集するコードを以下に載せておきます。
# -*- coding: utf-8 -*-
# ロト6の当選番号を自動的に収集する

import time
import random
import pandas as pd
from selenium import webdriver
from bs4 import BeautifulSoup

# ロト6の当選番号が掲載されているみずほ銀行ページのURL
loto_url1 = 'https://www.mizuhobank.co.jp/retail/takarakuji/loto/backnumber/loto6' # 1~460回目
loto_url2 = 'https://www.mizuhobank.co.jp/retail/takarakuji/loto/backnumber/detail.html?fromto=' # 461回目以降
num = 1

main_num_list = [] # 本数字6桁を格納するリスト
bonus_num_list = [] # ボーナス数字を格納するリスト

# PhantomJSをselenium経由で利用
driver = webdriver.PhantomJS()

while num <= 1241:
  
  # 第1~460回目までの当選ページのURL
  if num < 461:
    url = loto_url1 + str(num).zfill(4) + '.html'
  # 461回目以降当選ページのURL
  else:
    url = loto_url2 + str(num) + '_' + str(num+19) + '&type=loto6'
  
  # PhntomJSで該当ページを取得
  driver.get(url)
  time.sleep(2) # javascriptのページを読み込む時間
  html = driver.page_source
  
  soup = BeautifulSoup(html, "html.parser")
  print(soup.title)

  # ロト6の当選番号がのっているテーブルの取得
  table = soup.find_all("table")
  del table[0]

  for i in table:
    # 本数字の取得
    main_num = i.find_all("tr")[2].find("td")
    main_num_list.append(main_num.string.split(" "))

    # ボーナス数字の取得
    bonus_num = i.find_all("tr")[3].find("td")
    bonus_num_list.append(bonus_num.string)
    
  num += 20 # 次のページに移動するためにnumに20を追加
  time.sleep(random.uniform(1, 3)) # 1~3秒Dos攻撃にならないようにするためにコードを止める

# csvで出力
df = pd.DataFrame(main_num_list, columns = ['main1', 'main2', 'main3', 'main4', 'main5', 'main6'])
df['bonus'] = bonus_num_list
df.index = df.index + 1
df.to_csv('loto6.csv')



最後に


内容の中で何か分からないことがあればコメントで質問してください。答えられる範囲で答えます。

学習データを収集で来たので次の記事は機械学習を使って予測していきたいと思っています。深層学習を使うのならばRNNとか使うのがいいのかな。

SVRで予測する記事を書きました。
http://www.toshioblog.com/archives/16052074.html

Pythonのスクレイピングで分からないことがあれば以下の本が参考になると思うので読んでみてください。