![見出し画像](https://assets.st-note.com/production/uploads/images/139509581/rectangle_large_type_2_2f9973e62f11f36476013c8b281cddf2.png?width=1200)
AnnictのGraphQL APIを利用してアニメの作品情報やエピソード情報を取得する
Annictはshimbacoさんが運営されているアニメ視聴記録サービス
データを一括取得する方法について
とりあえずデータがどんなふうに取れるかスプレッドシートに貼り付けて確認するところまで
★流れ
①AnnictのGraphQL APIを利用して作品情報やエピソード情報を取得する
②取得した情報をGoogle Apps Scriptでスプレッドシートに貼り付ける
★前準備
・Googleアカウントを作って、Googleスプレッドシートを使えるようにしておく
・Annictのサイトでアカウントを作って、個人用アクセストークンを生成しておく
★必要であれば準備するもの(ここは飛ばしても大丈夫)
・GraphQL APIを操作するGUIクライアント
私はInsomniaを使ってます
初期設定は下記リンクを参考にしました
★早速やってみます
1.新規のスプレッドシートの「拡張機能」>「Apps Script」
![](https://assets.st-note.com/img/1714809869244-XU0QHZwHA3.png?width=1200)
2.コード.gs にデフォルトで入力されている4行を消す
![](https://assets.st-note.com/img/1714809977081-tDlT6eE12o.png?width=1200)
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で一度保存して、実行するときは「▷実行」ボタンを押す(初回実行時に「承認が必要です」が表示される)
![](https://assets.st-note.com/img/1714810096446-QA7xVVDGCR.png?width=1200)
実行結果
![](https://assets.st-note.com/img/1714810522281-NhO26qOUzN.png?width=1200)
★別パターンも作ってみます
AnnictのGraphQL APIを利用してどんな情報が取れるかはInsomnia上で確認できます
![](https://assets.st-note.com/img/1714811036949-RT7lRfTh0T.png?width=1200)
こんな感じ
![](https://assets.st-note.com/img/1714811090849-FDIHncueiq.png)
その情報を元にクエリを書いてみます
例えば、こう
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人分固定で取得
クエリのテストの様子
![](https://assets.st-note.com/img/1714811304737-cGMOFEtXYR.png?width=1200)
傷物語の情報もバッチリ取れてます
この部分は
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['シリーズ構成'],
を増やしてヘッダー定義を追加すると"美術監督""原作""音楽"などの情報も取得可能
実行結果
![](https://assets.st-note.com/img/1715008404346-nDuCI24owt.png?width=1200)
傷物語の情報もバッチリ取れてます
取得した情報で色々なもの作れます
あとスプレッドシートから直でLooker Studioレポート作成できるようになったので便利
4/25のLooker Studioリリースノート
この記事が気に入ったらサポートをしてみませんか?