Webスクレイピングは便利な技術です。

あるサイトのデータを見たいが、データベースにアクセスできない、あるいはAPIが用意されていない.....。

こういう場合にページからデータを抜き出す場合に使います。

特に過去データなどを参照する場合、必要なデータのみ見たい時役立ちます。

また、これでデータベースを独自に作っておけば、後々便利。

スクレイピングのコードは結構ややこしいですが、慣れればOKです。

いろいろな言語が使えますが、ここではPHPを使って具体的にやってみましょう。

J.リーグの公式記録は、以下のページで参照できます。

https://data.j-league.or.jp/

利用規約を見る限りでは、こういう使い方に問題はないと....思います。

規約についてはここを参照。
http://www.j-league.or.jp/general/kiyaku.html
(リンクしたら一報入れてね、なんて書いてますがどこに入れたらいいのか書いてないってどうよ)

ちなみに、https://data.j-league.or.jp/で参照できるのは、試合終了結果です。

速報の場合は以下を参照。

http://www.j-league.or.jp/live/
(1分ごとにアップデートされます)



公式記録のページでは、対戦別の個々の結果などはダイレクトに参照できません。

例えば、2010年のJ1リーグの結果は以下のURLで参照できますが、個々のページはID番号で管理されているので、1個づつクリックしないと出てきません。

https://data.j-league.or.jp/SFMS01/search?competition_years=2010&competition_frame_ids=1&tv_relay_station_name=

そこで、こういうページから参照用のIDを抽出して、データにアクセスできるようにしてみましょう。

例えば、2010年第2節C大阪vsG大阪のIDは、12560です。

ページのURLは、

https://data.j-league.or.jp/SFMS02/?match_card_id=12560

となります。

ちなみに、公式サイトは1992年からになっていますが、J.リーグは1993年からなので、1992年のデータはナビスコカップのもののみです。

J.リーグチームの対戦は、このカップ戦から始まり、初の優勝チームは読売クラブ(現・東京ヴェルディ)でした。

余談ですが、ガンバ大阪は8位でした。



ページの下段にサンプルを置いておきました。

年度別のスコア一覧と、個別のデータへのアクセスURLを表示します。






年度別のゲーム結果を表示するIDを取得

年度別・ゲーム別にスターティング・リザーブを表示

日本語・英語のページ切り替え

Webスクレイピングとプッシュ通知を組み合わせてみる


ログイン処理が必要な場合
curlを使用してログイン処理を行い、ログイン後のページを表示する






参照用のIDを抽出してみましょう。

以下のページにアクセスしてソースを覗いてみます。

https://data.j-league.or.jp/SFMS01/search?competition_years=2010&competition_frame_ids=1&tv_relay_station_name=

このページのデータはtableを使って表示されています。

例えば、こんな感じ。

<table class="table-base00 search-table">
    ・・・・・・・
    ・・・・・・・
    ・・・・・・・
    <tr>
    <td class="bl-non nowrap">2010</td>
    <td class="nowrap">J1 </td>
    <td class="nowrap">第1節第1日</td>
    <td class="nowrap">03/06(土)</td>
            <td class="nowrap">
        13:03</td>
    <td class="nowrap">
        <a href="http://www.j-league.or.jp/club/iwata/">磐田</a>
            </td>
    <td class="al-c nowrap">
        <a href="/SFMS02/?match_card_id=12545">0-1</a>
                    </td>
    <td class="nowrap">
        <a href="http://www.j-league.or.jp/club/sendai/">仙台</a>
            </td>
    <td class="nowrap">
        <a href="http://www.j-league.or.jp/stadium/shizuoka_03/">ヤマハ</a>
            </td>
    <td class="al-r nowrap">
        10,440</td>
    <td>スカパー(スカチャンHD、スカチャン)/e2スカチャンHD/静岡放送</td>
    </tr>
    ・・・・・・・
    ・・・・・・・
    ・・・・・・・


td要素のデータを抽出するPHPコードを作ってみます。

PHPの場合、Simple HTML DOM Parserというライブラリを使います。

sourceforge からダウンロードして読み込みます。

require_once("simple_html_dom.php");

ページからソースを取ってきます。
$url = "https://data.j-league.or.jp/SFMS01/search?competition_years=2010&competition_frame_ids=1&tv_relay_station_name=";
    
$html = file_get_html($url);




取得したhtmlソースを使って、class属性を持つtable要素の中からtd要素を抽出するphpコードです。

上記の場合、tableのクラス属性は、table-base00 search-tableとなっていますが、使用するのはメインのtable-base00です。

td要素のクラスは複数あります。nowrpaとal-c nowrap。al-c nowrapもal-cのみを使います。

データを抽出するコードは以下のようになります。

foreach ($html->find('table.table-base00 td.nowrap,td.al-c') as $entry) {
        //要素からタグを外してテキストのみ取得
        $data = $entry->plaintext;
        //a要素を取得、IDはここに含まれています
        $refid = $entry->find("a", 0)->href;
}


データを取得してみましょう。以下のようにして吐き出してみます。

echo $data . "/" . $refid ;

こんなデータが10個1セットで取得できます。

2010/
J1 /
第1節第1日/
03/06(土)/
13:03/
磐田 /http://www.j-league.or.jp/club/iwata/
0-1 //SFMS02/?match_card_id=12545
仙台 /http://www.j-league.or.jp/club/sendai/
ヤマハ /http://www.j-league.or.jp/stadium/shizuoka_03/
10,440/



必要なデータを配列に入れてみます。PHPのコード。

$year = array();
$gamedate = array();
$hometeam = array();
$score = array();
$uriid = array();
$awayteam = array();
$index = 0;
$counter = 0;

foreach ($html->find('table.' . 'table-base00' . ' td.nowrap,td.al-c') as $entry) {
    
    $data = $entry->plaintext;
    $refid = $entry->find("a", 0)->href;
    
    if ($counter == 0){
        $year[$index] = $data;
    }else if ($counter == 3){
        $gamedate[$index] = $data;
    }else if ($counter == 5){
        $hometeam[$index] = $data;
    }else if ($counter == 6){
        $score[$index] = $data;
        $uriid[$index] = $refid;
        
    }else if ($counter == 7){
        $awayteam[$index] = $data;
    }
    
    $counter++;
    
    if($counter == 10){
        $counter = 0;
        $index++;
    }
}


for ($i = 0;$i < $index;$i++){
    $data_set = "";
    $data_set .= $year[$i] . "/" . $gamedate[$i] . " " . $hometeam[$i] . "vs" . $awayteam[$i] ;
    $data_set .= "(" . $score[$i] . ")" . "->" . "https://data.j-league.or.jp" . $uriid[$i] . "<br>";
    
    
    echo $data_set;
    
    
}


結果は以下のようなものになります。

2010/03/06(土) 磐田 vs 仙台 ( 0-1 )->https://data.j-league.or.jp/SFMS02/?match_card_id=12545
2010/03/06(土) 湘南 vs 山形 ( 1-1 )->https://data.j-league.or.jp/SFMS02/?match_card_id=12544
2010/03/06(土) F東京 vs 横浜FM ( 1-0 )->https://data.j-league.or.jp/SFMS02/?match_card_id=12546
2010/03/06(土) 広島 vs 清水 ( 1-1 )->https://data.j-league.or.jp/SFMS02/?match_card_id=12547
2010/03/06(土) 川崎F vs 新潟 ( 2-1 )->https://data.j-league.or.jp/SFMS02/?match_card_id=12549
2010/03/06(土) 鹿島 vs 浦和 ( 2-0 )->https://data.j-league.or.jp/SFMS02/?match_card_id=12548
2010/03/06(土) G大阪 vs 名古屋 ( 1-2 )->https://data.j-league.or.jp/SFMS02/?match_card_id=12550
     ・
     ・
     ・
     ・



フルコードはこんな感じです。

<?php
    require_once("simple_html_dom.php");
    
    $url = "https://data.j-league.or.jp/SFMS01/search?competition_years=2010&competition_frame_ids=1&tv_relay_station_name=";
    
    $html = file_get_html($url);
    
    $year = array();
    $gamedate = array();
    $hometeam = array();
    $score = array();
    $uriid = array();
    $awayteam = array();
    $index = 0;
    $counter = 0;
    
    foreach ($html->find('table.' . 'table-base00' . ' td.nowrap,td.al-c') as $entry) {
        
        
        $data = $entry->plaintext;
        $refid = $entry->find("a", 0)->href;
        
        if ($counter == 0){
            $year[$index] = $data;
        }else if ($counter == 3){
            $gamedate[$index] = $data;
        }else if ($counter == 5){
            $hometeam[$index] = $data;
        }else if ($counter == 6){
            $score[$index] = $data;
            $uriid[$index] = $refid;
            
        }else if ($counter == 7){
            $awayteam[$index] = $data;
        }
        
        $counter++;
        
        if($counter == 10){
            $counter = 0;
            $index++;
        }
    }
    
    
    for ($i = 0;$i < $index;$i++){
        $data_set = "";
        $data_set .= $year[$i] . "/" . $gamedate[$i] . " " . $hometeam[$i] . "vs" . $awayteam[$i] ;
        $data_set .= "(" . $score[$i] . ")" . "->" . "https://data.j-league.or.jp" . $uriid[$i] . "<br>";
        
        
        echo $data_set;
        
        
    }
    
    $html.clear();
?>


やってみて分かったこと。

1992年のJ.リーグ・プレ大会のナビスコカップ第一戦、鹿島アントラーズVS横浜フリューゲルスから数えて、

Jのチームが関わった試合(天皇杯など日本サッカー協会等が主催のゲームは除く)の総数は、

2014年4月29日のセレッソ大阪vs大宮アルディージャまで、通算12015試合も行われたようだ....ということ。

総入場者数は142,164,860人。(まあ、どっかのクラブが水増し報告してたこともあったようだから、額面どうりには受け取れないけど)






サンプル1

下のフィールドに年度を入れて、ボタンをクリックしてみてください。

上記のコードを若干変更して、より多くのデータを表示してみました。

1992の場合はナビスコカップの結果、それ以外はJ1リーグの結果を表示します。

また、1995も興味深い結果が出ます。

特殊なレギュレーションだったため、14クラブしかなかったのにこの試合数といい勝敗の決め方といい(延長Vゴール方式、PKあり)、かなり過酷。

これに現在のようにACL参戦チームがあったとしたら、多分選手の何人かは死んでるだろうなあ。

年度(半角数字)








サンプル2

年度を指定して、対戦するチーム名を選択するとスターティングとリザーブを表示する

....というページを作ってみました。

データはDB化してみました。

以下のページからどうぞ。



J.リーグ(Division1) 年度・対戦別 スターティング・メンバー&リザーブ・メンバー






おまけ

J.リーグ公式記録のページは上部に日本語・英語の切り替え用ボタンがあります。

あるのですが、見せてもらってて文句を言うのもなんなんですが......これが結構不便。

日本語から英語に切り替えるのにEnglishのボタンをクリックすると、英語のトップページに移動してしまう。

また一から探さにゃならん。

多分、トップでlanguageを指定すれば、あとはページを移動しても言語が維持されるという仕様だと思うのですが...。

で、一発で切り替える方法をやってみます。

上記で、個別ゲームを表示するURLを取得しています。

こんな感じ。

2005年12月3日 第34節 川崎フロンターレVSガンバ大阪戦のURLは

https://data.j-league.or.jp/SFMS02/?match_card_id=8712

これは、日本語・英語共通です。

で、これを英語版で表示するように変更してみます。

https://data.j-league.or.jp/SFMS02/?lang=en&match_card_id=8712

日本語版は

https://data.j-league.or.jp/SFMS02/?lang=ja&match_card_id=8712

これで、トップページに飛ぶことなく表示が切り替わります。

簡単なサンプルページはこちら。

1992年の公式記録です。

1993年の公式記録です。

1994年の公式記録です。

1995年の公式記録です。

1996年の公式記録です。

1997年の公式記録です。

1998年の公式記録です。

1999年の公式記録です。

2000年の公式記録です。

2001年の公式記録です。

2002年の公式記録です。

2003年の公式記録です。

2004年の公式記録です。

2005年の公式記録です。

2006年の公式記録です。

2007年の公式記録です。

2008年の公式記録です。

2009年の公式記録です。

2010年の公式記録です。

2011年の公式記録です。

2012年の公式記録です。

2013年の公式記録です。






テキストデータ(1993-2013)

Excelで読み込む場合、デリミタはコンマ、スコアの列は「文字列」として読んでください。