見出し画像

AnnictのGraphQL APIを利用してアニメの作品情報やエピソード情報を取得する

Annictshimbacoさんが運営されているアニメ視聴記録サービス

データを一括取得する方法について
とりあえずデータがどんなふうに取れるかスプレッドシートに貼り付けて確認するところまで

★流れ

①AnnictのGraphQL APIを利用して作品情報やエピソード情報を取得する
②取得した情報をGoogle Apps Scriptでスプレッドシートに貼り付ける

★前準備

・Googleアカウントを作って、Googleスプレッドシートを使えるようにしておく
・Annictのサイトでアカウントを作って、個人用アクセストークンを生成しておく

★必要であれば準備するもの(ここは飛ばしても大丈夫)

・GraphQL APIを操作するGUIクライアント

私はInsomniaを使ってます
初期設定は下記リンクを参考にしました

★早速やってみます

1.新規のスプレッドシートの「拡張機能」>「Apps Script」

2.コード.gs にデフォルトで入力されている4行を消す

3.下記「作品ごとのエピソード情報を取得してスプレッドシートに貼り付ける関数」をコピーしておく

作品ごとのエピソード情報を取得してスプレッドシートに貼り付ける関数

function fetchGraphQLData() {
  // GraphQLエンドポイント
  const endpoint = 'https://api.annict.com/graphql';  
  // 個人用アクセストークン
  const accessToken = '★★★ここに個人用アクセストークンを入力するのじゃ!★★★';

  // GraphQLクエリ
  const query = `{
    searchWorks(
      seasons: ["2024-winter"],
      orderBy: { field: SEASON, direction: ASC }
    ) {
      edges {
        node {
          annictId
          seasonYear
          seasonName
          media
          title
          episodesCount
          episodes(orderBy: { field: SORT_NUMBER, direction: ASC }) {
            edges {
              node {
                episodesNumber: number
                episodesTitle: title
              }
            }
          }
        }
      }
    }
  }`;

  // POSTリクエストのオプション
  const options = {
    method: 'post',
    contentType: 'application/json',
    headers: {
      Authorization: `Bearer ${accessToken}`,
    },
    payload: JSON.stringify({ query }),
  };

  // POSTリクエストの送信
  const response = UrlFetchApp.fetch(endpoint, options);
  const data = JSON.parse(response.getContentText());

  // クエリで取得したデータを処理してスプレッドシートに貼り付ける
  const rowData = data.data.searchWorks.edges.flatMap(edge => {
    const node = edge.node;
    const episodes = node.episodes.edges.map(edge => {
      const episodeNode = edge.node;
      return [episodeNode.episodesNumber, episodeNode.episodesTitle];
    });

    return episodes.length > 0 ? episodes.map(episode => [
      node.annictId,
      node.seasonYear,
      node.seasonName,
      node.media,
      node.title,
      ...episode,
    ]) : [[
      node.annictId,
      node.seasonYear,
      node.seasonName,
      node.media,
      node.title,
      '', // エピソード番号
      '', // エピソードタイトル
    ]];
  });

  // ヘッダー定義
  const headers = [
    'Annict ID',
    'シーズン年',
    'シーズン名',
    'メディア',
    'タイトル',
    'エピソード番号',
    'エピソードタイトル',
  ];

  // スプレッドシートをクリア、データを貼り付ける
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  sheet.clear();
  sheet.getRange(1, 1, rowData.length + 1, headers.length).setValues([
    headers,
    ...rowData
  ]);
}

4.コピーした関数をコード.gs に貼り付け、下記の例のように「const accessToken」で定義している文字列を「★前準備」で取得しておいた個人用アクセストークンの文字列に置き換える

例)const accessToken = 'NmSA********'

Ctrl+Sで一度保存して、実行するときは「▷実行」ボタンを押す(初回実行時に「承認が必要です」が表示される)

実行結果

2024年冬アニメの全エピソード情報取得

★別パターンも作ってみます

AnnictのGraphQL APIを利用してどんな情報が取れるかはInsomnia上で確認できます

こんな感じ

その情報を元にクエリを書いてみます
例えば、こう

query {
  searchWorks(
    seasons: ["2024-winter"],
    orderBy: { field: SEASON, direction: ASC }
  ) {
    edges {
      node {
        annictId
        seasonYear
        seasonName
        media
        title
        officialSiteUrl
        wikipediaUrl
        twitterHashtag
        twitterUsername
        staffs(orderBy: { field: SORT_NUMBER, direction: DESC }) {
          edges {
            node {
              staffsRoleText: roleText
              staffsName: name
            }
          }
        }
        casts(orderBy: { field: SORT_NUMBER, direction: ASC }, first: 4) {
          edges {
            node {
              character {
                castsCharacterName: name
              }
              castsName: name
            }
          }
        }
        programs(orderBy: { field: STARTED_AT, direction: ASC }, first: 1) {
          edges {
            node {
              channel {
                programsChannelName: name
              }
              programsStartedAt: startedAt
            }
          }
        }
      }
    }
  }
}

キャラクターと声優は4人分固定で取得

クエリのテストの様子

クエリは左  「Send」ボタンで実行した結果が右
傷物語の情報もバッチリ取れてます

この部分は

searchWorks(
    seasons: ["2024-winter"],
    orderBy: { field: SEASON, direction: ASC }
  )

こういうふうにも書けます

searchWorks(
    seasons: ["2023-winter","2023-spring","2023-summer","2023-autumn"],
    orderBy: { field: SEASON, direction: ASC }
  )


作ったクエリの情報をスプレッドシートに貼り付けてみます

作品の基本情報を取得してスプレッドシートに貼り付ける関数

function fetchGraphQLData() {
  // GraphQLエンドポイント
  const endpoint = 'https://api.annict.com/graphql';
  // 個人用アクセストークン
  const accessToken = '★★★ここに個人用アクセストークンを入力するのです!★★★';

  // GraphQLクエリ
  const query = `{
    searchWorks(
      seasons: ["2024-winter"],
      orderBy: { field: SEASON, direction: ASC }
    ) {
      edges {
        node {
          annictId
          seasonYear
          seasonName
          media
          title
          officialSiteUrl
          wikipediaUrl
          twitterHashtag
          twitterUsername
          staffs(orderBy: { field: SORT_NUMBER, direction: DESC }) {
            edges {
              node {
                staffsRoleText: roleText
                staffsName: name
              }
            }
          }
          casts(orderBy: { field: SORT_NUMBER, direction: ASC }, first: 4) {
            edges {
              node {
                character {
                  castsCharacterName: name
                }
                castsName: name
              }
            }
          }
          programs(orderBy: { field: STARTED_AT, direction: ASC }, first: 1) {
            edges {
              node {
                channel {
                  programsChannelName: name
                }
                programsStartedAt: startedAt
              }
            }
          }					
        }
      }
    }
  }`;

  // POSTリクエストのオプション
  const options = {
    method: 'post',
    contentType: 'application/json',
    headers: {
      Authorization: `Bearer ${accessToken}`,
    },
    payload: JSON.stringify({ query }),
  };

  // POSTリクエストの送信
  const response = UrlFetchApp.fetch(endpoint, options);
  const data = JSON.parse(response.getContentText());

  // クエリで取得したデータを処理してスプレッドシートに貼り付ける
  const rowData = data.data.searchWorks.edges.map(edge => {
    const node = edge.node;
    
    // 指定した役職と一致するスタッフ名をセット
    const staffs = {};
    node.staffs.edges.forEach(staff => {
      staffs[staff.node.staffsRoleText] = staff.node.staffsName;
    });

    // キャラと声優の組み合わせをセット(最大で4つ)
    const casts = Array(8).fill('');
    node.casts.edges.forEach((cast, index) => {
      casts[index * 2] = cast.node.character.castsCharacterName;
      casts[index * 2 + 1] = cast.node.castsName;
    });

    // 放送チャンネル名と放送開始日時があればセット
    const program = node.programs.edges[0]?.node;
    const programChannelName = program?.channel?.programsChannelName || '';
    const programsStartedAt = program?.programsStartedAt || '';

    return [
      node.annictId,
      node.seasonYear,
      node.seasonName,
      node.media,
      node.title,
      node.officialSiteUrl,
      node.wikipediaUrl,
      node.twitterHashtag,
      node.twitterUsername,
      staffs['監督'],
      staffs['アニメーション制作'],
      staffs['キャラクターデザイン'],
      staffs['シリーズ構成'],
      ...casts,
      programChannelName,
      programsStartedAt
    ];
  });

  // ヘッダー定義
  const headers = [
    'Annict ID',
    'シーズン年',
    'シーズン名',
    'メディア',
    'タイトル',
    '公式サイトURL',
    'Wikipedia URL',
    'Twitter ハッシュタグ',
    'Twitter ユーザー名',
    '監督',
    'アニメーション制作',
    'キャラクターデザイン',
    'シリーズ構成',
    'キャラ1',
    '声優1',
    'キャラ2',
    '声優2',
    'キャラ3',
    '声優3',
    'キャラ4',
    '声優4',
    '放送チャンネル名',
    '放送開始日時',
  ];

  // スプレッドシートをクリア、データを貼り付ける
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  sheet.clear();
  sheet.getRange(1, 1, rowData.length + 1, headers.length).setValues([
    headers,
    ...rowData
  ]);
}

監督やキャラデザが2人以上の場合、最初の1人分の情報だけ取れます

↓この部分

staffs['監督'],
staffs['アニメーション制作'],
staffs['キャラクターデザイン'],
staffs['シリーズ構成'],

を増やしてヘッダー定義を追加すると"美術監督""原作""音楽"などの情報も取得可能


実行結果

2024年冬アニメの全作品情報取得
傷物語の情報もバッチリ取れてます


取得した情報で色々なもの作れます

あとスプレッドシートから直でLooker Studioレポート作成できるようになったので便利
4/25のLooker Studioリリースノート


この記事が気に入ったらサポートをしてみませんか?