LoginSignup
3
4

More than 3 years have passed since last update.

【初心者】GASで、Webスクレイピング, スプレッドシート保存, メール送信するコード

Posted at

はじめに

【初心者】GoogleAppsScriptでWebスクレイピングし、スプレッドシートに保存する
で学んだ内容を活かしたいと思い、

GASを利用したWebスクレイピングの練習で、品川区のWebサイトからGASでお知らせ情報を取得し、メール送付するスクリプトを作成しました。

品川区のお知らせ情報は以下の2つあり、それぞれのお知らせの情報を取得して別々にメールを送信することにしました。

  • 重要な情報
  • 区からのお知らせ

コード説明

function説明

function名 説明
scrapingJyuyou 「重要な情報」を処理するfunction
scrapingOshirase 「区からのお知らせ」を処理するfunction
sendMail 「scrapingJyuyou」と「scrapingOshirase」で取得したデータをメール送信するfunction

以下のコード実行前にやること

  • スプレッドシートの作成
    • 区からのお知らせ
    • 重要な情報
  • メール送信先(xxx@xxx.xxx)の書き換え

コード


function scrapingJyuyou() {
  // ■Scraping処理
  const url = 'https://www.city.shinagawa.tokyo.jp/';
  let fromText = '<ul class="infolist">'; // 取得するタグの開始指定
  let toText = '</ul>'; // 取得するタグの終了指定

  // スクレイピング
  const content = UrlFetchApp.fetch(url).getContentText();

  // パース
  let data = Parser.data(content).from(fromText).to(toText).iterate();

  // 登録日取得
  let regexUpdate = new RegExp('<span class="date">(.*?)</span>', 'g');
  let matchedUpdate = data.toString().match(regexUpdate);
  let replaceWordFromDate = /<span class="date">/g; // 取得後のタグで不要な部分を指定。後続のreplaceで利用する。
  let replaceWordToDate = /<\/span>/g; // 取得後のタグで不要な部分を指定。後続のreplaceで利用する。

  // タイトル取得
  var regexTitle = new RegExp('<a href=(.*?)>(.*?)</a>', 'g');
  var matchedTitle = data.toString().match(regexTitle);
  let replaceWordFromTitle = /<a href=(.*?)>/g;
  let replaceWordToTitle = /<\/a>/g;

  // URL取得
  var regexUrl = new RegExp('<a href=(.*?)>(.*?)</a>', 'g');
  var matchedUrl = data.toString().match(regexUrl);
  let replaceWordFromUrl = /<a href="/g;
  let replaceWordToUrl = /">(.*?)<\/a>/g;

  // 結果格納
  let items = [];

  // 不要なタグを除去して、結果(items)に追加
  for (let i in matchedUpdate) {
    items.push([
      matchedUpdate[i].replace(replaceWordFromDate, '').replace(replaceWordToDate, ''),
      matchedTitle[i].replace(replaceWordFromTitle, '').replace(replaceWordToTitle, ''),
      matchedUrl[i].replace(replaceWordFromUrl, '').replace(replaceWordToUrl, '')
    ]);
  }

  // ■Spreadsheet
  const sheet = SpreadsheetApp.getActive().getSheetByName('重要な情報');

  // Spreadsheetに登録
  sheet.getRange(2, 1, items.length, items[0].length).setValues(items);  


  // sendmail
  sendMail('重要な情報');

}


function scrapingOshirase() {

  // ■Scraping処理
  const url = 'https://www.city.shinagawa.tokyo.jp/PC/re_direct/hpg000016838.html';
  let fromText = '<ul class="link">'; // 取得するタグの開始指定
  let toText = '</ul>'; // 取得するタグの終了指定
  const content = UrlFetchApp.fetch(url).getContentText();

  let data = Parser.data(content).from(fromText).to(toText).iterate();
  // toString()
  // https://chaika.hatenablog.com/entry/2019/11/15/083000

  // 登録日取得
  let regexUpdate = new RegExp('<p class="news-list-date">(.*?)</p>', 'g');
  let matchedUpdate = data.toString().match(regexUpdate);
  let replaceWordFromDate = /<p class="news-list-date">/g; // 取得後のタグで不要な部分を指定。後続のreplaceで利用する。
  let replaceWordToDate = /<\/p>/g; // 取得後のタグで不要な部分を指定。後続のreplaceで利用する。

  // タイトル取得
  let regexTitle = new RegExp('<a href=(.*?)>(.*?)</a>', 'g');
  let matchedTitle = data.toString().match(regexTitle);
  let replaceWordFromTitle = /<a href=(.*?)>/g; // 取得後のタグで不要な部分を指定。後続のreplaceで利用する。
  let replaceWordToTitle = /<\/a>/g; // 取得後のタグで不要な部分を指定。後続のreplaceで利用する。

  // URL取得
  let regexUrl = new RegExp('<a href=(.*?)>(.*?)</a>', 'g');
  let matchedUrl = data.toString().match(regexUrl);
  let replaceWordFromUrl = /<a href="/g; // 取得後のタグで不要な部分を指定。後続のreplaceで利用する。
  let replaceWordToUrl = /">(.*?)<\/a>/g; // 取得後のタグで不要な部分を指定。後続のreplaceで利用する。

  // 結果格納
  let items = [];

  // 不要なタグを除去して、結果(items)に追加
  for (let i in matchedUpdate) {
    items.push([
      matchedUpdate[i].replace(replaceWordFromDate, '').replace(replaceWordToDate, ''),
      matchedTitle[i].replace(replaceWordFromTitle, '').replace(replaceWordToTitle, ''),
      matchedUrl[i].replace(replaceWordFromUrl, '').replace(replaceWordToUrl, '')
    ]);
  }

  // ■Spreadsheet
  const sheet = SpreadsheetApp.getActive().getSheetByName('区からのお知らせ');

  // Spreadsheetに登録
  // 2行目1列から取得
  sheet.getRange(2, 1, items.length, items[0].length).setValues(items);  

  sendMail('区からのお知らせ');
}


function sendMail(SheetByName) {
  // データ取得するシートを指定
  var sheet = SpreadsheetApp.getActive().getSheetByName(SheetByName);
  // シート内のデータ取得
  var rangeValues = sheet.getDataRange().getValues();
  let recipient = 'xxx@xxx.xxx'; // 送信先メールアドレスを入力してください
  let subject = '品川区 - ' + SheetByName; // メール件名。まあ適当に。
  let body = '';

  let date = new Date();
  let today = Utilities.formatDate(date, 'JST', 'yyyy-MM-dd');
  //現在の「日」を取得
  let day = date.getDate();
  //前日日付以降の情報を取得したい時は-1する
  date.setDate(day-1);
  //日付の表示形式を整形する
  let oneWeekBefore = Utilities.formatDate(date, 'JST', 'yyyy-MM-dd');
  let newFlg = false;

  for(let i=1; i<rangeValues.length; i++) {
    if (Utilities.formatDate(new Date(rangeValues[i][0]), 'Asia/Tokyo', 'yyyy-MM-dd') >= oneWeekBefore) {
      body += Utilities.formatDate(new Date(rangeValues[i][0]), 'Asia/Tokyo', 'yyyy-MM-dd');
      body += '\t'
      body += rangeValues[i][1]
      body += '\n'
      body += rangeValues[i][2]
      body += '\n\n'
    };
  };

  // 該当するレコードが無い場合は情報が無い旨をメール本文に記載
  if (body == '') {
    body = '新着情報はありません。';
  }

  GmailApp.sendEmail(recipient, subject, body); //, options
}

参考

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4