0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめての記事投稿
Qiita Engineer Festa20242024年7月17日まで開催中!

クライミングジムのインスタ投稿からセットスケジュールを抜き出してGoogleカレンダーに登録するまでの話-の続き

Last updated at Posted at 2024-06-28

これまでの話

前回の記事で、InstagramAPIからクライミングジムの投稿を抜き出すことができました

ここからの話

今回はスケジュールをGoogleカレンダーに登録して行きます
ざっくりとした作業の流れは

  1. GASからInstagramAPIを呼び出す
  2. 投稿内容からセットスケジュールを抜き出す
  3. Googleカレンダーにスケジュールを登録する

となります
いろんな説明をすっ飛ばしたい方は、最後にコード全体を載せてありますのでそちらを利用してください

GASってなーに

20211221163618.jpg

GASとはGoogleAppsScriptの略で、Googleが提供しているお手軽Web開発環境のことです

  • Webページの作成
  • WebAPIの作成
  • 外部APIの利用
  • Googleの各種サービス/APIの利用

などがとても簡単にできるので、おすすめです

ちなみに…
GAS環境で構築しなければいけない理由はありません
今後Googleカレンダーを使ったりスプレッドシートに情報を保存したり、GoogleVisonAPIを使ったりってことを考えているのでGASに実行環境を作っています

実装していく

GASでプロジェクトを作成する

GASでプログラムを書くときはまずプロジェクトを作成します

  1. Googleアカウントを取得
  2. GASのホームへアクセス
  3. 新しいプロジェクトを作成します

するとこんな画面になるのでプロジェクトの名前を適当に設定

スクリーンショット 2024-06-27 15.09.02.png

GASからInstagramAPIを呼び出す

以下のコードをmyFunctionの下に記述します

getRecentPages
function getRecentPages(targetAccount){
  var instragramID = 'InstagramビジネスID';
  var ACCESS_TOKEN = 'APIアクセストークン';
  var facebook_url = 'https://graph.facebook.com/v20.0/'+instragramID+'?fields=business_discovery.username('+targetAccount+'){followers_count,media_count,media{id,caption}}&access_token='+ACCESS_TOKEN;
  var response = UrlFetchApp.fetch(encodeURI(facebook_url),{muteHttpExceptions:true}); //URLから情報を取得
  var jsonData = JSON.parse(response);//JSONデータをパース
  inData = jsonData['business_discovery']['media']['data'];
  for(let index in inData)
  {
    var caption = inData[index]['caption'];
    console.log(caption);
  }
}
  • instragramID
  • ACCESS_TOKEN
    前の記事で取得した値に設定して
    myFunctionからgetRecentPagesを呼び出します
myFunction
function myFunction() {
  getRecentPages('bpumptokyo');
}

getRecentPagesの引数には取得したいインスタグラムアカウントのIDを入力します
インスタグラムのアカウントIDはブラウザでアクセスした時のURL
https://www.instagram.com/{この部分}/
または@でアカウント表すときの
@{この部分}
を指定します

今回の例で使用しているのは東京/秋葉原にあるBPUMP TOKYOのアカウントです
InstagramAPIの公式はやけにブルーボトルコーヒーを見せたがりますが
こちらのアカウントも人気のジムです◎

実行してみる

実行するときはコードの上部にある実行ボタンを押すだけ(!)簡単ですね

スクリーンショット 2024-06-28 7.31.55.png

初回の実行時は以下のように権限の承認を求められると思うので承認を行います
スクリーンショット 2024-06-27 15.12.16.png

承認が完了するとプログラムが実行されます
getRecentPagesでは実行結果をコンソールに出力しているので実行結果が実行ログに以下のように表示されます
スクリーンショット 2024-06-27 15.12.50.png

投稿内容からセットスケジュールを抜き出す

投稿内容は取得できるようになりましたが
ジムのインスタの記事にはいろんな種類があるので

  • セットスケジュールのお知らせ
  • メンテ日のお知らせ
  • 新商品のお知らせ
  • 課題の紹介
  • イベントのお知らせ
    などなど…

今回はセットスケジュールが欲しいので、それっぽいことが書いてある投稿のみ抜き出します

InstagramAPIを呼び出すコード
function getRecentPages(targetAccount){
  var instragramID = 'InstagramビジネスID';
  var ACCESS_TOKEN = 'APIアクセストークン';
  var facebook_url = 'https://graph.facebook.com/v20.0/'+instragramID+'?fields=business_discovery.username('+targetAccount+'){followers_count,media_count,media{id,caption}}&access_token='+ACCESS_TOKEN;
  var response = UrlFetchApp.fetch(encodeURI(facebook_url),{muteHttpExceptions:true}); //URLから情報を取得
  var jsonData = JSON.parse(response);//JSONデータをパース
  inData = jsonData['business_discovery']['media']['data'];
  for(let index in inData)
  {
    var caption = inData[index]['caption'];
+   if(caption !== undefined)
+   if(caption.includes('Route') || caption.includes('Schedule') || caption.includes('セット')|| caption.includes('スケジュール'))
+   {
    console.log(caption);
+   }
  }
}

本文(caption)にそれっぽいワード(Route,Schedule,セット等)が入っているかどうかで判別しています
いろんなジムでスケジュールをお知らせする時に使う文言が違うので、
対象のジムを増やしたいときはここをメンテナンスする必要があります
Scheduleを含めてしまうと関係ないイベントも結構拾ってしまうんですがそれはご愛嬌としてます
もっと細かく設定したい場合は引数として受け取る店舗ごとに適切なフィルタを設定するのが良いと思います◎

実行してみる

この状態で実行するとスケジュール関連の投稿のみがコンソールに表示されます

スクリーンショット 2024-06-28 7.59.38.png

無事スケジュール関連の投稿のみ抜き出すことができました◎

Googleカレンダーにスケジュールを登録する

ここまででインスタグラムの投稿からスケジュールのテキストを抜き出すことができました
GASにはGoogleカレンダーに予定を登録するライブラリがすでにあるので、それを利用します(便利)

登録にはGoogleカレンダーのIDが必要になりますので作成して取得します

GoogleカレンダーのIDを取得する

  • Googleカレンダーにアクセス
  • 設定->マイカレンダーの設定->カレンダーの統合->カレンダーID

取得してメモに保存しておきます

Googleカレンダーに予定を登録する

以下にカレンダーへ登録する部分のソースコードを載せます
少し長いですがやっていることはざっくりいうと

  • 本文から日付を取得する
  • 取得した日付分スケジュールを登録する

です

細かい仕様を説明すると

  • 一つの投稿に複数日付がある場合には全部取得して全部の日程に予定を登録
  • アカウントIDを件名に設定
  • 同じ件名で予定が登録されていない場合に取得した日付でカレンダーを登録

という実装になっています

カレンダーへ投稿する関数
function extractAndScheduleToCustomCalendar(targetAccount,postText) {
  var dates = [];
  
  // 日付を抽出する正規表現パターン
  var datePattern = /(\d{1,2})[\/](\d{1,2})(?:\([月火水木金土日]\))?/g;
  
  // 投稿テキストから日付を抽出
  var match;
  while ((match = datePattern.exec(postText)) !== null) {
    var month = parseInt(match[1], 10); // 月(数値に変換)
    var day = parseInt(match[2], 10);   // 日(数値に変換)
    
    // 今年の日付としてDateオブジェクトを作成
    var currentYear = new Date().getFullYear();
    var date = new Date(currentYear, month - 1, day); // 月は0から始まるため、-1する
    
    // 日付が有効かどうかを確認(無効な日付は無視)
    if (!isNaN(date.getTime())) {
      dates.push(date);
    }
  }
  // 専用のカレンダーを指定してイベントを追加
  var calendarId = '{GoogleカレンダーのID}'; // GoogleカレンダーのID(カレンダー設定から確認できる)
  var calendar = CalendarApp.getCalendarById(calendarId);
  
  // 各日付に対してイベントを登録
  for (var i = 0; i < dates.length; i++) {
    var eventTitle = targetAccount; // イベントのタイトル
    var eventDescription = postText; // イベントの説明
    var events = calendar.getEventsForDay(dates[i]);
      // 同じ日に同じ件名の予定があるかどうかをチェック
    var isDuplicate = events.some(function(event) {
      return event.getTitle() === eventTitle;
    });
    if(!isDuplicate){
      var event = calendar.createAllDayEvent(eventTitle, dates[i], {
        description: eventDescription
      });
      console.log('Event ID: ' + event.getId() + ' targetAccount:' + targetAccount);
    }
  }
}

getRecentPagesからextractAndScheduleToCustomCalendarを呼び出すように修正します

extractAndScheduleToCustomCalendarを呼び出すコード
function getRecentPages(targetAccount){
  var instragramID = 'InstagramビジネスID';
  var ACCESS_TOKEN = 'APIアクセストークン';
  var facebook_url = 'https://graph.facebook.com/v20.0/'+instragramID+'?fields=business_discovery.username('+targetAccount+'){followers_count,media_count,media{id,caption}}&access_token='+ACCESS_TOKEN;
  var response = UrlFetchApp.fetch(encodeURI(facebook_url),{muteHttpExceptions:true}); //URLから情報を取得
  var jsonData = JSON.parse(response);//JSONデータをパース
  inData = jsonData['business_discovery']['media']['data'];
  for(let index in inData)
  {
    var caption = inData[index]['caption'];
   if(caption !== undefined)
   if(caption.includes('Route') || caption.includes('Schedule') || caption.includes('セット')|| caption.includes('スケジュール'))
   {
+    extractAndScheduleToCustomCalendar(targetAccount,caption);   
-    console.log(caption);
   }
  }
}

実行してみる

プログラム上部の実行ボタンから再実行すると
コンソールに実行ログが出ているのがわかると思います

スクリーンショット 2024-06-28 11.31.01.png

無事スケジュールに登録することができました

スクリーンショット 2024-06-28 11.31.32.png

最後に

コード全体を載せておきます
うまく動かないときはここと見比べてみてください

コード全体
function myFunction() {
  getRecentPages('bpumptokyo');
}

function getRecentPages(targetAccount){
  var instragramID = '{InstagramビジネスID}';
  var ACCESS_TOKEN = '{アクセストークン}';
  var facebook_url = 'https://graph.facebook.com/v20.0/'+instragramID+'?fields=business_discovery.username('+targetAccount+'){followers_count,media_count,media{id,caption}}&access_token='+ACCESS_TOKEN;
  var response = UrlFetchApp.fetch(encodeURI(facebook_url),{muteHttpExceptions:true}); //URLから情報を取得
  var jsonData = JSON.parse(response);//JSONデータをパース
  inData = jsonData['business_discovery']['media']['data'];
  for(let index in inData)
  {
    var caption = inData[index]['caption'];
    if(caption !== undefined)
    if(caption.includes('Route') || caption.includes('Schedule') || caption.includes('セット')|| caption.includes('スケジュール'))
    {
     extractAndScheduleToCustomCalendar(targetAccount,caption);
    }
  }
}
function extractAndScheduleToCustomCalendar(targetAccount,postText) {
  var dates = [];
  // 日付を抽出する正規表現パターン
  var datePattern = /(\d{1,2})[\/](\d{1,2})(?:\([月火水木金土日]\))?/g;
  // 投稿テキストから日付を抽出
  var match;
  while ((match = datePattern.exec(postText)) !== null) {
    var month = parseInt(match[1], 10); // 月(数値に変換)
    var day = parseInt(match[2], 10);   // 日(数値に変換)
    
    // 今年の日付としてDateオブジェクトを作成
    var currentYear = new Date().getFullYear();
    var date = new Date(currentYear, month - 1, day); // 月は0から始まるため、-1する
    
    // 日付が有効かどうかを確認(無効な日付は無視)
    if (!isNaN(date.getTime())) {
      dates.push(date);
    }
  }
  // 専用のカレンダーを指定してイベントを追加
  var calendarId = '{GoogleカレンダーID}';
  var calendar = CalendarApp.getCalendarById(calendarId);
  
  // 各日付に対してイベントを登録
  for (var i = 0; i < dates.length; i++) {
    var eventTitle = targetAccount; // イベントのタイトル
    var eventDescription = postText; // イベントの説明
    var events = calendar.getEventsForDay(dates[i]);
      // 同じ日に同じ件名の予定があるかどうかをチェック
    var isDuplicate = events.some(function(event) {
      return event.getTitle() === eventTitle;
    });
    if(!isDuplicate){
      var event = calendar.createAllDayEvent(eventTitle, dates[i], {
        description: eventDescription
      });
      console.log('Event ID: ' + event.getId() + ' targetAccount:' + targetAccount);
    }
  }
}

今後の改修予定

カレンダーの色分けをしたいとなるとCalendarAppではなくGoogleのカレンダーAPIを利用することになります。GCPでプロジェクトを作ってAPIキーを取得すればすぐ利用できるようになるので、次のチャレンジとするかもしれません

お疲れ様でした

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?