【GAS】Cheerioライブラリを使ってWebスクレイピング

GASでスクレイピングについては結構前に一度記事にしてましたが、調べてみるとCheerioライブラリを使う手法がヒットし、これの方が使いやすそうだなと思いました。

今回はCheerioライブラリを使って、Google スプレッドシートにWebサイトの情報を取得するスクリプトを作成します。

プログラムの内容

https://ymsn.iehohs.com/

サンプルに使うのはこちらの僕が作ったサイトです。

トップページに記事の一覧が並んでいます。1番下の記事が見えませんが合計6記事あります。

記事タイトル部分には.entry-listのh3タグが使用されており、各記事へのリンクが貼られています。

各記事ページの最下部にはコメント欄があります。ここに新規コメントが投稿されたかどうかをチェックするプログラムです。

Google スプレッドシートに各記事のタイトル、URL、コメント数が書かれています。

このコメント数が変化したらば新規コメントが投稿されたとみなします。コメントを削除した場合にも同様の反応をしちゃいますが、今回はそこまで細かいことは気にしない。

新規コメントがあった場合のみ、指定のメールアドレス宛に通知します。

Cheerioライブラリの準備

事前にCherriorのライブラリを追加する必要があります。スクリプトエディタから追加できます。

CherrioライブラリのスクリプトIDは下記です。バージョンは最新のものを選びます。

1ReeQ6WO8kKNxoaA_O0XEQ589cIrRvEBA9qcWpNqdOP17i47u6N9M5Xh0

GAS

// スプレッドシートのIDとシート名を指定
const spreadsheet = SpreadsheetApp.openById("********")   // スプレッドシートのURLの projects/********/edit を入力
const sheet = spreadsheet.getSheetByName('シート1')

//最後の行に追記する設定
var lastrow = sheet.getLastRow();
var targetrow = lastrow + 1;
var flg;

function cherrioScraping(){
  //取得先のURLを指定
  var content = UrlFetchApp.fetch("https://ymsn.iehohs.com/").getContentText();
  var $ = Cheerio.load(content); //コンテントの読み込み  
  var $entrylist = $('.entry-list h4');

  $entrylist.each(function(index, element) {
    // 各記事のurl
    var posturl = $(element).html().match(/<a href=".*?">/g).toString();
    posturl = posturl.replace('<a href="', '').replace('">', '');

    // 各記事のタイトル
    var entrytitle = $(element).text()

    flg = true;   // 既にスプレッドシートにある場合はfalseにする
    for (var i=1;i<targetrow;i++){
      if (sheet.getRange("B" + i).getValue() == posturl){
        flg = false;
        break;
      }
    }

    // スプレッドシートになければ最終行に追加
    if (flg == true){
      sheet.getRange("A" + targetrow).setValue(entrytitle);
      sheet.getRange("B" + targetrow).setValue(posturl);
      sheet.getRange("C" + targetrow).setValue(0);
      lastrow++;
      targetrow++;
    }
  });

  // 各記事のコメントを取得
  eachpage();
}

function eachpage(){
  flg = false;    // 新しいコメントがあればtrueにする
  var notifyurl = "";   // メールに記載するurl
  var options = {
    "muteHttpExceptions": true,     // 404エラーでも処理を継続する
  }
  for (var i=1;i<targetrow;i++){
    var eachurl = sheet.getRange("B" + i).getValue();
    var content = UrlFetchApp.fetch(eachurl,options).getContentText();
    var $ = Cheerio.load(content); //コンテントの読み込み  

    // コメント数を取得
    var cnt = 0;
    var $comment = $('.comment-body');
    $comment.each(function(index, element){
      cnt++;
    });

    // 前回取得時との比較
    if (sheet.getRange("C" + i).getValue() != cnt){
      flg = true;
      sheet.getRange("C" + i).setValue(cnt);
      notifyurl = notifyurl + eachurl + "\n";   // メールに記載するurl
    }

    // 5秒待機
    Utilities.sleep(5000);
  }

  // 新しいコメントがあればメールを送信
  if (flg == true){
    sendMail(notifyurl);
  }
}

function sendMail(url){
  var email = 'sample@example.com';
  //本文
  var body    = "新しいコメントが投稿されたのは以下の記事です。\n\n" + url;
  //送信者の名前
  var sender  = "コメント通知システム";
  //メールの件名
  var subject = "新しいコメントが投稿されました";

  //メールの送信処理
  GmailApp.sendEmail(email, subject, body,
  {
    name : sender
  });
}

【Google Apps Script】GASでwebスクレイピングを簡単にする方法「Cheerio編」

こちらの記事を主な参考にして作りました。

メンテナンスする時はそれぞれ個別に動かせる方が良いので3つに分けてますが1つにまとめても問題ありません。

404エラーの時の処理

各記事へ順番にアクセスする際、ページが存在しない404エラーが出るとスクリプトが中止してしまいます。

【GAS】GASでのWebスクレイピングについて雑多に書いてみた。

この記事を参考にして404エラー時でも続行するようにしています。

メールの送信

【GAS】スプレッドシートからメールを送信する方法

こちらの記事を参考にしました。

最初は送信元となるGmailから自身宛に送るように設定していましたが、なぜかそれではうまく送れず。

他の宛先にしたらちゃんと送れました。

スクレイピングの注意点

スクレイピングはサイトによっては禁止されていますし、連続でアクセスを繰り返すとサーバーに負荷がかかります。

負荷を配慮して次のページへアクセスする時に5秒間隔をあけるようにしていますが、それでも十分と言えない場合があります。

相手に迷惑がかかるだけでなく、何らかのペナルティが生じる場合があるかもしれませんので、行う場合は自己責任でお願いします。

トリガーを設定

トリガーを設定しておけば定期的に発動してチェックしてくれます。GASはその点が便利ですね。

コメント

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