ヤフー株式会社は、2023年10月1日にLINEヤフー株式会社になりました。LINEヤフー株式会社の新しいブログはこちらです。LINEヤフー Tech Blog

テクノロジー

「検定詳細API」を使って問題を表示してみよう!

Yahoo!みんなの検定ProjectのK.K.です。

前回、【「三国志」に関する検定を表示し、受験する】という
機能を作成するため、検定リストAPIを使うということを説明しました。

今回は、「検定詳細API」を使って、問題を表示してみましょう。

ひとまず、表示する内容を

・「三国志」のキーワードを持つ
・作成された最新の検定から
・ランダムで1問表示する

に絞ってみましょう。

では、PHPでのサンプルを使って説明していきます。
APIのレスポンスとして返ってくるXML。
これのパース方法は、PHP5では「SimpleXML関数」が強力なのですが、
PHP4でも動くPEARの「XML_Unserializer」ライブラリを使用しています。

<?php
require_once 'XML/Unserializer.php';

// みんなの検定APIの基本URL
$API_BASE_URL = 'http://cert.yahooapis.jp/MinnaCertWebService/V1/';

// APP_ID
$APP_ID = '{あなたのAPP_ID}';

// 指定するキーワード
$KEYWORD = '三国志';

// 検定一覧APIのURL(order=1:公開日の降順 amount=1:1件取得)
$LIST_API_URL = $API_BASE_URL . 'certList?' . http_build_query(
    'appid' => $APP_ID,
    'order' => 1,
    'amount' => 1,
    'keyword' => $KEYWORD
);

// 検定詳細APIのURL(get_q=2:問題情報+正解と解説を取得)
$DETAIL_API_URL = $API_BASE_URL . 'certDetail?' . http_build_query(
    'appid' => $APP_ID,
    'get_q' => 2
    'cert_id' => null
);

/* 
 *
 * XMLのパース
 *
 */

// XMLパース用クラス作成
$class_xml_uns = new XML_Unserializer(array('parseAttributes' => true));

// 検定一覧XMLのパース実行
$class_xml_uns->unserialize(file_get_contents($LIST_API_URL));

// パース結果を配列に格納
$res_list = $class_xml_uns->getUnserializedData();

これで「三国志」のキーワードを持つ最新の検定の情報を取得し、
検定に個別に割り振られている「検定ID」を抽出することができるようになりました。
/*
 * 検定の各情報を抽出
 */

// 検定の詳細を取得
$ary_cert = $res_list['Result'];

// 検定ID抽出
$cert_id = $ary_cert['CertId'];

// 検定名抽出
$cert_name = mb_convert_encoding($ary_cert['CertName'], 'EUC-JP', 'UTF-8');

// 検定のURLを抽出
$cert_url = $ary_cert['CertDetailPcUrl'];


ランダムに1問だけ表示したいですが、検定によって問題数が5問〜8問までさまざまです。
問題数を示す「QuestionCount」を抽出して、その中から何問目かをランダムで取得するようにしましょう。

// 検定の中からランダムに1問取得する
$order_number = mt_rand(1, $ary_cert['QuestionCount']);

検定IDと、何問目を取得するかを抽出できたので、
これをもとに検定詳細APIを呼び出し、パースします。

// 抽出したIDで指定した検定の詳細XMLのパース実行
$class_xml_uns->unserialize(file_get_contents($DETAIL_API_URL . $cert_id . "&order_number=" . $order_number));

// パース結果を配列に格納
$res_detail = $class_xml_uns->getUnserializedData();
$ary_detail = $res_detail['Result']['QuestionResult']['QuestionData'];

// 問題文抽出
$question_text = mb_convert_encoding($ary_detail['QuestionText'], 'EUCJP-WIN', 'UTF-8');
$question_text = str_replace("\n" ,"<br>", $question_text);

// 選択肢抽出
$choice = '';
foreach ($ary_detail['ChoicesResult']['ChoiceData'] as $ary_choice ) {
    $choice_number = $ary_choice['OrderNumber'];
    $choice_text = mb_convert_encoding($ary_choice['ChoiceText'], 'EUCJP-WIN', 'UTF-8');

    $choice .=  '(' . $choice_number . ')' . $choice_text . '<br>';
}

// 正解抽出
$answer = $ary_detail['CorrectAnswer'];

// 解説抽出
$explanation = mb_convert_encoding($ary_detail['QuestionExplanation'], 'EUCJP-WIN', 'UTF-8');
if ( $explanation == '' ) {
    $explanation = '※解説はありません';// 解説は必須ではないので空の場合あり
} else {
    $explanation = str_replace("\n", '<br>', $explanation);
}


このようにして、問題表示に必要そうな情報を取得することができました。
これを使っていろいろなことができそうですが、
とりあえずシンプルに表示だけしてみます。


/** 
 * HTML部分作成
 * とりあえず、「答えを見る」ボタンを押すと、
 * 折りたたんである答えが表示されるだけのシンプルなもの。
 */

// 問題部分のHTMLを作成
$question_html = <<<_HTML_
${cert_name}<br>
<br>
${question_text}<br>
<br>
[ 選択肢 ]<br>
${choice}

_HTML_;

// 解答部分のHTMLを作成
$answer_html = '[ 正解 ] (' . $answer .  ')<br>[ 解説 ]' . $explanation .  
    '<br><a href="' . $cert_url . '" target="_brank">ほかの問題も解いてみる</a>';

準備完了。htmlとして表示します。
<html>
 <head>
  <meta http-equiv="content-type" content="text/html;charset=utf-8">
  <title>サンプル</title>
 </head>
 <body>
  <?php echo $question_html ?>
  <form>
   <input type="button" id="answer" value="答えを見る" onClick="answerOn();">
   <script type="text/javascript">
    function answerOn() {
     var answer = '<?php echo $answer_html ?>';
     document.getElementById("result").innerHTML = answer;
    }
   </script>
  </form>
  <div id="result"></div>
 </body>
</html>

今回は1問だけランダムで取得してきましたが、全問取得したり、
複数の検定からまたいで問題を取得したりと応用できますので、
あっと驚くような使い方を期待してます。

なお、検定には「何問中何問以上で合格」といった基準や
正解数に応じて評価メッセージが設定されているものもあります。


検定の解答結果から、その評価を返す「検定受験API」も、
また紹介していこうと思います。

受けて作ってつながろう!
Yahoo!みんなの検定

こちらの記事のご感想を聞かせください。

  • 学びがある
  • わかりやすい
  • 新しい視点

ご感想ありがとうございました

このページの先頭へ