LoginSignup
2
2

More than 1 year has passed since last update.

【GAS】Instagram Graph APIを使って他ユーザーの投稿画像を自動取得するbotを作った

Last updated at Posted at 2022-10-30

はじめに

Instagram Graph APIの勉強も兼ねて、投稿情報の自動収集ツールを作りました。
ユーザーIDを入れると、投稿日・いいね数・コメント数・画像URL・動画URLをスプレッドシートに取得してくれます。
今回はクリスティアーノ・ロナウドの投稿を取得してみます。

完成品はこんな感じ

手順

  1. Instagram Graph APIの設定 (最難関)
  2. APIからJSON形式で投稿情報を取得
  3. JSONから必要な箇所を抽出して整形
  4. シートに書き込む

1. Instagram Graph APIの設定 (最難関)

大変なので割愛。

必要なもの

  • 有効期限なしのアクセストークン
  • InstagramビジネスアカウントのユーザーID

2. APIからJSON形式で投稿情報を取得

// Instagram Graph APIから画像情報をjson形式で取得する関数 (username, limit) -> json
function getPostImage(username, limit) {
  const USER_ID = ScriptProperties.getProperty('USER_ID');
  const ACCESS_TOKEN = ScriptProperties.getProperty('ACCESS_TOKEN') ;

  const url = "https://graph.facebook.com/v15.0/" + USER_ID +"?fields=business_discovery.username(" + username+ ")%7Bmedia.limit(" + limit + ")%7Btimestamp%2Clike_count%2Ccomments_count%2Cmedia_url%2Cchildren%7Bmedia_url%7D%7D%7D&access_token=" + ACCESS_TOKEN;
  
  const response = UrlFetchApp.fetch(url).getContentText();
  const response_json = JSON.parse(response).business_discovery.media.data;

  return response_json;
}

該当部分のソースコードはこんな感じ。

グラフAPIエクスプローラでフィールドをいじって投稿情報が取得できるかを確認し、
「< / >コードを取得」「cURL」「OK」 でURLは取得できます。

その後、ユーザーIDとアクセストークンをスクリプトプロパティから、ユーザーネームとlimitをセルから取得する形に変更しました。

3. JSONから必要な箇所を抽出して整形

// mediaオブジェクトを成形する関数 json -> array
function formatPost(post_json) {
  let formatted_data = [];

  formatted_data.push(post_json.id);
  formatted_data.push(post_json.timestamp);
  formatted_data.push(post_json.like_count);
  formatted_data.push(post_json.comments_count);

  if(post_json.hasOwnProperty('children')){
    const children = post_json.children.data;

    let images_url = '';

    for(child of children){
      images_url += child.media_url + '\n'
    }
    images_url = images_url.slice(0, -2);
    formatted_data.push(images_url);
  }
  else formatted_data.push(post_json.media_url);

  console.log(formatted_data);
  return formatted_data;
}

ソースコードはこんな感じ。
シートに書き込むデータは配列にしなければならないため、この関数で成形しています。

また、投稿のjsonデータは画像が複数枚ある場合はchildrenというオブジェクトが入れ子になっているため、投稿画像が1枚or複数枚で分岐させてます。

投稿画像が複数ある場合は、1つのリンク毎に改行した文字列を返します。
この場合、1つのセルに複数のリンクが存在することになるので別途処理が必要になりました(後述)。

4. シートに書き込む

for(post of posts){
    if(!hasID(post.id)){ // 未取得の投稿のみ書き込む
      const post_info = formatPost(post); // json形式の投稿情報を書き込み用に成形
      sheet.appendRow(post_info);
    }
    else continue;
}

1投稿毎にシートに取得済みかどうかをhasID関数で確認し、未取得であれば成形して1行ずつ書き込みます。

// メディアIDが存在するかを判定する関数 id -> bool
function hasID(id) {
  const sheet = SpreadsheetApp.getActiveSheet();
  const ids = sheet.getRange(3, 1, sheet.getLastRow()-1).getValues();

  return ids.some(function(array, i, ids){
    return (array[0] == id);
  })
}

hasId関数は投稿に紐づいたメディアIDというユニークな番号で未取得かどうかを判定します。

困ったところ

  • APIのアクセストークンの取得

  • 1つのセル内に複数リンクの設定

  • オフセットの設定がわからん
    このスクリプトでは「最新の投稿から◯件取得」のような仕様になっているため、めちゃくちゃ古い投稿を取得するのは困難(1000件くらいなら余裕だが、10000件とかになると怪しい)。リファレンスを読み込んでいないので、知っている方がいたらコメントください。

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