2018年5月21日月曜日

Wikipedia API で、検索と本文を1度に取得する方法

Wikipedia Viewer」の続き。(前回の記事

freeCodeCampの見本のページが"extract"(本文のテキスト)というプロパティを表示しているようなので同じことをしようとしたのですが、検索結果のJSONを見てみるとextractはここに入ってこない。
extractを取得するには、最初のリクエストで検索をしてtitleなりpageidなりのリストを取得して、それを元にもう一回ページ内容を取得するAPIを呼ばないと出来なさそう…?に見えたのですが。
ありました。

Querying query results in one request
https://www.mediawiki.org/wiki/API:Page_info_in_search_results#Querying_query_results_in_one_request

「generator」という機能を使えばできる様子。





API sandbox で言うと、action=query 配下のこれ。

API Sandbox
https://en.wikipedia.org/wiki/Special:ApiSandbox#action=query&format=json&prop=extracts&list=&generator=search&exsentences=1&exlimit=10&exintro=1&explaintext=1&gsrsearch=NASA&gsrlimit=10
(上記リンクから飛ぶと、「NASA」という固定キーワードで検索する場合の設定がされているはず)

で、一度のAPIコールで取ることはできたのですが、今度はその検索結果のリストが配列ではなくオブジェクトになっている。
それを一個一個取り出して表示したい…(超初心者なのでこれでもう詰まる)
そこで参考にさせていただいたのがこちら↓

JSのObjectをforEachで処理する方法
https://qiita.com/nantekkotai/items/6c603b40ac2264e9f6f6


こうして、generatorを使って一回に書き換えてみた形がこちら↓
(まだユーザー入力を取得する部分を実装していないので、固定キーワードで検索してその結果を表示させるだけです。)

$(document).ready(function() {
  $.ajax({
    url: "//en.wikipedia.org/w/api.php",
    data: {
      action: "query",
      format: "json",
      prop: "extracts",
      list: "",
      generator: "search", // used for querying query results in one request
      exsentences: "1",
      exlimit: "10",
      exintro: 1,
      explaintext: 1,
      gsrsearch: "NASA", // Search string
      gsrlimit: "10"
    },
    type: "GET",
    dataType: "jsonp",
    success: function (data){
      
      var searchResults = data.query.pages;
      var panelsHtml = "";
      
      Object.keys(searchResults).forEach(function(pageid){ // Returned search results are objects (not an array)
        panelsHtml += 
          "<div>" 
          + searchResults[pageid].title + "</br>"
          + searchResults[pageid].extract
          + "</div>";
      });
        // Display Title & Extract
      $("#results").html(panelsHtml);
      
    }, // end success handler
    xhrFields: {
      withCredentials: false
    } 
  }); // end ajax
});

ちなみに最初に考えていた、二回APIを呼ぶ形↓

$(document).ready(function() {
  $.ajax({
    url: "//en.wikipedia.org/w/api.php",
    data: {
      action: "query", 
      format: "json", 
      list: "search", 
      srsearch: "NASA", 
      srlimit: "10" 
    },
    type: "GET",
    dataType: "jsonp",
    success: function (data){
      
      var searchResults = data.query.search;
      var pageIds = "";
      var pageIdArray = [];
      
      for (var i=0; i<searchResults.length; i++) {
        if (i!=0){
          pageIds += "|";
        };
        pageIds += searchResults[i].pageid;
        pageIdArray.push(searchResults[i].pageid);
      };
      console.log(pageIdArray);
      // 2nd Ajax call
      $.ajax({
          url: "//en.wikipedia.org/w/api.php",
          data: {
            action: "query",
            format: "json",
            prop: "extracts",
            list: "",
            pageids: pageIds,
            exsentences: "1",
            exlimit: "10",
            exintro: 1,
            explaintext: 1
          },
          type: "GET",
          dataType: "jsonp",
        success: function (data2){
          
          var pages = data2.query.pages;
          var panelsHtml = "";
          pageIdArray.forEach(function(pageId){
            panelsHtml += 
              "<div>" 
              + pages[pageId].title + "</br>"
              + pages[pageId].extract
              + "</div>";
          });
      $("#results").html(panelsHtml);
          
        }, // end 2nd success handler
        xhrFields: {
          withCredentials: false
        } 
      }); // end 2nd ajax
      
    }, // end 1st success handler
    xhrFields: {
      withCredentials: false
    } 
  }); // end 1st ajax
});

0 件のコメント:

コメントを投稿