サッカーを通じて観戦力と分析力を上げていくブログ

基本的にはサッカー×データに関して試してみたことをまとめています。最近はもっぱらPythonを使った可視化中心。時々自分の好きなガジェットも。

【Python】Beautiful Soupを使ってJリーグ選手の情報をスクレイピングしてみる

データ分析をするにしても、肝心のデータが無ければ始まらないと言うことで、Webからデータを集める方法にも挑戦してみます。集めるといってもEXCEL等に一つ一つコピペしてては日が暮れてしまうので、Pythonスクレイピングと呼ばれる技術を実装してみたいと思います。具体的には、PythonのライブラリRequestsでHTMLを取得、そこからBeautiful Soupを使って特定の情報をスクレイピング、最後にPandasを使ってcsvファイルへの保存を試みます。

 

何がしたいのか/今回やってみること

今回やりたいのは、「Jリーグデータサイト」にある選手情報をデータとして綺麗な形で保存することです。身長・体重・生年月日を始め、Jリーグ通算出場試合数や通算ゴール数などもあり、分析に向けてこうしたデータは保存しておきたいと思ったことがきっかけです。単純に画面で選択してコピペでは綺麗にならない形で表示されているので、Webスクレイピングの技術を使って収集してみます。

data.j-league.or.jp

f:id:virgilvd:20181209170855p:plain

▲「Jリーグデータサイト」では、こんな感じで様々な情報をみることが出来ます。

今回はまずはファーストステップと言う事で、選手名のみに絞ってデータを収集してみます。先にも記載したように、PythonのライブラリRequestsでHTMLを取得、そこからBeautiful Soupを使って特定の情報をスクレイピング、最後にPandasを使ってcsvファイルへの保存という順番でやっていきます。

今回も使用する環境としては、「Google Colaboratory」でPython3系を使用します。

96lovefootball.hatenablog.com

 

RequestsでHTMLを取得

早速やっていきたいと思います。まずは対象ページのHTMLを取得します。Python標準ライブラリのurllibよりも、Requestsライブラリの方が分かりやすくて使いやすいという記事を何個か見たのでここではRequestsを使います。

まずはライブラリのインポートから。

import requests

requestsは、requests.get( )クラスに対象のurlを与える事でhtmlを取得できます。ここでは、先日Jリーグ連覇を果たした川崎フロンターレの選手情報ページを指定します。

url = "https://data.j-league.or.jp/SFIX02/search?displayId=SFIX02&selectValue=1&displayId=SFIX02&selectValueTeam=21&displayName=%EF%BC%AA%EF%BC%91%E3%83%AA%E3%83%BC%E3%82%B0&displayNameTeam=%E5%B7%9D%E5%B4%8E%E3%83%95%E3%83%AD%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%AC"
html = requests.get(url)

取得したhtmlの内容は、.contentを使って取得することが出来ます。

f:id:virgilvd:20181209180445p:plain

これでスクレイピングを行う準備ができました。

 

Beautiful Soupを使って選手名をスクレイピング

Beautiful Soupというライブラリで取得したhtmlを、html(マークアップされた文章)として正しく解釈することで情報の扱いを容易に(といっても難しいですが)してくれます。

こちらもライブラリ(モジュール)のインポートから。

from bs4 import BeautifulSoup

先ほど取得したhtmlを、Beautiful Soupでhtmlとして扱えるようにします。"html.parser"(htmlパーサー)の部分がhtmlとして扱うために必要な部分だと理解しています。

soup = BeautifulSoup(html.content, "html.parser")

.prettify( )を使うと取得したhtmlの中身を整形された状態で表示してくれるので、諸々確認する際に役に立ちます。

print(soup.prettify)

f:id:virgilvd:20181209182058p:plain

ここで今回取得したい値がhtml上でどのように記述されているのか確認しておきます。htmlを確認する方法は、前述の.prettify( )を始めいくつかあると思いますが、ブラウザのデベロッパーツールを使って行います。

Chromeで対象のページを表示し、右クリックから検証。

f:id:virgilvd:20181209194041p:plain

デベロッパーツールの画面左上の矢印マークを選択。

f:id:virgilvd:20181209194055p:plain

取得したい値(今回は選手名)までカーソルを持ってきてクリック。

f:id:virgilvd:20181209194133p:plain

するとデベロッパーツール側でその部分のhtmlが表示されます。

f:id:virgilvd:20181209194212p:plain

これで選手名がクラス"box-info register-list"のdivタグ内、クラス"name"のpタグ内、クラス"s-txt"のspanタグの中にあることが分かりました。

いよいよここからスクレイピングをしていきます。.find_all( )でタグ名を指定すると、htmlに含まれるそのタグを全て取得することが出来ます。同時にクラスも指定できるので、今回選手名を取得するためには「クラス"s-txt"のspanタグ」で指定すれば良さそうですが、「クラス"s-txt"のspanタグ」で囲まれた情報の中には選手名のローマ字表記や(2種)といったものも混ざっています。そこで「クラス"name"のpタグ」を取得してから、各「クラス"name"のpタグ」内最初の「クラス"s-txt"のspanタグ」を抽出する方法でスクレイピングします。

ps = soup.find_all("p", class_="name")

 これで全ての「クラス"name"のpタグ」がリスト形式で取得されているはずです。確認してみると、

f:id:virgilvd:20181209201008p:plain

分かりづらいですが、確かにpタグ単位でリストとして取得できています。次にここから最初の「クラス"s-txt"のspanタグ」を取得し、新たなリストに格納します。タグで囲まれた文字列だけを取得したい場合は、.stringで取得可能です。今回はname_listというリストを作って、そこに入れていきます。

name_list=[]
for p in ps:
 name_list.append(p.span.string)
print(name_list)

f:id:virgilvd:20181209201455p:plain

全角スペースは上手く扱えないらしく、エスケープ文字になってしまっているので、今度は半角スペースに置換しつつリストを作ります。

name_list=[]
for p in ps:
 name_list.append(p.span.string)
 list_replace = [s.replace('\u3000', ' ') for s in name_list]
print(list_replace)

f:id:virgilvd:20181209202546p:plain

これで無事スクレイピングは完了です。

 

Pandasを使ってcsvファイルへ保存する

最後に取得したデータをcsvで保存したいと思います。「Google Colaboratory」を使っているので、Googleドライブへ保存してみます。マウントする方法は下の記事を参照頂ければと思います。

96lovefootball.hatenablog.com

リストのデータをcsvとして保存する方法として、標準ライブラリcsvを使う方法もあるのですが、その方法だと行方向への保存しか分かりませんでした。なので今回はPandasを使って保存したいと思います。その方法は至って簡単で、.to_csvでデータと保存場所を指定してあげれば終了です。

まずは、リスト形式のデータをPandasの形式であるSeriesへと変換します。

import pandas as pd

names_kawasaki = pd.Series(list_replace)

f:id:virgilvd:20181209204459p:plain

インデックスのついたSeries型へ変換できました。後は.to_csvで保存するだけです。元ファイルは無くても自動で生成されるので、予め作っておく必要はありません。

names_kawasaki.to_csv('/content/gdrive/My Drive/Colab Notebooks/data/JPlayers.csv')

無事保存することが出来ました。

f:id:virgilvd:20181209204830p:plain

 さて今回はスクレイピングの触りの部分をやってみました。今後の発展形としては、当初の目的である選手情報(選手名以外)をスクレイピングしたり、他チームも合わせてスクレイピングするためにクローリングすることなどが考えられます。また、応用編としてJavaScriptで描画されているような動的なページの情報も取得できたら幅が広がりそうな感じがします。データ分析と並行して、こういったデータを収集するスキルも身につけて行きたいと思います。

戦術や分析に関して、こういう見方もあるよ、こうして見た方がいいよ、などご意見等ありましたら、コメントで教えていただけると幸いです。ぜひよろしくお願いいたします!