wikipedia apiを直接たたいてXMLを取得する

phpのsimplexml_load_fileを使ったサンプルコードを書いていただけると助かります。
URLは以下でキーワード(カテゴリ)は「海軍兵学校卒業生一覧_(日本)」です。

この質問は、
http://q.hatena.ne.jp/1329309002
と関連した質問です。

http://ja.wikipedia.org/w/api.php?action=query&prop=revisions&rvprop=content&format=xml&titles=%E6%B5%B7%E8%BB%8D%E5%85%B5%E5%AD%A6%E6%A0%A1%E5%8D%92%E6%A5%AD%E7%94%9F%E4%B8%80%E8%A6%A7_%28%E6%97%A5%E6%9C%AC%29

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2012/02/23 17:54:44
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:tobeoscontinue No.2

回答回数220ベストアンサー獲得回数59

ポイント150pt
<?php
require_once "Text/Wiki/Mediawiki.php";
function translate_mediawiki($text) {
  $wiki= new Text_Wiki_Mediawiki();
  $wiki->setFormatConf('Xhtml','translate',HTML_SPECIALCHARS);
  return $wiki->transform($text,'xhtml');
}

function simplexml_wikipedia($keyword) {
  $url="http://ja.wikipedia.org/w/api.php?action=query&prop=revisions&rvprop=content&format=xml&titles=".urlencode($keyword);
  ini_set("user_agent", "php/5.3.3");
  $xml = simplexml_load_file($url);
  $txt = translate_mediawiki(implode($xml->xpath('//rev')));
   return simplexml_load_string("<?xml version='1.0'?>\n<api>".$txt."</api>");
}
$xml = simplexml_wikipedia("海軍兵学校卒業生一覧_(日本)");
foreach ($xml->xpath('//h3 | //ul/li') as $li) {
		echo is_array($li) ? implode($li) : $li."\n";
}
?>

phpのsimplexml_load_fileからja.wikipedia.orgにアクセスすると403で何故か叱られるので
ini_set("user_agent", "php/5.3.3");
でUser_Agentを設定している。環境によっては必要ないかも。
xmlのrevタグに記述されているがwiki記法のままなのでText_Wiki_Mediawikiでxhtmlに変換する。(xmlに出来ればいいのだが)
次にxhtmlをxmlと騙してsimplexml_load_stringで格納する。ただかなり無理がある。
必要な情報がどれか分からないがh3とul/liのものを抜き出してみる。
wikipedia apiを直接たたくのは無理があるように思う。

<?php
function simplexml_zubapita_t($keyword) {
  $url="http://ws.zubapita-t.com/index.php?&keywords=".urlencode($keyword)."&type=xml&size=full";
  return simplexml_load_file($url);
}
$xml = simplexml_zubapita_t("海軍兵学校卒業生一覧_(日本)");
//foreach ($xml->chapters->chapter->sub->chapter as $chapter) {
foreach ($xml->xpath('//sub/chapter') as $chapter) {
  echo $chapter->title."\n".
       $chapter->article."\n\n";
}
?>

サイトに依存することになるがhttp://www.zubapita.jp/2009/03/30/wikipedia_search_api/を使ったほうが簡単のように思う。
ライセンスはGPLだがソースも公開されている。

id:kohhi

ご回答ありがとうございました。
>wikipedia apiを直接たたくのは無理があるように思う
確かにそうですね。
ご紹介いただいたパーサー勉強してみます。

2012/02/23 17:45:39

その他の回答1件)

id:shell631 No.1

回答回数9ベストアンサー獲得回数3

ポイント150pt

以下のスクリプト(UTF-8で保存してください)をお試しください。
関数getWikiに見出し語$keywordを渡すと、XML文がそのまま返るようになっています。

途中、ZIP解凍のための一時処理ファイルを作るので、スクリプトのあるディレクトリを書き込み可能にしていただくか、定数ZIPFNAMEの値を書き込み可能なディレクトリ名を含むファイル名に変更してください。

<?php
define('ZIPFNAME', '_TMP_.ZIP');        //一時処理用ファイル名

//メインプログラム
$keyword = '海軍兵学校卒業生一覧_(日本)';   //検索したい見出し
$xml = getWiki($keyword);
echo $xml;  //取得したXML

// Wikipedia APIからXML取得
function getWiki($keyword) {
    $host = 'ja.wikipedia.org';
    $query = urlencode($keyword);
    $path = '/w/api.php?action=query&prop=revisions&rvprop=content&format=xml&titles=' . $query;

    $request  = "POST {$path} HTTP/1.1\r\n";
    $request .= "Host: {$host}\r\n";
    $request .= "User-Agent: Mozilla/5.0\r\n";
    $request .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
    $request .= "Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n";
    $request .= "Accept-Encoding: gzip, deflate\r\n";
    $request .= "Connection: keep-alive\r\n";
    $request .= "\r\n";
    $request .= "\r\n";

    $fp = fsockopen($host, 80);
    if (! $fp)   return FALSE;
    fputs($fp, $request);
    //ヘッダ取得
    $len = 0;
    $flag_zip = FALSE;
    while (! feof($fp)) {
        $str = trim(fgets($fp));
        if ($str == '') {
            break;
        } else if (preg_match("/Content-Length: ([0-9]+)/iu", $str, $arr) > 0) {
            $len = $arr[1];
        } else if (preg_match("/Content-Encoding: gzip/iu", $str, $arr) > 0) {
            $flag_zip = TRUE;
        }
    };
    //コンテンツ取得
    $contents = '';
    while (! feof($fp))     $contents .= fread($fp, 1000);
    fclose($fp);

    $xml = '';
    if ($flag_zip) {
        file_put_contents(ZIPFNAME, $contents);
        $fp = gzopen(ZIPFNAME, 'r');
        if (! $fp)  break;
        while (! gzeof($fp))    $xml .= gzread($fp, 1000);
        gzclose($fp);
        unlink(ZIPFNAME);
    } else {
        $xml = $contents;
    }

    return $xml;
}
?>
id:kohhi

早速お返事いただきありがとうございました。
動きました。

2012/02/23 17:41:44
id:tobeoscontinue No.2

回答回数220ベストアンサー獲得回数59ここでベストアンサー

ポイント150pt
<?php
require_once "Text/Wiki/Mediawiki.php";
function translate_mediawiki($text) {
  $wiki= new Text_Wiki_Mediawiki();
  $wiki->setFormatConf('Xhtml','translate',HTML_SPECIALCHARS);
  return $wiki->transform($text,'xhtml');
}

function simplexml_wikipedia($keyword) {
  $url="http://ja.wikipedia.org/w/api.php?action=query&prop=revisions&rvprop=content&format=xml&titles=".urlencode($keyword);
  ini_set("user_agent", "php/5.3.3");
  $xml = simplexml_load_file($url);
  $txt = translate_mediawiki(implode($xml->xpath('//rev')));
   return simplexml_load_string("<?xml version='1.0'?>\n<api>".$txt."</api>");
}
$xml = simplexml_wikipedia("海軍兵学校卒業生一覧_(日本)");
foreach ($xml->xpath('//h3 | //ul/li') as $li) {
		echo is_array($li) ? implode($li) : $li."\n";
}
?>

phpのsimplexml_load_fileからja.wikipedia.orgにアクセスすると403で何故か叱られるので
ini_set("user_agent", "php/5.3.3");
でUser_Agentを設定している。環境によっては必要ないかも。
xmlのrevタグに記述されているがwiki記法のままなのでText_Wiki_Mediawikiでxhtmlに変換する。(xmlに出来ればいいのだが)
次にxhtmlをxmlと騙してsimplexml_load_stringで格納する。ただかなり無理がある。
必要な情報がどれか分からないがh3とul/liのものを抜き出してみる。
wikipedia apiを直接たたくのは無理があるように思う。

<?php
function simplexml_zubapita_t($keyword) {
  $url="http://ws.zubapita-t.com/index.php?&keywords=".urlencode($keyword)."&type=xml&size=full";
  return simplexml_load_file($url);
}
$xml = simplexml_zubapita_t("海軍兵学校卒業生一覧_(日本)");
//foreach ($xml->chapters->chapter->sub->chapter as $chapter) {
foreach ($xml->xpath('//sub/chapter') as $chapter) {
  echo $chapter->title."\n".
       $chapter->article."\n\n";
}
?>

サイトに依存することになるがhttp://www.zubapita.jp/2009/03/30/wikipedia_search_api/を使ったほうが簡単のように思う。
ライセンスはGPLだがソースも公開されている。

id:kohhi

ご回答ありがとうございました。
>wikipedia apiを直接たたくのは無理があるように思う
確かにそうですね。
ご紹介いただいたパーサー勉強してみます。

2012/02/23 17:45:39
  • id:Cherenkov
    http://sinkinkousoku.com/wiki01.php
    これじゃないんですか?
  • id:kohhi
    Cherenkov様
    勉強不足ですいません。
    余計なリクエストしてしまいました。
    自分でやっていたのも、よく理解しておりませんでした。
    重ね重ねすいません。
     By 投稿者

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

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

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

回答リクエストを送信したユーザーはいません