Yahoo!デベロッパーネットワークについて質問です。

データ内のマッチしたクエリー数(totalResultsAvailabl)を
printするというスクリプトを作ってください。

なお回答にはそのスクリプトが何を意味するか、
//を用いてできるだけ丁寧に説明していただけると幸いです。

質問者はまだ勉強を初めて間がないので、
回答は初心者にもわかるようご配慮くださいますようお願いします。

以上、よろしくお願いします。

回答の条件
  • URL必須
  • 1人2回まで
  • 登録:2008/02/09 20:45:27
  • 終了:2008/02/11 00:56:45

回答(2件)

id:yoneto164 No.1

ヨネちゃん回答回数813ベストアンサー獲得回数942008/02/10 16:05:15

ポイント50pt

質問意味がよく分からないのですが、

PHPで以下のような感じのものでしょうか。

<?php
$query ="検索";//クエリを指定
$id ="adi_id";//アプリケーションIDを指定
$data = file("http://api.search.yahoo.co.jp/WebSearchService/V1/webSearch?appid=".$id.".&query=".urlencode($query));//XMLファイルを取得
echo "<p>\"".$query."\" をクエリとした場合の結果</p>";
foreach ($data as $line) {//XMLを1行づつ$lineに代入
	if (strpos($line, "totalResultsAvailable") != false) {//totalResultsAvailableが存在した場合
		$line = ereg_replace(".*totalResultsAvailable=\"","",$line);//目的の数値以前の文字を削除
		$ans = ereg_replace("\".*","",$line);//目的の数値以降の文字を削除
		echo "<p>".$ans."</p>";//数値を表示
	}
}
?>

http://acappella.cc/test/yahoodeveloper/

当方のサーバは実行できる関数が制限されてるので、

実際はもっとスマートな記述もあります。

id:taroemon

ご回答ありがとうございます。

参考になりました。


下記の質問にコメントを複数いただきましたので、

気持ちだけポイントを上乗せさせていただきます。

http://q.hatena.ne.jp/1202577328

少ないですがお受け取りください。

2008/02/11 00:55:23
id:tobeoscontinue No.2

tobeoscontinue回答回数213ベストアンサー獲得回数532008/02/10 21:03:30

ポイント100pt

Yahoo!デベロッパーネットワークについて質問でクエリー数を表示するということなのでウェブ検索Webサービスのことと思います。実装するには幾つかの関数にした方がいいだろうと思いクラスにしてみました。クラスはphp4とphp5では若干違うのでエラーがあるかもしれません(php4で作成)。


Yahooのこのサービスでは文字エンコードとしてUTF-8を要求しています。このクラスでは文字エンコードには考慮していないので前もってUTF-8である必要があります。必要なら文字変換して下さい。


基本的な処理は

1:リクエストに応じてURLを構築して

2:そのURLでアクセスしてxmlファイルを入手し

3:そのxmlファイルをパースして目的のデータを取り出す

の三つです。少し面倒なのはxmlファイルを入手する部分と、xmlファイルをパースする部分です。


phpではリモートにあるファイルでもローカルにあるファイルのように扱えますがallow_url_fopenがoffになっているとそれが使えません。サーバーによってはallow_url_fopenがoffになっているようでphpのバージョンによってはPHP_INI_SYSTEMとなっているので変更する権限が与えられていないかもしれません。その場合はcurlを使うようです(DreamHostでは推めているような)。


phpには幾つかxmlを処理できるものがありますが環境によってはどれが使えて、どれが使えないとかあると思います。php5ならSimpleXML関数が便利そうです。今回はXML パーサ関数を使っています。SimpleXML関数やDOMを使ったものはYahooのSDK(ソフトウエア開発キット)ダウンロードにphpのコードがあります。またhttp://www.pahoo.org/e-soul/webtech/php06/php06-02-01.shtmなども参考になると思います。


$yahoo = new Yahoo_Web_Search('アプリケーションID');
$request = array('query'=>'はてな'
/*                ,'type'=>'all'
                  ,'results'=>50
                  ,'start'=>1
                  ,'format'=>'any'
                  ,'adult_ok'=>0
                  ,'similar_ok'=>0
                  ,'language'=>'ja'
                  ,'country'=>'jp'
                  ,'site'=>'www.yahoo.co.jp'  */
);
$xml = $yahoo->Request($request);
if ($xml) {
  $xml = $xml['ResultSet'];
  echo 'totalResultsAvailable='.$xml['totalResultsAvailable'].'<br>';
  if (array_key_exists(0, $xml['Result']))
    foreach ($xml['Result'] as $item) {
      echo $item['Title'].'<br>';
      echo $item['Url'].'<br>';
      echo $item['Summary'].'<br><br>';
    }
  else {
    $item = $xml['Result'];
    echo $item['Title'].'<br>';
    echo $item['Url'].'<br>';
    echo $item['Summary'].'<br><br>';
  }
  echo $yahoo->Credit();
}

使いかたは

$yahoo = new Yahoo_Web_Search('アプリケーションID');

で自分のアプリケーションIDを指定してクラスを生成します。

次に

$request = array('query'=>'はてな'

/* ,'type'=>'all'

,'results'=>50

,'start'=>1

,'format'=>'any'

,'adult_ok'=>0

,'similar_ok'=>0

,'language'=>'ja'

,'country'=>'jp'

,'site'=>'www.yahoo.co.jp' */ );

でリクエストを配列で指定します。名前はYahooのリクエストパラメータ名と同じにする必要があります。

$xml = $yahoo->Request($request);

が処理の中心で$requestからURLを構築してYahooにアクセスしてxmlファイルを取り込み、パースして、その結果を配列で返します。その構造はprint_r($xml)として確認してみてください。

if ($xml) {

で$xmlが空でないなら正常と判断していますが、実際は十分でないかもしれません。エラーの場合でもxmlファイルは返るようなのでエラーでも$xmlが空でないかもしれません。

$xml['Result']はちょっと問題有りで1個の場合と2個以上では配列の構造が違っています。そのため少し冗長です。

最後に

echo $yahoo->Credit();

でクレジットを表示しています。

class Yahoo_Web_Search
{
  var $YAHOO_URL;
  var $SERVICE = array('Web'=>'web', 'Image'=>'image',
                          'Video'=>'video', 'Assist'=>'webunit');
  function Yahoo_Web_Search($app_id, $service='Web') {
    $this->YAHOO_URL = 'http://api.search.yahoo.co.jp/'.$service.
                          'SearchService/V1/'.$this->SERVICE[$service].'Search'.
                          '?appid='.$app_id;
  }
  function Request($request) {
    $url = $this->YAHOO_URL.$this->_querynize($request);
    return $this->_XML_parse($this->_get_curl($url));
  }
  function Credit() {
    return '<!-- Begin Yahoo! JAPAN Web Services Attribution Snippet -->
<span style="margin:15px 15px 15px 15px"><a href="http://developer.yahoo.co.jp/about">Webサービス by Yahoo! JAPAN</a></span>
<!-- End Yahoo! JAPAN Web Services Attribution Snippet -->';
  }
  function _XML_parse($file) {
//    echo $file."\n<br>\n<br>\n<br>";
    $xp = xml_parser_create();
    xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0);
    xml_parse_into_struct($xp,$file,$vals,$index);
    xml_parser_free($xp);
    unset($file, $index, $xp);

    $stack = array();
    $value = array();
    foreach ($vals as $target) {
      if (isset($target['type'])) {
        $name = $target['tag'];
        switch ($target['type']) {
        case 'open':
          array_push($stack, $value);
          $value = isset($target['attributes']) ? $target['attributes'] : array();
          break;
        case 'complete';
          $value["$name"] = $target['value'];
          break;
        case 'close':
          $prev = array_pop($stack);
          if (!isset($prev[$name]))
            $prev[$name] = $value;
          else {
            if (!array_key_exists(0, $prev[$name])) {
              $copy = $prev[$name];
              $prev[$name] = array($copy);
            }
            $prev[$name][] = $value;            
          }
          $value = $prev;
    }  }  }
    return $value;
  }
  function _get_curl($url) {
//  echo "URL=".$url.'<br>';
    if (ini_get('allow_url_fopen'))
      return file_get_contents($url);

    $ch = curl_init($url);
    curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
    $file_contents = curl_exec($ch);
    curl_close($ch);
    return $file_contents;
  }
  function _querynize($query) {
    $q = '';
    foreach($query as $key => $value)
      $q .= '&'.$key.'='.urlencode($value);
    return $q;
  }
};

function Yahoo_Web_Search($app_id, $service='Web')

リクエストURLの途中までを構築します。文字の連結だけなので問題はないでしょう。


function Request($request)

$url = $this->YAHOO_URL.$this->_querynize($request);

でリクエストパラメータを入れた完全なURLを作成します。

$this->_get_curl($url)

で$urlへアクセスしてxmlファイルを取り出します。その内容が文字列として返されます。

return $this->_XML_parse();

でパースして配列にしてreturnで返します。


function Credit()

クレジット表示用の文字列を返します。そんだけ。


function _XML_parse($file)

$fileはxmlファイルの文字列です。これをパースします。

$xp = xml_parser_create();

xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0);

xml_parse_into_struct($xp,$file,$vals,$index);

xml_parser_free($xp);

この時点で$valsにはパースされた内容が配列として格納されています。totalResultsAvailable程度であればこの時点でも$valsからアクセスできるのですがフラットな状態なので'Result'のような要素にアクセスするには面倒です。そこで更に階層をもった配列に再構築します。

unset($file, $index, $xp);

は使わない変数を宣言しているだけでしなくてもいいのですが。


再構築の部分は試行錯誤の産物なのでうまく説明できず。たぶん問題有。特に'Result'のように要素が1個の場合と2個以上の場合で配列の構造が違うのは問題だとは認識しているのですが。できればDOMやSimpleXMLなどの別の実装を考慮した方がいいかもしれません。


function _get_curl($url)

単にfile_get_contents()で用は足りるのですがallow_url_fopenがoffの場合、使えないのでその場合はcurlを使って入手するようにしています。


function _querynize($query)

$queryは配列でkey=>valueで登録されている必要があります。それを&key=valueが結合された文字列として返します。この文字列はURLの一部として使われるのでvalueの値はurlencode()でエンコードしています。

id:taroemon

ご回答ありがとうございます。

これほど丁寧にご回答いただき恐縮です。

質問者は初心者ですので、一見では全てを理解できませんでしたが

これから一文一文調べながら理解していこうと思います。

2008/02/11 00:54:12
  • id:tobeoscontinue
    たくさんのポイントありがとうございます。

    やはり$xml['Result']の要素数によって配列の構造が違うというのはきれいでないので例外的な処理になりますがfunction _XML_parse()にあるcase 'close':の部分を下記のように変更したいと思います。
     $prev = array_pop($stack);
     if (!isset($prev[$name])) {
      if ($name == 'Result') $prev[$name] = array($value);
      else $prev[$name] = $value;
     } else {
    // if (!array_key_exists(0, $prev[$name])) {
    //  $copy = $prev[$name];
    //  $prev[$name] = array($copy);
    // }
      $prev[$name][] = $value;
     }
     $value = $prev;

    注釈の部分は必要ないので削除してもいいのですがxmlの内容によっては必要になるのかもしれないので注釈としています。
    こうすることで$xml['Result']の内容は常に配列となるので表示する部分は
     foreach ($xml['Result'] as $item) {
      echo $item['Title'].'<br>';
      echo $item['Url'].'<br>';
      echo $item['Summary'].'<br><br>';
     }
    だけでokになります。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません