【GAS】スクレイピングでブログ村のポイントを自動で記録

GASでウェブスクレイピング 生産性アップ

Google Apps Scriptを利用したウェブスクレイピングによって、にほんブログ村のポイントを記録するツールを作成しました。
スクレイピングは簡単、便利、汎用性が高いと3拍子揃ったヤクルトの山田哲人のような存在です。

わからない、わかりにくい、うまくいかない等ありましたらコメントください。

ビフォーアフター

今回は効果の面では地味です。

にほんブログ村には7日分のデータしか記録されないので適当なタイミングで手で記録していた
(忘れるのが怖いので毎日記録していた)

前日のにほんブログ村のポイントの結果が自動的に記録される

必要なもの

  1. Googleアカウント

以下の理由でGASを採用しました。
・PCの常時稼働が不要( Googleのサーバーで実行されるため)
・定期実行の設定が簡単

作成する前にウェブスクレイピング利用の注意点

ウェブスクレイピングとは、 「プログラムによってウェブサイトから任意の情報を取得する技術 」です。
作成するのは容易なのですが使用法を間違うと違法行為になる可能性すらある行為になりますので、十分注意が必要です。

下記の記事で大変分かりやすくまとめられているのでぜひ読んでみてください。

スクレイピングは違法?3つの法律問題と対応策を弁護士が5分で解説 | TOPCOURT LAW FIRM
...

今回にほんブログ村の掲載情報をスクレイピングするにあたってチェックポイントを確認したところ、すべてクリアできていました。さらにアクセス回数も1日1回ですので、健全です。

①利用目的
  情報解析のためのポイント数取得です。

②スクレイピングの対象
  各種ポイント(INポイント、OUTポイント、PVポイント)なので一部です。

③アクセス制限の遵守
  にほんブログ村のrobots.txtを確認してみたところ以下の2行の記載がありました。
  翻訳すると「アメリカのComscoreのクローラだけはアクセスしてくれるな」でした。
  ——
  User-agent: proxemic
  Disallow: /
  ——

④利用規約
  にほんブログ村の利用規約にはスクレイピングについての記載はありませんでした。

作成手順

  1. スプレッドシート スプレッドシートを作成し、スクリプトエディタを開く
  2. GAS スクリプト作成

[仕様]
・1日に1回、にほんブログ村の前日分のINポイント、OUTポイント、PVポイントを取得
・取得したポイント数をスプレッドシートに記録

・スクレイピング対象URLを変更すれば気になる村人のポイントも記録できます

[パラメータ]
・スプレッドシート名
・スクレイピング対象URL

[スクリプト]

function getPoints() {
  //ブログ村のURLを指定
  //※手間を減らすためマイページではなくログイン不要でポイントが確認できるページを指定
  const url = "https://blogmura.com/profiles/11011449/";

  //シート名を指定し、2行目を追加
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('History');
  sheet.insertRows(2);
  
  //前日の日付を入力
  const datetime = new Date();
  datetime.setDate(datetime.getDate() - 1);
  sheet.getRange('A2').setValue(Utilities.formatDate(datetime,'JST','yyyy/M/d'));
  
  // APIを用いて指定したURLにアクセスし、とりあえず全部取ってくる
  const res = UrlFetchApp.fetch(url);

  // 受け取った情報をUTF-8のテキストとして加工
  const html = res.getContentText('UTF-8');

  //INポイント取得
  var start = html.indexOf('<th>INポイント</th>');
  start = html.indexOf('</td>', start);//start以降の</td>の開始位置を取得
  start = html.indexOf('<td>', start)+('<td>').length;//前日の<td>の開始位置を取得
  var end = html.indexOf('<', start)//終了タグの開始位置を取得

  //INポイント入力
  sheet.getRange('B2').setValue(html.substring(start, end));


  //OUTポイント取得
  start = html.indexOf('<th>OUTポイント</th>', start);
  start = html.indexOf('</td>', start);
  start = html.indexOf('<td>', start)+('<td>').length;
  end = html.indexOf('<', start)

  //OUTポイント入力
  sheet.getRange('C2').setValue(html.substring(start, end));


  //PVポイント取得
  start = html.indexOf('<th>PVポイント</th>', start);
  start = html.indexOf('</td>', start);
  start = html.indexOf('<td>', start)+('<td>').length;
  end = html.indexOf('<', start)

  //PVポイント入力
  sheet.getRange('D2').setValue(html.substring(start, end));

}

補足説明:
スクレイピングにおいてはhtmlソース内の欲しい情報までたどり着くかが肝になります。

  //INポイント取得
  var start = html.indexOf('<th>INポイント</th>');
  start = html.indexOf('</td>', start);//start以降の</td>の開始位置を取得
  start = html.indexOf('<td>', start)+('<td>').length;//前日の<td>の開始位置を取得
  var end = html.indexOf('<', start)//終了タグの開始位置を取得

indexOfで探している文字列の開始位置が取得できるので上記の場合は、

<th>INポイント</th>の開始位置を取得

②①以降の</td>の開始位置を取得

③②以降の<td>の開始位置を取得

という流れで目的のINポイント数の開始位置にたどり着いています。

indexOfは検索文字列の開始位置を取得します。③は最後の仕上げの部分なのでポイント数の開始位置とするため、検索文字列分の数値の加算が入っています。

どうやって上記のたどり着き方を見つけるかは、htmlソースを見て当たりをつけて、スクリプトを変更しながら試行錯誤となります。

ここではindexOfで抜き出す部分の開始位置、終了位置を見つける方法を採用していますが、正規表現を利用して抜き出す方法もあります。

スプレッドシートの関数であるImportXMLを利用してスクリプトを書かずにスクレイピングをする技もあります。

  1. GAS トリガーをセット

今回は実行時間について厳密な指定は必要ないのでスクリプト内にトリガー作成の記述はいれませんでした。毎日1回実行するトリガーを作成してください。

  1. GAS スクリプトを実行
    getPointsを実行し、データが取得できれば完成です。
    見出しは適当につけてください。
スクリプト実行結果
スクリプト実行結果

参考サイト

・ 【GAS】初めてのスクレイピング 〜会社の株価を取得〜
https://qiita.com/Cesaroshun/items/cec8b307cab6605ad8bc

あとがき

スクレイピングはVBAで経験済みでしたので、同じ要領でGASでも開発できました。
前日の日付を取得するdatetime.setDate(datetime.getDate() - 1);の部分で唯一プチはまりが発生しました。

コメント

タイトルとURLをコピーしました