質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google カレンダー

Google カレンダーは、Google社が提供する無料のスケジュール管理ツールです。パソコンやスマートフォン、タブレットなどからアクセスし、スケジュールの追加・変更が可能。Googleアカウントがあれば誰でも使用できます。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

RSS

RSS(Really Simple Syndication)はブログのエントリやニュースの見出し、標準のフォーマットの音声やビデオなどを発行するために使われるウェブフィードのフォーマットの集合体です。

Twitter

Twitterは、140文字以内の「ツイート」と呼ばれる短文を投稿できるサービスです。Twitter上のほぼ全ての機能に対応するAPIが存在し、その関連サービスが多く公開されています。

Q&A

1回答

1133閲覧

RSS⇒スプレッドシート⇒Googleカレンダー⇒通知時間にTwitter投稿

kuroryu

総合スコア7

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google カレンダー

Google カレンダーは、Google社が提供する無料のスケジュール管理ツールです。パソコンやスマートフォン、タブレットなどからアクセスし、スケジュールの追加・変更が可能。Googleアカウントがあれば誰でも使用できます。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

RSS

RSS(Really Simple Syndication)はブログのエントリやニュースの見出し、標準のフォーマットの音声やビデオなどを発行するために使われるウェブフィードのフォーマットの集合体です。

Twitter

Twitterは、140文字以内の「ツイート」と呼ばれる短文を投稿できるサービスです。Twitter上のほぼ全ての機能に対応するAPIが存在し、その関連サービスが多く公開されています。

0グッド

0クリップ

投稿2020/03/04 00:56

編集2022/01/12 10:55

あるブログのRSSをスプレッドシートに読み込んで整形し、Googleカレンダーに読み込み、カレンダーで通知設定した時間になったら、自動でTwitterで予告投稿をするというプログラムを作っています。
見様見真似で1ヶ月ほど前からいろいろなサイトを参考に試行錯誤してこの方法に辿り着き、テストした時には成功したのですが、その後正常に動かなくなってしまいました。
手順を詳しく書きますと、
(1)ブログのRSSを取得してスプレッドシートに読み込み
(2)Googleカレンダー用に整形
(3)カレンダーに重複追加されないように、追加したら1行目に「済」マーク。次回予定追加時にマークがないもののみをカレンダーに追加。
(4)カレンダーで通知設定した「10分前」になったらTwitterで予告投稿。
という流れです。

スプレッドシートに書き込む時の手順が少々ごちゃごちゃしていますが、これはRSSのデータ本文から開始時間と終了時間を取得するためのもので、開始時間だけはRSSのPubDateで取得できますが、終了時間はコンテンツ本文に表示されたものから抜粋して取り出したものを使用するためです。その部分を一例を挙げて説明しますと、
☆RSSから「投稿日時」「タイトル」「本文」を取得して列ごとに書き込んだ際、本文セルの中に終了日時と場所の情報が一括で含まれているため、半角スペースで分割した後、「場所」が半角スペースで区切られてしまっているデータに関しては分割後結合するようにしています。
本文は
10:05~11:00(半角スペース)[あああ]
または、
10:05~11:00(半角スペース)[あああ(半角スペース)いいいいい]
というような形で配信されています。半角スペースで分割後、結合処理が必要なのは後者の場合のためです。
☆終了日時は本文から文字列として取得したものなので、B列に読み込んだ投稿日時を利用してカレンダーに読み込めるようにしています。
☆トリガーは「RSSread」を時間主導型で1時間おき、「MinuteCheckCalender」を1分おきに設定しています。

少ない知識の中で組んだ内容なので、書き方も正しくないかもしれませんし、非常に効率が悪いかもしれません。
テスト段階で一度だけ正常に動いたのに、その後一切動かなくなってしまいましたので困っています。アカウント、トリガー設定は一切変更していません。
どこかおかしいところや、もっと効率のよい方法があれば教えていただけないでしょうか?よろしくお願い致します。

function RSSread() { var LIMIT_TIME = 24*60*60; var NOW_UNIX_TIME = Math.floor((new Date().getTime())/1000);//現在時刻 var URL = "https://wifjkege8uhsogfxto.com/rss";//取得RSSのURL var body = ""; //URLから情報を取得 var data = UrlFetchApp.fetch(URL); var xml = XmlService.parse(data.getContentText()); var items = xml.getRootElement().getChildren('channel')[0].getChildren('item'); //itemの数だけまわす items.forEach(function(item){ var pubDate = new Date(item.getChild("pubDate").getText()); var pubDateUnixTime = Math.floor(pubDate.getTime()/1000); //もしitemの配信時刻と現在時刻の差が24時間以内だったら  if(NOW_UNIX_TIME-pubDateUnixTime<LIMIT_TIME){ var title = item.getChild("title").getText(); var date = item.getChild("description").getText(); } }); var mySheet = SpreadsheetApp.getActiveSheet(); //スプレッドシートに書き込み var cellnum = 1; for(var i = 0; i < items.length; i++) { var pubDate = new Date(items[i].getChild("pubDate").getText()); var title = items[i].getChild("title").getText(); var date = items[i].getChild("description").getText(); mySheet.getRange("B" + cellnum).setValue(pubDate); mySheet.getRange("D" + cellnum).setValue("「"+title+"」"); mySheet.getRange("E" + cellnum).setValue(date); cellnum++; } //D列の「~」を半角スペースに置換 var lastrow = mySheet.getLastRow(); for (var i = 0; i < lastrow; i++){ var rangeD = mySheet.getRange(i+1,5).getValue(); var replace = rangeD.replace("~"," "); mySheet.getRange(i+1,5).setValue(replace); //D列を半角スペースで分割 var beforeSplit = mySheet.getRange(i+1,5).setValue(replace); beforeSplit.splitTextToColumns(" "); //G列とH列を結合 var rangeG = mySheet.getRange(i+1,8).getValue(); var rangeH = mySheet.getRange(i+1,9).getValue(); mySheet.getRange(i+1,8).setValue(rangeG+" "+rangeH); mySheet.getRange(i+1,9).clear(); //B列の日付から年月日だけ取得 var rangeB = mySheet.getRange(i+1,2).getValue(); var rangeF = mySheet.getRange(i+1,7).getValue(); var YMD = Utilities.formatDate(rangeB,"JST","yyyy/MM/dd"); var HMS = Utilities.formatDate(rangeF,"JST","H:mm:ss"); mySheet.getRange(i+1,3).setValue(YMD+" "+HMS); } mySheet.deleteColumns(5,3); //----▲スプレッドシート整形終了▲---- //----▼Googleカレンダーに追加▼---- var calendar = CalendarApp.getDefaultCalendar(); var values = mySheet.getDataRange().getValues(); var range = mySheet.getDataRange(); var added = mySheet.getRange(i,1).getValue(); if(added == ""){ for(var i = 0; i < values.length; i++){ var title = values[i][3]; var startTime = values[i][1]; var endTime = values[i][2]; var option = { location: values[i][4] } calendar.createEvent(title, startTime, endTime, option); mySheet.getRange(i+1,1).setValue("済"); } } }//end of RSSread // カレンダーからTweet // Twitter AppのConsumer Api Key var API_KEY = "yyyyyyyyyyyyyy"; var API_SECRET = "zzzzzzzzzzzzzzzzz"; /* サービスの設定 */ function getService() { return OAuth1.createService('Twitter') .setAccessTokenUrl('https://api.twitter.com/oauth/access_token') .setRequestTokenUrl('https://api.twitter.com/oauth/request_token') .setAuthorizationUrl('https://api.twitter.com/oauth/authorize') .setConsumerKey(API_KEY) .setConsumerSecret(API_SECRET) .setCallbackFunction('authCallback') .setPropertyStore(PropertiesService.getUserProperties()); } /* コールバック関数 */ function authCallback(request) { var service = getService(); var authorized = service.handleCallback(request); if (authorized) return HtmlService.createHtmlOutput('認証成功'); } /* 認証リセット */ function reset() { getService().reset(); } /* 認証用URL */ function getOAuthURL() { Logger.log(getService().authorize()); } /*------------------------------------* * 毎分カレンダーから1週間先までの予定を見る。 * ↓ * 予定が現在、または通知を登録していた時間だった場合お知らせする *------------------------------------*/ function MinuteCheckCalender() { //カレンダーからイベントの取得 var myCals = CalendarApp.getCalendarById('xxxxxxx@gmail.com'); //特定のIDのカレンダーを取得 if (myCals != null) { //権限がないなどの時はnullになるので処理をスルーする //カレンダーから現在〜1週間後までのイベントを取得 var startDate = new Date(); startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate(), startDate.getHours(), startDate.getMinutes(), 0); var endDate = new Date(); endDate.setDate(endDate.getDate()+7); var myEvents = myCals.getEvents(startDate, endDate); if (myEvents.length > 0) { //カレンダーに予定がない時はスルーする //お知らせが必要な予定一覧を作成する var strBody = ""; for(var i = 0; i < myEvents.length; i++){ var alertTime = -1; var strStart = myEvents[i].getStartTime(); //イベントの開始時刻 //予定の日付と今日が同じかチェックする if (startDate.getFullYear() == strStart.getFullYear()) { if (startDate.getMonth() == strStart.getMonth()) { if (startDate.getDate() == strStart.getDate()) { //予定の日時と今が同じ時分かチェックする if (startDate.getHours() == strStart.getHours()) { if (startDate.getMinutes() == strStart.getMinutes()) { //何分前の通知かを保持 alertTime = 0; } } } } } var intReminders = myEvents[i].getPopupReminders(); //何分前にお知らせするか if (intReminders != null) { if (intReminders.length > 0) { //予定の日時じゃなくても通知が登録されていれば通知時間にお知らせする if (alertTime == -1) { for (var j = 0; j < intReminders.length; j++) { //通知として登録していた日時を取得 var minute = intReminders[j]; var alertDate = new Date(strStart.getTime()); alertDate.setMinutes(alertDate.getMinutes()-minute); //通知の日時と今日が同じかチェックする if (startDate.getFullYear() == alertDate.getFullYear()) { if (startDate.getMonth() == alertDate.getMonth()) { if (startDate.getDate() == alertDate.getDate()) { //通知の日時と今が同じ時分かチェックする if (startDate.getHours() == alertDate.getHours()) { if (startDate.getMinutes() == alertDate.getMinutes()) { //何分前の通知かを保持 alertTime = minute; break; } } } } } } } } } if (alertTime > 0) { var strTitle = myEvents[i].getTitle(); //イベントのタイトル var strLocation = myEvents[i].getLocation(); //場所 var strDescription = "\n"+myEvents[i].getDescription(); //説明 var strEvent = ""; if (myEvents[i].isAllDayEvent()) {//終日イベント strEvent += "【本日のお知らせ】\n本日は、"+strTitle+"です。"+strDescription; } else { var strEnd = myEvents[i].getEndTime(); //イベントの終了時刻 strEvent += "【まもなく】\n"+Utilities.formatDate(strStart,'JST','HH:mm')+"~"+Utilities.formatDate(strEnd,'JST','HH:mm')+" "+strLocation+"\n"+strTitle+strDescription; } if (strEvent != "") { strBody += strEvent; } } } if (strBody != "") {//Twitterに予定を投稿する var service = getService(); var endPointUrl = 'https://api.twitter.com/1.1/statuses/update.json'; var response = service.fetch(endPointUrl, { method: 'post', payload: { status: strBody } } ) } } } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

t_obara

2020/03/04 05:12

まずは、どのステップまで想定通り動作しているかを確認するのが良いのではないでしょうか。
guest

回答1

0

マイナス評価ばっちこい

Case 1. 本気で"どこかおかしいところ"が知りたい場合

  • 前回回答のように、できました BA で終わるのをやめ、なにをどうしたらできるようになったかを明らかにしましょう。

前回、本質的には動くはずだったコードでこちらは再現検証もして動くと申しあげているのに、うごかないと伺っておりました。それがなぜだかわからないのですが動くようになったとのことです。今回同じコードをどう指摘すればよいか分かりません。

  • 状況をつまびらかにしましょう。
var URL = "https://wifjkege8uhsogfxto.com/rss";//取得RSSのURL

これは、そこから得られる内容をこちらでは追試できない、ということを意味します。では取得したデータがシート上にどう展開されているか、カレンダーの予定はどうなったか、を示していただかないと、データがない、データが正しく整形されていない、時刻が正しく解釈できていない、など"データ"に起因する問題を無数に想定でき、対処方法の提言ができません。RSS からどういう値が取得できるかやどういう経過を辿っているのか詳細を明らかにしてください

Case2. 本気で"もっと効率のよい方法"が知りたい場合

やっている操作で、カレンダーにうつしているのは全く無意味です。カレンダーの通知機能で情報を取得しないのですから。
その処理をすっとばして、rss をシートにかき、毎分のチェックでは、予告したい時刻から n 分以内のものを投稿して、データを消せばいいと思います。
なお、こうしたことを具体的にかたちにしようにも RSS のデータ形式がわからないので、コードで示せません。
べつにそのサイトのことを知りたくはないのですが、XML のノード構造は公開してほしいです(著作権等に違反しないなら)。

投稿2020/03/04 13:59

papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問