2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

アニメのデータが使いたくて外部APIを使う話

Posted at

はじめに

自分は10月よりAPPRENTICE SHIP(内定直結型エンジニア学習プログラム)のカリキュラムに2期生として参加しています。
その一環としてチーム開発を行っており、技術情報をまとめることで学習に役立てるよう、記事を作成しております。

概要

今回はチーム開発において外部のAPIサービスを利用する必要が出てきたので、情報をまとめております。
具体的には検索候補(オートコンプリート機能)をフロントエンドで実装する手順をまとめました。

今回使用させて頂くAPIサービス

ANNICT

試聴中のアニメを記録してくれるwebアプリケーションサービスになります。
スクリーンショット 2024-01-06 16.21.55.png
(※サーバーの関係か画像が読み込まれなかった)

Annict Developers

有志の方により開発が行われており、今回はこちらで公開しているAPIサービス
Annict developers」を使用させて頂きます。

スクリーンショット 2024-01-06 16.24.50.png

問題と使用用途

今回開発しているアニメ関係のアプリでタイトルを登録する際に、ユーザー任せで記入してしまうと表記揺れが発生してしまうことが予想されました。
その予防策として、検索式にしてタイトルを選択してもらう機能(オートコンプリート機能)が必要となりました。
またタイトルに応じて話数の取得が必要となり、Annict様よりAPIを使ってデータをお借りする運びとなりました。
アニメ聖地.002.jpeg

そもそもAPIって?

API

ソフトウェア同士が情報をやり取りする際に使用されるインタフェースのことです。より細かく表現すると、アプリケーション同士が接続する際のプロトコルや接続部分の仕様を取り決めたもの、と定義されます。

アプリケーションの開発者は、APIを使ってアプリケーション間の連携がスムーズに行えるよう、意識してプログラムを作成します。

WEB API

APIの中でも、インターネットを経由して情報のやり取りが行われるAPIを「Web API」と呼びます。

Web APIは、インターネット上で情報のやり取りに広く使われているHTTP/HTTPSを利用して、アプリケーション同士が接続する仕組みを提供します。使用するプログラミング言語の仕様に左右されず、汎用的に利用できることが大きな特徴です。

出典元:KDDI 今さら聞けない「API」とは?

使用準備

Annictのアカウント作成、ログイン

APIを利用するにあたり、こちらのページからアカウントを作成してください。
スクリーンショット 2024-01-06 22.45.41.png

個人用アクセストークンの生成

アカウント作成が完了したら「設定」⇨「アプリケーション」のタブからアクセストークンの「新規作成」を行なって下さい。
今回はデータの使用なので「読み込み専用」の設定でトークンを作成します。
スクリーンショット 2024-01-06 22.58.46.png

トークンは一度しか表示されないのでコピーをしておいて下さい。
スクリーンショット 2024-01-06 23.14.28.png

詳細はこちらに記載があります。
Annict 個人用アクセストークンの作成方法

実装と解説

今回はJavaScriptのライブラリ「AutoComplete.js」を使用してオートコンプリート機能を実装していきたいと思います。
参考サイト: AutoComplete.js活用術

デモ画面

実際のデモ画面がこちらになります。
スクリーンショット 2024-01-07 17.28.16.png
インプットの検索するキーワードに応じて検索候補が表示されます。
スクリーンショット 2024-01-07 17.28.45.png

HTML

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>オートコンプリートデモ</title>
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
      rel="stylesheet"
    />
  </head>
  <body>
    <div class="container mt-5">
      <h2>オートコンプリートデモ</h2>
      <input
        id="autoComplete"
        class="form-control"
        type="text"
      />
    </div>

    <!-- autoComplete.jsの読み込み -->
    <script src="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@10/dist/autoComplete.min.js"></script>
    <!-- script.jsの読み込み -->
    <script src="script.js"></script>
  </body>
</html>

*CSSにはbootstrap5を使用しています。

JavaScript

script.js
// API config
const api = "https://api.annict.com/v1/works";

const token = "ご自身のTOKENを入れて下さい";

const annictFetchData = async (query) => {
  const params = {
    filter_title: query,
  };
  const queryString = new URLSearchParams(params).toString();
  const urlWithParams = `${api}?${queryString}&access_token=${token}`;

  const response = await fetch(urlWithParams);
  const data = await response.json();
  console.log(data);
  return data.works; // 作品のリストを返す
};

// autoComplete.js
const autoCompleteJS = new autoComplete({
  name: "autoComplete",
  selector: "#autoComplete",
  wrapper: true,
  data: {
    src: async (query) => {
      const source = await annictFetchData(query);
      return source.map((work) => work.title);
    },
    cache: false,
  },
  placeHolder: "検索クエリを入力してください...",
  debounce: 100, // Milliseconds value
  searchEngine: "loose",
  resultsList: {
    render: true,
    container: (source) => {
      source.setAttribute("id", "autoComplete_list");
      source.classList.add("list-group");
    },
  },
  resultItem: {
    highlight: true,
    content: (data, source) => {
      source.innerHTML = data.match;
      source.classList.add("list-group-item");
      source.classList.add("list-group-item-action");
    },
    maxResults: 10,
  },
  submit: false,
  events: {
    input: {
      selection: (event) => {
        const selection = event.detail.selection.value;
        autoCompleteJS.input.value = selection;
      },
    },
  },
});

JavaScriptのコードの解説

AnnictAPIを叩きに行く

まずは前段部分のAnnictのAPIを叩く部分になります。
今回は検索キーワードが含まれているタイトルのみ取得したいので、用意されているAPIのパラメータの中から「filter_title」というパラメータに検索キーワードを入れてAPIを叩きにいきます。

script.js
// API config
const api = "https://api.annict.com/v1/works";

const token = "ご自身のTOKENを入れて下さい";

ここの部分ではAnnictのAPIと発行したトークンを記述します。

script.js

const annictFetchData = async (query) => {
  const params = {
    filter_title: query,
  };
  const queryString = new URLSearchParams(params).toString();
  const urlWithParams = `${api}?${queryString}&access_token=${token}`;

  const response = await fetch(urlWithParams);
  const data = await response.json();
  return data.works; // 作品のリストを返す
};

次に用意したAPIのURLとトークンを使用して、APIを叩きにいきます。

const params = {
    filter_title: query,
  };
const queryString = new URLSearchParams(params).toString();
const urlWithParams = `${api}?${queryString}&access_token=${token}`;

ここのquery引数には、インプットに入れたキーワードが入ってきます。
そのあとはparamsをクエリ文字列に変換して、URLを構築しています。

  const response = await fetch(urlWithParams);
  const data = await response.json();
  return data.works; // 作品のリストを返す

残りは構築したURLを元にfetch関数でAPIを叩き、JSON形式に変換後、レスポンスデータ内のworks(検索候補として返ってきた作品リスト)を返しています。

オートコンプリート機能

最後に後段のオートコンプリートの部分となります。
こちらは設定が主になりますので、用意したAPIを叩きに行くannictFetchData関数の使用箇所のみ解説します。

script.js
// autoComplete.js
const autoCompleteJS = new autoComplete({
  name: "autoComplete",
  selector: "#autoComplete",
  wrapper: true,
  data: {
    src: async (query) => {
      const source = await annictFetchData(query);
      return source.map((work) => work.title);
    },
    cache: false,
  },
  placeHolder: "検索クエリを入力してください...",
  debounce: 100, // Milliseconds value
  searchEngine: "loose",
  resultsList: {
    render: true,
    container: (source) => {
      source.setAttribute("id", "autoComplete_list");
      source.classList.add("list-group");
    },
  },
  resultItem: {
    highlight: true,
    content: (data, source) => {
      source.innerHTML = data.match;
      source.classList.add("list-group-item");
      source.classList.add("list-group-item-action");
    },
    maxResults: 10,
  },
  submit: false,
  events: {
    input: {
      selection: (event) => {
        const selection = event.detail.selection.value;
        autoCompleteJS.input.value = selection;
      },
    },
  },
});
data: {
    src: async (query) => {
      const source = await annictFetchData(query);
      return source.map((work) => work.title);
    },
    cache: false,
}
  1. データソース関数の設定:
    data: { src: async (query) => { ... } } は、オートコンプリート機能に対して、ユーザーが入力フィールドに何か入力した際に呼び出される非同期関数を設定しています。この関数は、ユーザーの入力(query)を引数として受け取ります。

  2. APIリクエストの実行:
    const source = await annictFetchData(query); は、ユーザーの入力を引数としてannictFetchData関数(AnnictのAPIを叩く関数)を呼び出し、APIからの応答を待機します。annictFetchDataは、指定された検索クエリに基づいてAnnict APIを叩き、結果を取得します。

  3. データの加工と返却:
    return source.map((work) => work.title); は、APIから取得したデータ(作品のリスト)を加工しています。ここでは各作品オブジェクトのtitleプロパティを取り出し、それらのタイトルのみの配列を生成しています。この配列がオートコンプリートの候補として表示されます。

  4. キャッシュの設定:
    cache: false は、オートコンプリート機能のキャッシュを無効にする設定です。これにより、同じ検索クエリに対しても毎回APIへのリクエストが行われることを意味します。

まとめ

今回は外部APIを使用してオートコンプリート機能の作成を行いました。
AutoComplete.js使用しての作成でしたが、初めて使うライブラリとAPIを組み合わせて、こういった機能が実装できるのは驚きでしたし、勉強にもなりました。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?