(87) NPBプロ野球選手の年別成績を取得する。(ver.2)

投稿者: | 2017年8月4日

3,128 views

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

前回の (86) NPBプロ野球選手の年別成績を取得する。 では、一人の選手の紹介ページのURLを入力し、一人の選手の年別成績を出力するだけの機能だった。数百人ものプロ野球選手についてこれを手作業で繰り返すのは大変だ。

今回は、NPB様サイトのチームメンバー一覧ページのURLを入力し、そこから個々の選手紹介ページのURLを抽出し、個々の選手の年別成績を出力するように改良する。すなわち、チームを指定すれば所属メンバー全員分のデータが自動で出力されるようにする。

1. 仕様

・NPB様ホームページの1チームの選手一覧ページのURLを入力する。
・そのページから選手個々の紹介ページのURLを自動抽出する。
・選手個々の紹介ページから年別成績を自動抽出する。
・打者成績、投手成績に分けてCSVファイルを自動出力する。

2. プログラム

ちょっと力ずくなところもあるが後で改良しよう…

コマンドライン入力

以下の操作でホークスの全選手の年度別投手成績、年度別打者成績がファイル出力される。

$ mkdir ./da
$ mkdir ./pt
$ python3

>>> import lib_npb
>>> lib_npb.generate_record_file_for_1team("http://npb.jp/bis/teams/rst_h.html", "H")

他のチームのURLは以下の通り。

http://npb.jp/bis/teams/rst_c.html 広島
http://npb.jp/bis/teams/rst_g.html 巨人
http://npb.jp/bis/teams/rst_db.html 横浜
http://npb.jp/bis/teams/rst_t.html 阪神
http://npb.jp/bis/teams/rst_s.html ヤクルト
http://npb.jp/bis/teams/rst_d.html 中日

http://npb.jp/bis/teams/rst_h.html ソフトバンク
http://npb.jp/bis/teams/rst_f.html 日ハム
http://npb.jp/bis/teams/rst_m.html ロッテ
http://npb.jp/bis/teams/rst_l.html 西武
http://npb.jp/bis/teams/rst_e.html 楽天
http://npb.jp/bis/teams/rst_bs.html オリックス

lib_npb.py

import urllib.request
from bs4 import BeautifulSoup
import csv

#////////////////////////////////////////////////////////////////
class NpbPlayer:
    #------------------------------------------------------------
    def __init__(self, name, url):
        self.name = name
        self.url  = "http://npb.jp" + url
        self.ary_record_pitch = []    # 投手記録
        self.ary_record_bat = []      # 打者記録

    #------------------------------------------------------------
    # 1選手の投手記録をCSVファイルに出力
    def output_record_to_csv_file_pitch(self, fname):
        if len(self.ary_record_pitch) > 0 :
            with open(fname, "w") as fh:
                writer = csv.writer(fh, lineterminator="\n")
                writer.writerows(self.ary_record_pitch)

    #------------------------------------------------------------
    # 1選手の打者記録をCSVファイルに出力
    def output_record_to_csv_file_bat(self, fname):
        if len(self.ary_record_bat) > 0 :
            with open(fname, "w") as fh:
                writer = csv.writer(fh, lineterminator="\n")
                writer.writerows(self.ary_record_bat)

    #------------------------------------------------------------
    # 1選手の記録を収集
    def get_record(self):
        try:
            resp = urllib.request.urlopen(self.url)
        except urllib.error.HTTPError as e:
            print("HTTP-Error : ", e.code)
            return False
        except urllib.error.URLError as e:
            print("URL-Error : ", e.reason)
            return False
        else:
            self.ary_record_pitch = []
            self.ary_record_bat = []
            bs = BeautifulSoup(resp.read(), "html.parser")
            for div in bs.findAll("div",id="registermaintbl"):
                th = div.find(text="防")
                for tr in div.findAll("tr",class_="registerStats"):
                    ary_1_record = []
                    for td in tr.findAll("td"):
                        ary_1_record.append(td.get_text())
                    if th == None :
                        self.ary_record_bat.append(ary_1_record)
                    else:
                        self.ary_record_pitch.append(ary_1_record)
            return True

#////////////////////////////////////////////////////////////////
def get_player_list_detail( resp ):
    ary_cPlayer = []
    bs = BeautifulSoup(resp.read(), "html.parser")
    # find name
    for tr in bs.findAll("tr",{"class":"rosterPlayer"}):
        td = tr.find("td",{"class":"rosterRegister"})
        a = td.find("a")
        if a == None :
            continue
        url  = a.attrs["href"]
        name = a.get_text()
        cPlayer = NpbPlayer(name, url)
        ary_cPlayer.append(cPlayer)
    return ary_cPlayer

#////////////////////////////////////////////////////////////////
def get_player_list( team_url ):
    try:
        resp = urllib.request.urlopen(team_url)
    except urllib.error.HTTPError as e:
        print("HTTP-Error : ", e.code)
        return None
    except urllib.error.URLError as e:
        print("URL-Error : ", e.reason)
        return None
    else:
        ary_cPlayer = get_player_list_detail(resp)
        return ary_cPlayer

#////////////////////////////////////////////////////////////////
def generate_record_file_for_1team( team_url, prefix ):
    ary_cPlayer = get_player_list(team_url)
    for cPlayer in ary_cPlayer:
        if True == cPlayer.get_record():
            print("now generating %s" % cPlayer.name)
            cPlayer.output_record_to_csv_file_bat(  "./da/data_%s_%s_da.txt" % (prefix, cPlayer.name))
            cPlayer.output_record_to_csv_file_pitch("./pt/data_%s_%s_pt.txt" % (prefix, cPlayer.name))

3. 備忘録

python3では reload()が使えなくなった。
同じことを以下のように実現できる。

import importlib
importlib.reload(lib_npb)

シーズン中は日々成績が変化するので、ときどき以下を実行して最新情報を収集する。

import lib_npb
lib_npb.generate_record_file_for_1team("http://npb.jp/bis/teams/rst_c.html", "C")
lib_npb.generate_record_file_for_1team("http://npb.jp/bis/teams/rst_g.html", "G")
lib_npb.generate_record_file_for_1team("http://npb.jp/bis/teams/rst_db.html", "DN")
lib_npb.generate_record_file_for_1team("http://npb.jp/bis/teams/rst_t.html", "T")
lib_npb.generate_record_file_for_1team("http://npb.jp/bis/teams/rst_s.html", "Y")
lib_npb.generate_record_file_for_1team("http://npb.jp/bis/teams/rst_d.html", "D")
lib_npb.generate_record_file_for_1team("http://npb.jp/bis/teams/rst_h.html", "H")
lib_npb.generate_record_file_for_1team("http://npb.jp/bis/teams/rst_f.html", "F")
lib_npb.generate_record_file_for_1team("http://npb.jp/bis/teams/rst_m.html", "M")
lib_npb.generate_record_file_for_1team("http://npb.jp/bis/teams/rst_l.html", "L")
lib_npb.generate_record_file_for_1team("http://npb.jp/bis/teams/rst_e.html", "E")
lib_npb.generate_record_file_for_1team("http://npb.jp/bis/teams/rst_bs.html", "O")

コメントを残す

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