【GAS】Google Apps Script 活用事例 Twitter APIと連携して、Twitterの検索結果をSpreadsheetに書き出す方法
Twitter APIと、Google Spreadsheetの連携、第2段、ユーザーが自社のブランドについて、どのような事を呟いているか、エゴサーチのような業務で、使う事を想定し、書いてみました。
今回は、デバイスも加えてみました。オブジェクト形式でまとまっているので、コツさえ掴めば、比較的、簡単に取り出す事が出来ました。
const apiUrl = 'https://api.twitter.com/1.1/search/tweets.json?q=' + keyWord + '&lang=ja&result_type=recent&count=' + tweetCounter;
この部分で、本当に何度も、何度も、何度もエラーが出て、前に進めなかったのですが、下記の記事を見つけ、前途に光明を見い出す事が出来ました。感謝しかないです。
前回と同じように、keyWordsという検索ワードを記載したシートから読み取り、その検索結果を取得し続けます。
A列の検索キーワードに、
野比商事 評判
野比商事 面接
上記のように入力したあと、B列でエンコードした状態にします。replaceとかでも良かったんですが、今回は関数で行ました。SUBSTITUTE関数で、スペースを%20に変換しています。
完成形のスクリプトはこちら。
function getKeyWordsList() {
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const sheet = spreadsheet.getSheetByName('keyWords');
const lastRow = sheet.getLastRow();
//A3から最終行まで
const array = sheet.getRange(2, 2, lastRow -1, 1).getValues().flat();
console.log(`1次元配列の内容 ${array}`);
//リツイートを検索結果から除外する。
const newArray = array.map(element => element + ' -rt');
console.log(newArray);
return newArray;
}
function getToken2() {
// Twitter Bearerトークンの取得(検索APIの呼び出しに必要)
// POST oauth2/token https://developer.twitter.com/en/docs/basics/authentication/api-reference/token
const API = {
KEY: PropertiesService.getScriptProperties().getProperty('API_KEY'),
SECRET_KEY: PropertiesService.getScriptProperties().getProperty('API_SECRET_KEY'),
MILLISECOND: 100000 //tokenの有効期限(ミリ秒)
}
const blob = Utilities.newBlob(API.KEY + ':' + API.SECRET_KEY);
const credential = Utilities.base64Encode(blob.getBytes());
const formData = {
'grant_type': 'client_credentials'
};
const headers = {
'Authorization': 'Basic ' + credential
};
const options = {
'method': 'post',
'contentType': 'application/x-www-form-urlencoded;charset=UTF-8',
'headers': headers,
'payload': formData,
};
const response = UrlFetchApp.fetch('https://api.twitter.com/oauth2/token', options);
const token = JSON.parse(response).access_token;
console.log(token);
return token
}
function getSearchTweets(){
//Twitterの複数アカウントのタイムラインを読み込むため、配列で取得
const keyWords = getKeyWordsList();
let results = [];
for(let i = 0; i < keyWords.length; i++){
const keyWord = keyWords[i];
const tweetCounter = 20;
console.log(keyWord);
const apiUrl = 'https://api.twitter.com/1.1/search/tweets.json?q=' + keyWord + '&lang=ja&result_type=recent&count=' + tweetCounter;
const token = getToken2();
const apiOptions = {
'headers':{
'Authorization': 'Bearer ' + token
}
};
const responseApi = UrlFetchApp.fetch(apiUrl, apiOptions);
//HTTP リスポンスが200以外だったら、処理を終了
if (responseApi.getResponseCode() !== 200) return '';
const tweets = JSON.parse(responseApi.getContentText());
if (!tweets) return '';
//console.log(tweets)
const statuses = tweets.statuses;
for(const status of statuses){
//ツイートされた文字列を分割し、配列を作成する。
const date = new Date(status.created_at);
const tweetDate = Utilities.formatDate(date, 'Tokyo/Asia', 'yyyy/MM/dd E HH:mm');
let tweetContents = tweetDate.split(' ');
//アカウント名 ツイート内容
const user = status.user.screen_name;
const text = status.text;
//アイコン画像を取得
const profileImage = status.user.profile_image_url_https;
const formula = getImage(profileImage);
//どのデバイスからツイートをしたか
const device = status.source.match(/Twitter.*/);
const tweetId = status.id_str;
const tweetUrl = 'https://twitter.com/' + user + '/status/' + tweetId;
const retweet = status.retweet_count;
const favorite = status.favorite_count;
console.log(`${user}\n\n${text}\n${device}\n\n${tweetUrl}\n${retweet}\n${favorite}`);
//投稿時間が入っている配列に、要素を足していく。
tweetContents.push(user,formula, text, device, retweet, favorite, tweetUrl);
results.push(tweetContents);
}
}//for_i
console.log(`配列の内容 ${results}`);
return results;
}
function setSearchTweets() {
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const sheet = spreadsheet.getSheetByName('search');
const sheetName = sheet.getName();
const lastRow = sheet.getLastRow() + 1;
const userTweets = getSearchTweets();
sheet.getRange(lastRow, 1, userTweets.length, userTweets[0].length).setValues(userTweets);
//aタグを置換して削除する。
const textFinder = sheet.createTextFinder('</a>');
textFinder.replaceAllWith('');
//中横揃えなど 行の高さをイイ感じに修正する。
setStyle2();
sheet.setRowHeights(2, 999, 92);
//重複を削除
removeDuplicates(sheetName);
//日付の新しいツイートが上に
const range = sheet.getRange('A2:J');
range.sort([
{column: 1, ascending: false}
]);
}//ends
//イメージ関数を作成する。
function getImage(url) {
const formula = `=IMAGE("${url}",1)`;
return formula
}
理由は、よく分からないけど、動くようになった。
OAuth 2.0やHTTP responseなどは、GASとは全く別の知識で、関連所を最低5冊くらいは読み込まないと分からなそうな知識です。
なので、動いたには、動いたけど、どうして動いたのかを図説などで解説したくても出来ません。Twitter APIの変更とかで突然動かなくなったりする事も普通にあり得そうな気がします。
2020年6月現在は、このスクリプトで問題なく動いています。
for of 文を使って検索結果を処理していく。
for(const status of statuses){
//ツイートされた文字列を分割し、配列を作成する。
const date = new Date(status.created_at);
const tweetDate = Utilities.formatDate(date, 'Tokyo/Asia', 'yyyy/MM/dd E HH:mm');
let tweetContents = tweetDate.split(' ');
//アカウント名 ツイート内容
const user = status.user.screen_name;
const text = status.text;
//アイコン画像を取得
const profileImage = status.user.profile_image_url_https;
const formula = getImage(profileImage);
//どのデバイスからツイートをしたか
const device = status.source.match(/Twitter.*/);
const tweetId = status.id_str;
const tweetUrl = 'https://twitter.com/' + user + '/status/' + tweetId;
const retweet = status.retweet_count;
const favorite = status.favorite_count;
console.log(`${user}\n\n${text}\n${device}\n\n${tweetUrl}\n${retweet}\n${favorite}`);
//投稿時間が入っている配列に、要素を足していく。
tweetContents.push(user,formula, text, device, retweet, favorite, tweetUrl);
results.push(tweetContents);
}
検索結果が、statusesにまとまっていたので、これを、for of 文で回して取得しています。 userのTimelineの取得時と返り値が異なっていたため、ここもかなり苦労しました。
今回、上手くいった理由が、よく分からないので、OAuth2.0や、HTTP responseについては、勉強をする必要があるなと痛感。しかし、それはそれとして、LINE、Slackに続いて、何とか自力で、API連携して、Twitterの情報を取得出来るようになったのは、個人的にすごく大きいです。
Twitterの特定ユーザーのツイートを書き出す方法
Twitter API v2で、書きました。
この記事が気に入ったらサポートをしてみませんか?