背景・目的
- 趣味の格闘ゲーム(ストリートファイターV)の戦績の推移を確認したい
- 公式戦績サイトでは今現在のポイントと直近に戦った対戦相手のデータしか確認できなくて困ってる
利用するもの
- Google Apps Script(GAS)
- スプレッドシート
- 対戦ゲームの公式戦績サイト
- 対戦ゲームのアカウント
それぞれの詳細は以下の通り。
Google Apps Script(GAS)
Google Apps Script(通称GAS)とは、Googleが提供しているスクリプト言語のこと。
Googleのサービスと連携したり、タスクの自動化などができることが特徴。
スプレッドシート
言わずと知れたGoogleが提供しているウェブベースの表計算ソフト。
対戦ゲームの公式戦績サイト
ストリートファイターVの戦績を確認できるWebサイト「シャドルー格闘家研究所」。
戦績を確認するには、ゲームに紐づいたPSNアカウントかSteamアカウントでのログインが必要。
今回はこのサイトからスクレイピングを行います。
対戦ゲームのアカウント
ゲームに紐づいたPSNアカウントかSteamアカウント。
作成する仕組みの全体図
①ユーザが手動で公式戦績サイトにアクセス
②公式戦績サイトからログイン時に発行されたCookieをメモ
③メモしたCookieをプログラムに入力して、プログラムから公式戦績サイトにアクセス
④公式戦績サイトからログイン時に発行されたCookieと戦績データを取得(Cookieは次回ログインに利用)
⑤スプレッドシートに戦績データとCookieを記録
⑥スプレッドシートで戦績データからグラフを作成
③~⑥を一定時間ごとに繰り返してスプレッドシート上の戦績データを更新する
実装
それでは、上記の仕組みを実際に実装する流れを見ていきます。
スプレッドシートの作成
まずは、戦績データとCookieを記録するためのスプレッドシートを作成します。
-
同様の手順で「Cookieシート」などの名前を付けて保存する
-
シートの作成は以上でとりあえず完了
GASの作成
次に公式戦績サイトからスクレイピングする処理を担当するGASを作成します
1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw
このライブラリはGoogleが公開している公式のParserライブラリです。
これを利用することでHTML形式のテキストデータから容易に任意の情報を抽出することができます。
5. 「検索」>「追加」を選択してスクレイピング処理用のライブラリである「Parser」が追加されていることを確認
6. 以下のスクリプトを書き込む
function main() {
//ログイン処理
const login_url = 'https://game.capcom.com/cfn/sfv/profile/XXXXXX';
//CookieシートからCookie取得
const cookie_sheet = SpreadsheetApp.openById('XXXXXXXXXXXX');
const cookie_sheet_obj = cookie_sheet.getSheetByName('シート1');
const cookies = cookie_sheet_obj.getRange('A1').getValue();
const headers = {Cookie:cookies};
const get_options = {
method:"get",
headers:headers,
followRedirects:true
};
//データ取得
const response = UrlFetchApp.fetch(login_url,get_options);
const content = response.getContentText('UTF-8');
//Logger.log(content);
//データ抽出
let LP_text = Parser.data(content).from('<dt>League Points</dt>').to('</dd>').build();
LP_text = Parser.data(LP_text).from('<dd>').to('<span>').build();
Logger.log(LP_text);
let recent_opp = Parser.data(content).from('<dl class="fId">').to('<div class="fighter">').build();
let recent_opp_LP = Parser.data(recent_opp).from('<dt>League Points</dt>').to('/dd>').build();
recent_opp_LP = Parser.data(recent_opp_LP).from('<dd>').to('<').build();
let recent_opp_char = Parser.data(recent_opp).from('<dt>Fought Character</dt>').to('/dd>').build();
recent_opp_char = Parser.data(recent_opp_char).from('<dd>').to('<').build();
let recent_opp_id = Parser.data(recent_opp).from('ID</dt>').to('/dd>').build();
recent_opp_id = Parser.data(recent_opp_id).from('<dd>').to('<').build();
//今日の日付を取得
date = Utilities.formatDate(new Date(),'JST','yyyy/MM/dd HH:mm:ss');
//headerからcookieを取得
let all_cookies = response.getAllHeaders()['Set-Cookie'];
let next_scirid = Parser.data(all_cookies.filter(matchScirid)[0]).from("scirid=").to(';').build();
let next_fuel_csrf_token = Parser.data(all_cookies.filter(matchFuelCsrfToken)[0]).from("fuel_csrf_token=").to(';').build();
Logger.log(all_cookies)
Logger.log(next_scirid)
Logger.log(next_fuel_csrf_token)
//LPシート書込み
const battle_record_sheet = SpreadsheetApp.openById('XXXXXXXXXXXXX');
const battle_record_sheet_obj = battle_record_sheet.getSheetByName('シート1');
const battle_record_sheet_lastrow = battle_record_sheet_obj.getLastRow();
const battle_record_sheet_targetrow = battle_record_sheet_lastrow + 1;
const old_LP = battle_record_sheet_obj.getRange('A' + battle_record_sheet_lastrow).getValue();
Logger.log(battle_record_sheet_obj.getRange('B' + battle_record_sheet_lastrow).getValue())
Logger.log(recent_opp_id)
if(battle_record_sheet_obj.getRange('B' + battle_record_sheet_lastrow).getValue() != recent_opp_id){
battle_record_sheet_obj.getRange('A' + battle_record_sheet_targetrow).setValue(LP_text);
battle_record_sheet_obj.getRange('B' + battle_record_sheet_targetrow).setValue(recent_opp_id);
battle_record_sheet_obj.getRange('C' + battle_record_sheet_targetrow).setValue(recent_opp_char);
battle_record_sheet_obj.getRange('D' + battle_record_sheet_targetrow).setValue(recent_opp_LP);
battle_record_sheet_obj.getRange('E' + battle_record_sheet_targetrow).setValue(LP_text - old_LP);
battle_record_sheet_obj.getRange('F' + battle_record_sheet_targetrow).setValue(date);
}
//Cookieシート書込み
cookie_sheet_obj.getRange('A1').setValue('scirid=' + next_scirid + '; fuel_csrf_token=' + next_fuel_csrf_token + ';')
}
function matchScirid(value) {
return value.match('scirid');
}
function matchFuelCsrfToken(value) {
return value.match('fuel_csrf_token');
}
9. どの程度の頻度でスクレイピング処理を実行するかを選択する
(今回は「分ベースのタイマー」、「5分おき」を選択)
スクレイピング頻度が高すぎると対象サイトに大きな負荷を与えてしまう可能性があります。
スクレイピング頻度を高すぎる値に設定しないように注意してください。
10. 完成!
動作確認
では実際に動作確認してみます。
初期値設定
今回作成したスクレイピング処理を実行するには、Cookieと初期戦績データが必要なので設定していきます。
Cookie設定
scirid=XXXXX;fuel_csrf_token=XXXXX;
テスト
参考資料
商標
Google Apps Script、Google スプレッドシートはGoogle LLC の商標です。
ストリートファイターは株式会社カプコンの商標です。
記載の会社名、製品名、サービス名等はそれぞれの会社の商標または登録商標です。