• 作成日:

【JavaScript】Wikipediaの情報をAPIを使って非同期で取得する方法- asyncとawaitを学ぶ

【JavaScript】Wikipediaの情報をAPIを使って非同期で取得する方法- asyncとawaitを学ぶ

今回はJavaScriptでwikipediaの情報をAPIを使って非同期で取得する方法について説明します。

前提条件は以下です。

  • 同期処理と非同期処理について理解している
  • Promise、async/awaitについて理解している
  • MediaWiki APIを使う

説明する環境は以下です。

  • macOS Catalina v10.15.5
  • Visual Studio Code v1.57.0
この記事の目次

Wikipediaの情報をAPIを使って非同期で取得する方法

Wikipediaの情報はMediaWiki APIを使うことで取得できます。以下のデモサイトでは検索したワードから関連した情報をWikipediaから45件取得しています。

たとえば「バナナマン」と検索すれば以下のように関連した情報が出てきます。出てきた情報はWikipediaのそれぞれの詳細ページへリンクしています。

HTMLで書くこと

HTML構造は以下の通り。input要素に入力したワードを使ってWikipediaから情報を取得し、クラス名p-wikipedia__bodyの中に表示させます。

<div class="p-wikipedia">
   <div class="p-wikipedia__inner">
      <h3 class="p-wikipedia__heading">Wikipediaで検索する</h3>
          <div class="p-wikipedia__search">
              <input id="js-wikipedia-input" type="text" value="" placeholder="検索ワード">
              <button id="js-wikipedia-button" type="button">検索</button>
          </div>
     <div class="p-wikipedia__body" id="js-wikipedia-body"></div>
   </div>
 </div>

JavaScriptで書くこと

JavaScriptに書くコードは以下。後ほど細かく説明していきます。

(() => {
 
  const wikiInput = document.getElementById("js-wikipedia-input"); //input部分
  const wikiButton = document.getElementById("js-wikipedia-button"); //button部分
  const wikiBody = document.getElementById("js-wikipedia-body"); //表示させるエリア

  const wikiFetch = async (inputValue) => { //asyncで非同期処理だと宣言する
    const fetchValue = fetch(`https://ja.wikipedia.org/w/api.php?format=json&action=query&origin=*&list=search&srlimit=45&srsearch=${inputValue}`, {
      method: "GET"
    })
      .then((value) => {
        return value.json(); //wikipediaからのデータをJSON形式に変換
      })
      .catch(() => {
        alert("wikipediaにうまくアクセスできないようです、、");
      });

    const valueJson = await fetchValue; //非同期処理を実行
    const valueTargets = valueJson.query.search; //必要な情報が入っている配列を取得

    if (!valueTargets.length) {
      const wikiNull = document.createElement("p");
      wikiNull.classList.add("p-wikipedia__null");
      wikiNull.textContent = "検索したワードはヒットしませんでした。";
      wikiBody.appendChild(wikiNull);
    } else {
      const elemWrap = document.createElement("div");
      elemWrap.classList.add("p-wikipedia__main");

      for (const elem of valueTargets) {
        //a要素を作ってリンク先にページIDを設定する
        const elemBlock = document.createElement("a");
        elemBlock.classList.add("p-wikipedia__block");
        elemBlock.setAttribute("target", "_blank");
        elemBlock.setAttribute("rel", "noopener noreferrer");
        const elemId = elem.pageid;
        elemBlock.setAttribute("href", `http://jp.wikipedia.org/?curid=${elemId}`);
        
        //span要素を作ってタイトルを設定する
        const elemSpan = document.createElement("span");
        elemSpan.classList.add("p-wikipedia__block-ttl");
        const elemTitle = elem.title;
        elemSpan.textContent = elemTitle;
        
        //span要素を作って更新日を設定する
        const elemSpan2 = document.createElement("span");
        elemSpan2.classList.add("p-wikipedia__block-date");
        const elemDate = elem.timestamp;
        const elemDateSlice = elemDate.slice(0, 10).replace(/-/g, ".");
        elemSpan2.textContent = "最終更新日:" + elemDateSlice;

        //作成した要素を順番に組み合わせていく
        elemWrap.appendChild(elemBlock);
        elemBlock.appendChild(elemSpan);
        elemBlock.appendChild(elemSpan2);
        wikiBody.appendChild(elemWrap);
      }
    }
  };
  
  //クリックイベントに設定している関数
  const wikiData = () => {
    wikiBody.innerHTML = ""; //一旦js-wikipedia-bodyの中を空にする
    const inputValue = wikiInput.value; //Input要素に入力されたテキストを取得
    wikiFetch(inputValue);
  };

  wikiButton.addEventListener("click", wikiData, false);
})();

JavaScriptで書いたコードを解説する

上で書いたJavaScriptのコードを分解して説明していきます。

Button要素にクリックイベントを設定する

Button要素に対してクリックイベントを設定しています。クリックされるとwikiData関数が呼ばれます。

wikiData関数では、まずクラス名js-wikipedia-bodyのエリアに余計なものがあったら消しています。そしてinput要素に入力されたテキストを変数inputValueに入れ、それをwikiFetch関数の引数としてセットしています。

const wikiData = () => {
    wikiBody.innerHTML = ""; //余計な要素を消す
    const inputValue = wikiInput.value; //input要素に打ち込まれたテキストを変数inputValueに保存
    wikiFetch(inputValue); //wikiFetch関数の引数にinputValueをセット
  };

wikiButton.addEventListener("click", wikiData, false); //クリックイベントを設定する

非同期処理でWikipediaの情報を取得する

wikiFech関数にasyncをつけて非同期処理だと宣言しています。inputValueにはinputに入力された検索ワードが入っているので、その検索ワードをWekipediaのAPIにセットします。それをfetchすることで関連情報を取得できます。

正しく取得できればthenにデータを渡して、その情報をJSON形式に変換。取得できず何かしらエラーが出ればcatchからアラートさせています。

const wikiFetch = async (inputValue) => { //asyncで非同期処理だと宣言する
    const fetchValue = fetch(`https://ja.wikipedia.org/w/api.php?format=json&action=query&origin=*&list=search&srlimit=45&srsearch=${inputValue}`, {
      method: "GET"
    })
      .then((value) => { //データが取得できればこっち
        return value.json(); //wikipediaからのデータをJSON形式に変換
      })
      .catch(() => { //取得に失敗すればこっち
        alert("wikipediaにうまくアクセスできないようです、、");
      });

    const valueJson = await fetchValue; //非同期処理を実行
    const valueTargets = valueJson.query.search; //必要な情報が入っている配列を取得
};

Wikipediaから情報が来てから処理を進めていきたいので、fetchValueはawaitをつけて非同期で実行しています。受け取ったデータをJSON形式に変えてから変数valueJsonに代入しています。

変数valueJsonをコンソールで見てみると以下のように表示されるので、query.searchでアクセスして必要な情報を変数valueTargetsに代入しています。

WikipediaのAPIの設定方法

WikipediaのAPIで使う基本的なURLは以下です。
このURLに取得したい情報にあわせたパラメーターをつけていくことになります。

http://ja.wikipedia.org/w/api.php?

パラメーターについては以下の記事をどうぞ。

今回は以下のように設定しています。
searchした単語に対して45件取得する設定です。

https://ja.wikipedia.org/w/api.php?format=json&action=query&origin=*&list=search&srlimit=45&srsearch=${inputValue}

重要なのがorigin=*で、これがないと以下のようにCORSエラーが起きてしまい、情報が取得できません。

取得した情報をサイトに表示させる

もし取得した情報が空であれば(配列が空であれば)、「検索したワードはヒットしませんでした」と表示させて、情報があれば配列の中をループして最大45件を表示させます。

if (!valueTargets.length) { //配列が空なら
      const wikiNull = document.createElement("p");
      wikiNull.classList.add("p-wikipedia__null");
      wikiNull.textContent = "検索したワードはヒットしませんでした。";
      wikiBody.appendChild(wikiNull);
    } else { //配列の中があれば
      const elemWrap = document.createElement("div");
      elemWrap.classList.add("p-wikipedia__main");

      for (const elem of valueTargets) {
        //a要素を作ってリンク先にページIDを設定する
        const elemBlock = document.createElement("a");
        elemBlock.classList.add("p-wikipedia__block");
        elemBlock.setAttribute("target", "_blank");
        elemBlock.setAttribute("rel", "noopener noreferrer");
        const elemId = elem.pageid; //ページIDを代入
        elemBlock.setAttribute("href", `http://jp.wikipedia.org/?curid=${elemId}`);
        
        //span要素を作ってタイトルを設定する
        const elemSpan = document.createElement("span");
        elemSpan.classList.add("p-wikipedia__block-ttl");
        const elemTitle = elem.title; //タイトルを代入
        elemSpan.textContent = elemTitle;
        
        //span要素を作って更新日を設定する
        const elemSpan2 = document.createElement("span");
        elemSpan2.classList.add("p-wikipedia__block-date");
        const elemDate = elem.timestamp; //更新日を代入
        const elemDateSlice = elemDate.slice(0, 10).replace(/-/g, ".");
        elemSpan2.textContent = "最終更新日:" + elemDateSlice;

        //作成した要素を順番に組み合わせていく
        elemWrap.appendChild(elemBlock);
        elemBlock.appendChild(elemSpan);
        elemBlock.appendChild(elemSpan2);
        wikiBody.appendChild(elemWrap);
 }

取得できる情報の中にはpageidがあります。このidを以下の${elemId}に設定することで、それぞれのページリンクを作れます。

http://jp.wikipedia.org/?curid=${elemId}

これでデモページのように入力したワードに関連した情報を表示させることができます。

おわりに

今回はJavaScriptでwikipediaの情報をAPIを使って非同期で取得する方法について説明しました。WikipediaのAPIに設定したパラメーターを変えれば記事の要約や記事に使われている画像も取得できるので試してみてください。

無料で使えるAPIといえば、郵便番号を打つと住所が取得できる「zipcloud」が有名ですね。コンタクトフォームに使えます。

非同期処理に使うPromiseについては以下の記事を参考にどうぞ。

asyncとawaitについては以下の記事をどうぞ。