LoginSignup
22
21

More than 3 years have passed since last update.

GASを使って、Twitter検索した結果をSlackへ定期投稿してみた

Last updated at Posted at 2020-01-05

この記事について

Google Apps Script(以下、GAS)を使って、情報収集のために、ある固定のキーワードで定期的に検索を行い、Slackへ自動投稿する、ということをやってみた備忘録です。
GASから定期的に固定メッセージを自動投稿するというのを前回実施したので、その続きです。
(ちなみに、TwitterとSlackの連携は、この手順ですぐできます)

手順

大まかな手順です。

  1. Twitter Developer Accountの申請
  2. Twitter Appの作成
  3. GASスクリプト作成
    4. Twitter Bearerトークン取得
    5. Twitter 検索
    6. Twitterの検索結果をSlackに通知
  4. GASトリガー設定(定期的実行)

手順詳細

1. Twitter Developer Accountの申請

Twitterの検索APIを呼ぶためには、Twitter Developer Accountの取得が必要です。
Twitter Developerのサイトから申請し、承認される必要があります。
右上の[Apply]から申請を開始できます。
01_twitterDevAccount.png

申請時、Twitterアカウントでログインを求められるので、作成するアプリで利用するTwitterアカウントが必要です。私は、既存の普段使っているアカウントを使用しました。

また、Twitter APIを利用する予定のアプリケーションについて、その内容や目的などを英語で書く必要がありました。Google翻訳を利用しながら埋めました。
申請には30分〜1時間くらい時間がかかったので、時間に余裕があるときに取り組むとよさそうです。
Twitter Developerの登録については既に色々な記事が書かれているので、気をつけるべきポイントを事前に確認できました。

承認されると、このようなメールアドレス確認のメールが届きました。
02_twitterDevAccountConfirm.png

メールアドレスを確認すると、無事にDeveloper Accountが取得できました! :tada:
03_twitterDevAccountComplete.png

私の場合、申請してから承認されるのに1時間もかからなかった記憶があるのですが、このあたりは申請内容に拠るのだと思います。既出の記事だと、数日かかる場合もあるようでした。

2. Twitter Appの作成

Twitterの公式ドキュメントのGetStartedに従いながら進めます。
Twitter Developer Account / GetStarted

Twitter APIを使用するには、OAuth認証スキームの一部として、アプリを作成する必要があります。
アプリを作成することで、API呼び出しに必要なAPI keysが発行されます。
Twitter DeveloperサイトのAppsページへ行き、Create an appから必要な項目を入力し、Appを作成します。
04_twitter_apps.png
05_twitter_create_app.png
09_create_app_form.png

アプリが作成され、Consumer API keysが生成されました。
Website URLが必須項目だったので、作成する予定のGASスクリプトのURLを登録しました。(URLを指定するために、空のGASスクリプトを作成しておきました。)
[Keys and tokens]の注意書きで書かれているように、2020年1月20日以降は、初回にaccess tokenaccess token secretを生成した以降はこのページで表示されなくなるので、必要なら書き留めておく必要がありそうです。またはいつでもこのサイトから再生成できるようです。
06_twitter_create_app.png
07_twitter_api_keys.png

アプリのAccess permissionは、ツイートを読み込むだけでツイートの書き込みはしないので、Read-onlyに設定しました。
08_twitter_permission.png

参考になりそうな公式ドキュメントはこちら :point_down: です。

これで、Twitter APIを呼び出す準備が整いました。

3. GASスクリプト作成

ここから、GASのスクリプトを書いていきます。
この手順の1-3を参考に、GASのスクリプトを用意します。

1. Twitter Bearerトークン取得

Twitter APIを呼ぶには認証が必要です。

特定のアカウントのデータにアクセスする(ユーザの情報を読み取ったり、そのユーザとして書き込みする)にはアクセストークンでの認証が必要です。公開されている情報にアプリケーションとしてアクセスするにはアプリケーション認証(Bearerトークン)を行います。
今回は、公開されている情報にアクセスすれば十分なので、Bearerトークンを使ったアプリケーション認証を行います。
認証の処理の流れは、こちらの図がわかりやすいです。
10_application_auth.png
出典:Application-only authentication

Twitter認証について参考になりそうなページはこちら :point_down: です。

GASで、TwitterのBearerトークンを取得するプログラムを書いていきます。
Twitterのドキュメント(Application-only authentication)に、アプリケーション認証の方法が書かれているので、それに沿って進めます。

POST oauth2/tokenに、以下のようなリクエストを行う必要があります。

  • Authorizationヘッダに、Consumer key、コロン[:]、Consumer secretを連結してBase64エンコードした文字列をBasic xxxxxxxxxxxの形式で設定
  • Content-Typeヘッダにapplication/x-www-form-urlencoded;charset=UTF-8を設定
  • リクエストボデイにgrant_type=client_credentialsを設定

(ドキュメントでは、最初にConsumer keyConsumer secretRFC1738に沿ってURLエンコードする必要があると書いてありました。この手順はConsumer keyConsumer secretの値を変更しないが、これらの値の形式が将来変更される場合に備えてこの手順を実行する必要があるということです。今回は、現時点で値は変更されないので省略しました。)

参考にしたURLです。

Bearerトークンを取得するコードです。

var consumer_key = 'xxxxxxxxxxxxxxxxx';
var consumer_secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

function searchTweetsApps() { 
  // ①Twitter Bearerトークンの取得(検索APIの呼び出しに必要)
  // POST oauth2/token  https://developer.twitter.com/en/docs/basics/authentication/api-reference/token
  var blob = Utilities.newBlob(consumer_key + ':' + consumer_secret);
  var credential = Utilities.base64Encode(blob.getBytes());

  var formData = {
    'grant_type': 'client_credentials'
  };
  
  var basic_auth_header = {
    'Authorization': 'Basic ' + credential
  };
  
  var options = {
    'method': 'post',
    'contentType': 'application/x-www-form-urlencoded;charset=UTF-8',
    'headers':  basic_auth_header,
    'payload': formData,
  };
  
  var oauth2_response = UrlFetchApp.fetch('https://api.twitter.com/oauth2/token', options);  
  var bearer_token = JSON.parse(oauth2_response).access_token; 

ちゃんとBearerトークンが取得できているか見たいので、GASでログに書き出してみます。

Logger.log(bearer_token);

GASの[View]->[Logs]から見ると、Bearerトークンが参照できたので問題なさそうです。

11_bearer_token.png

2. Twitter 検索

やっと、本題のTwitter検索です。
Twitterの検索APIは、こちらのドキュメントSearch Tweets API overviewを見ていただけるとわかるのですが、Standard, Premium, Enterpriseの3種類があります。検索対象の期間、有料/無料などが異なり、できることが異なっています。
今回は、無料で7日前までのツイートを検索できるStandardを使います。

APIリクエストのAuthorizationヘッダに、前述の手順で取得したBearerトークンを、Bearer xxxxxxxxxxxxxの形式で設定します。
リファレンスはこちら :point_down: です。

GASで書いたコードです。
変数search_keywordには、[Using Standard Searchのドキュメント]に沿って、ツイートを検索したい文字列を設定します。
私は検索結果からリツイートを除外したかったので、-rtを指定しています。
また、検索件数をcountで指定できるので、3件を指定しました。

  // ②Twitter 検索APIの呼び出し 
  // GET https://api.twitter.com/1.1/search/tweets.json
  var search_keyword = 'xxxxx -rt';

  var bearer_auth_header = {
    'Authorization': 'Bearer ' + bearer_token
  };
  
  var search_response = UrlFetchApp.fetch(
    'https://api.twitter.com/1.1/search/tweets.json?q=' + search_keyword + '&lang=ja&result_type=recent&count=3',
    { 'headers': bearer_auth_header });
  result = JSON.parse(search_response);

3. Twitterの検索結果をSlackに通知

Twitterで検索結果の文字列を、Slackに通知します。
こちらの手順4を参考に、SlackのWebhook URLを呼び出すコードを書きます。

こんなコードになりました。
検索結果が3件なので、forEachで1件ずつSlackにPOSTしています。
投稿結果がわかりやすいように、ツイートの投稿日時(created_at)やユーザ名(user.name)、区切り線を入れてみました。

  // ③Slackに通知  Incoming Webhook
  result.statuses.forEach(function(status) {    
    var data = { 
      'text': '-----------------------------------------\n' +
      status.text + 
      '\n----------------------------------------\n' +
      status.created_at + 
      '\nby ' + 
      status.user.name,
    };
  
    var options = {
      'method' : 'post',
      'contentType': 'application/json',
      'payload' : JSON.stringify(data)
    };

    UrlFetchApp.fetch(slackWebhookUrl, options);

これでGASを実行すると、このように検索結果がSlack通知されました。
GAS%20Google Apps Script -rtで検索した結果です)

12_result.png

4. GASトリガー設定(定期的実行)

あとは、定期実行のために、GASでトリガーを設定します。
こちらの手順を参考に、GASのトリガーを設定します。
これで、定期的にTwitterを固定キーワードで検索して、その結果をSlackに投稿することができました! :tada:

最後に、全体のコードを載せておきます。


var slackWebhookUrl = 'https://hooks.slack.com/services/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

var consumer_key = 'xxxxxxxxxxx';
var consumer_secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

var search_keyword = 'xxxxxxxx -rt';

function searchTweetsApps() { 
  // ①Twitter Bearerトークンの取得(検索APIの呼び出しに必要)
  // POST oauth2/token  https://developer.twitter.com/en/docs/basics/authentication/api-reference/token
  var blob = Utilities.newBlob(consumer_key + ':' + consumer_secret);
  var credential = Utilities.base64Encode(blob.getBytes());

  var formData = {
    'grant_type': 'client_credentials'
  };
  
  var basic_auth_header = {
    'Authorization': 'Basic ' + credential
  };
  
  var options = {
    'method': 'post',
    'contentType': 'application/x-www-form-urlencoded;charset=UTF-8',
    'headers':  basic_auth_header,
    'payload': formData,
  };
  
  var oauth2_response = UrlFetchApp.fetch('https://api.twitter.com/oauth2/token', options);  
  var bearer_token = JSON.parse(oauth2_response).access_token; 
  
  // ②Twitter 検索APIの呼び出し 
  // GET https://api.twitter.com/1.1/search/tweets.json
  var bearer_auth_header = {
    'Authorization': 'Bearer ' + bearer_token
  };
  
  var search_response = UrlFetchApp.fetch(
    'https://api.twitter.com/1.1/search/tweets.json?q=' + search_keyword + '&lang=ja&result_type=recent&count=3',
    { 'headers': bearer_auth_header });
  result = JSON.parse(search_response);
  
  // ③Slackに通知  Incoming Webhook
  result.statuses.forEach(function(status) {    
    var data = { 
      'text': '-----------------------------------------\n' +
      status.text + 
      '\n----------------------------------------\n' +
      status.created_at + 
      '\nby ' + 
      status.user.name,
    };
  
    var options = {
      'method' : 'post',
      'contentType': 'application/json',
      'payload' : JSON.stringify(data)
    };

    UrlFetchApp.fetch(slackWebhookUrl, options);    
  });
}

やってみた感想

TwitterのAPIを触るのがはじめてだったので、Developer Accountの申請、APIの認証方式などについて調べるのに手間取りましたが、Twitterからの定期的な情報収集という目的が果たせたのはよかったです。
Slackへの投稿も装飾したりできそうなので、広げてやってみたらおもしろいかもしれないと思っています。

22
21
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
22
21