(81) 野球選手の成績を主成分分析 (続編1/2)

投稿者: | 2016年11月12日

4,585 views

この記事は最終更新から 1949日 が経過しています。

(80) 野球選手を測ってみる 2016年版 では、日本プロ野球2016年シーズンの打者結果を使って遊んだ。どうせやるのならば、もっと大きなデータで同じことをやってみたい、プロ野球の過去の結果も使って同じ解析をしてみたい、と思う。

しかし…
前回はYahooスポーツの表示情報を手動でコピペして入力用 CSVファイルを作成したが、この手作業を過去何年分もやると量が多すぎて途中で気持ちが切れちゃいそうだ。

そこで…
(75) 指定URLのWEBページのHTMLソースコードを表示
(79) なんちゃってGoogle検索
で使ったテクニックを利用して、過去データをプログラムに自動収集させてみたい。

過去データをスクレイピング

前述の(79)では、取得したHTMLの構文解析に HTMLParser モジュールを使用していた。
今回は楽をするために lxml モジュールを使う。C,C++での開発で libxmlを長いこと使っているが、これを使うと XPathでちょちょいと各タグにアクセスできるので便利だ。

まずは Pythonに lxmlをインストールしておく。

$ easy_install --user lxml
$ easy_install --user cssselect

1) データ収集&保存

NPB(日本野球機構)様のホームページでは、2005年~2016年の打者成績が掲載されているので、これをデータ解析の入力データとして使わせていただく。2005年~2016年の12年分×2リーグ分、全24ページのデータを使わせていただく。

index.cgi

#!/usr/local/bin/python
# -*- coding: utf-8 -*-

print 'Content-type: text/html'

import npbparser
import numpy as np

print """
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>0081</title>
</head>
<body>
"""

def collect_data(year, league_cp):
	url = "http://npb.jp/bis/%d/stats/bat_%s.html" % (year, league_cp)
	fname = "%d_%s.csv" % (year, league_cp)
	res = npbparser.get_npb_score(url);
	np.savetxt( fname, res, delimiter=',',fmt='%s')

for year in range(2005,2016):
	collect_data(year,'c')
	collect_data(year,'p')

print """
<form enctype="multipart/form-data" action="./" method=post>
<input type=submit value="実行">
</form>
</body>
</html>
"""

npbparser.py

#!~/usr/local/bin/python
# -*- coding: utf-8 -*-
import numpy as np
import urllib2
import lxml.html
import chardet

def get_npb_score(url):
    #------------------------------------------------
    # load html
    opener = urllib2.build_opener()
    opener.addheaders = [('User-agent', 'Mozilla/5.0')]
    res = opener.open(url)
    html = res.read()
    res.close()
    ccode = chardet.detect(html)          # 文字コードを判定
    html = html.decode(ccode['encoding']) # unicodeに変換

    #------------------------------------------------
    # parse HTML
    dom = lxml.html.fromstring(html)      # DOMツリー生成
    ary_tr = dom.xpath("//div[@id='stdivmaintbl']//table/tr")
    ary_1player = []
    for tr in ary_tr:
        if len(tr) &lt; 25:
            continue
        da_items = []
        for td in tr:
            da_items.append(td.text.encode("utf-8"))
        ary_1player.append(da_items)
    ary_np = np.array(ary_1player)
    return ary_np

2) 実行結果

過去12年分のCSVファイルデータができた。
※UTF-8なのでExcelで開くと文字化けするかも
2005年セ , 2005年パ
2006年セ , 2006年パ
2007年セ , 2007年パ
2008年セ , 2008年パ
2009年セ , 2009年パ
2010年セ , 2010年パ
2011年セ , 2011年パ
2012年セ , 2012年パ
2013年セ , 2013年パ
2014年セ , 2014年パ
2015年セ , 2015年パ
2016年セ , 2016年パ

次回 (82) 野球選手の成績を主成分分析 (続編2/2) では、このデータを使ってPCAしてみる。


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です