2008年02月03日02:06
さあ、今日も元気にZAPA先生のマッシュアップ講座。もうみなさまにも完全に馴染んだと思うので、とっとと進んじゃうけど、良いよね。
答えは、聞かない。
前回:相変わらずマッシュアップやってます〜
今日見ていくのは、第3回の後半です。
その前に、簡単にマッシュアップ講座第3回の前半の内容と、後半に何をやっていくのかをまとめときます。
<まとめ>
ライブドアお天気のXMLを、震える手でリクエストする小汚いおっさん、afiliate。
くれてやるから、おととい来やがれと言わんばかりの勢いでXMLを投げ返すAPI。
投げ返されたXMLをじっと見つめ、迷子の子猫のように途方に暮れるafiliateを見て、
simplexml_load_fileを使えばいいと思うよ、とつぶやくZAPA。
ZAPAのつぶやきで我に返ったafiliateは、いち早くPHP5に切り替わったさくらインターネットのレンタルサーバーで、ZAPA型決戦兵器「simplexml_load_file」を使用。XMLを完全撃破するのであった。
続く後半戦、旧世界の遺物と化しつつあるPHP4に対峙するafiliate。
しかし、ZAPA型決戦兵器「simplexml_load_file」は、PHP4に対し、その力を発揮できないという衝撃の事実が明らかとなる。
抗えない予定調和を前にして、満を持して新・超絶決戦兵器「正規表現」を送り込むZAPA。
これで完全に第3回マッシュアップ講座を終結できると確信したZAPAの予想を覆し、afiliateは混乱したまま、その場に立ち尽くしてしまうのであった。
果たして、afiliateの運命は・・・
</まとめ終了>(敬称略)
わかりにくいまとめはさておき、ZAPA先生のマッシュアップ講座第3回の後半では、PHP4でもXMLを解析できるような解説がされています。
「正規表現」というのが使ってあるんですが、これが難しいんですよ、私には。
前にも一度本で読んだ時に「正規表現」で混乱して、壁にぶち当たりました。
結局、完全に理解する事は出来ませんで、放置していました。
しかし、そのままで終わるのも進歩がないので、ZAPA先生が今回紹介して下さっているものがどういう処理をしているのかというところを見てみました。
最初に、file_get_contents関数というのが使ってあります。
これは「ファイルを読みこんで、全体を文字列で返す」という関数です。
file_get_contents関数で、まずはXMLを文字列にしちゃうわけです。
そして、preg_match_allという関数が使用されているのですが、これは「与えられた文字列を検索し、配列で返す」という関数みたいです。
つまり、
XML → 文字列にしちゃえ → 配列にしちゃえ → 必要なところを取り出しちゃえ。
というところを、この第3回の後半で学ぶらしいです。
しかし、preg_match_all関数がどういう処理をしているのかが全く見えてきません。
どういう配列を作っているのか?というところが特にわかりにくいです。
そういうわけで、preg_match_all関数がどういう配列を作っているのか、「配列界のお宅拝見」とも言われるprint_r関数を用いて、どういう配列を作っているのか調べるコードを書いてみました。
<サンプルコード:array.php>
<?php
$str = "タイトル:アフィリエイトは儲かんないってば<url>http://afiliate.livedoor.biz</url>というブログを紹介しますね。<description>哀愁漂う小汚いおっさんが儲からなくても涙目でがんばるブログです。</description>以上です。名残惜しいですが、紹介終わりますね。";
preg_match_all('@<url>(.*?)</url>.*?<description>(.*?)</description>@s',$str,$match, PREG_SET_ORDER);
print_r($match);
echo "<br />";
echo "<br />";
echo $match[0][1];
echo "<br />";
echo $match[0][2];
?>
<実行結果>
Array ( [0] => Array ( [0] => http://afiliate.livedoor.bizというブログを紹介しますね。哀愁漂う小汚いおっさんが儲からなくても涙目でがんばるブログです。 [1] => http://afiliate.livedoor.biz [2] => 哀愁漂う小汚いおっさんが儲からなくても涙目でがんばるブログです。 ) )
http://afiliate.livedoor.biz
哀愁漂う小汚いおっさんが儲からなくても涙目でがんばるブログです。
注目すべきは、実行結果の最初です。
これは、print_r関数でさらされた配列の中身です。
が、しかし、なんだこの2階層の配列は。
私が大家さんだとすると、[0]という名前をつけた一軒家の物件を田中さん(仮名)に貸していたら、驚いた事に田中さん(仮名)は、家の中を3つに分割して、他の人に貸し出していたのです!
それぞれの部屋に[0]、[1]、[2]と名前までつけていました。
部屋の用途はこんな感じです。
[0]・・・正規表現でぶっこ抜かれた家族連れの鈴木さん一家(仮名)が集まる部屋。
[1]・・・最初の正規表現で抜き出された鈴木さん(仮名)パパの部屋
[2]・・・次の正規表現で抜き出された鈴木さん(仮名)ママの部屋
通常の配列は一階層なので、キーを指定して$array[1]とだけ書けば、呼び出せます。
(参考:電脳コメンテーター・ヤマダサマノゴユウジン)
しかし、このような配列の構造で、鈴木さんのパパを呼び出そうとすると、私の一軒家物件[0]の、部屋番号[1]と指定することで、ようやく鈴木さん(仮名)パパを呼び出すことができます。
それをechoで表示すると下記のようになります。
echo $match[0][1];
出来上がった配列は、そういうイメージに出来上がっていると思っていいみたいです。
詳しくpreg_match_all関数の中身を見てみます。
preg_match_all('@<url>(.*?)</url>.*?<description>(.*?)</description>@s',$str,$match, PREG_SET_ORDER);
「$str」という文字列を、「$match」という配列にしてしまえという命令文のようです。
シングルクォーテーションとシングルクォーテーションで囲まれた部分が、正規表現みたいなのですが、
・<url>と、</url>で囲まれた部分
・<description>と、</description>で囲まれた部分
に分かれています。
配列$matchの最初の部屋、$match[0][0]には、正規表現で抜き出されたものが全て詰め込まれています。
$match[0][1]には、<url>と、</url>で囲まれた部分が詰め込まれています。
$match[0][2]には、<description>と、</description>で囲まれた部分が詰め込まれています。
よく見ると、$match[0][0]には、$match[0][1]と$match[0][2]の間の部分の文字列も含まれていますね。
preg_match_all関数の詳しい働きとか細かい事はよくわかりません。
特に、@と@sとか、PREG_SET_ORDERの意味とか。
わかりませんが、こういう風に配列にセットされているということがわかれば、使う事はできそうです。
そういう目で、ZAPA先生が書かれたコードをみてみましょう。
preg_match_all('@<title>(.*?)</title>.*?<description>(.*?)</description>.*?<image>.*?<title>(.*?)</title>.*?<url>(.*?)</url>.*?</image>.*?<temperature>.*?<max>.*?<celsius>(.*?)</celsius>.*?</max>.*?<min>.*?<celsius>(.*?)</celsius>.*?</min>.*?</temperature>@s', $buf, $match, PREG_SET_ORDER);
$bufという文字列を、$matchという配列にしなさい、という命令のようです。
で、配列の中身は以下のようになるようです。
$match[0][1]・・・ <title>(.*?)</title>
$match[0][2]・・・ <description>(.*?)</description>
$match[0][3]・・・ <title>(.*?)</title>(<image>内)
$match[0][4]・・・ <url>(.*?)</url>(<image>内)
$match[0][5]・・・
?<celsius>(.*?)</celsius>(<temperature>、<max>内)
$match[0][6]・・・
?<celsius>(.*?)</celsius>(<temperature>、<max>内)
$match[0][3]〜$match[0][6]は複雑な構造になっていますので、推測ですが、わかりにくくなったら、print_r関数で調べればいいような気もします。
一応、preg_match_all関数でもイケるような気がしてきした。
しかし、よく考えると、以前のマッシュアップ講座で出てきたXML_RSSでもイケるんじゃないかという気がしました。
しかも、PHP4でも、PHP5でも動いてましたし。
そういうわけで、XML_RSSでもできないものかと粘ってみたのですが、どうにもうまくいきません。
RSSにしか対応してないからでしょうか。
しょうがないので、検索してみると、XML_Serializerというものがあり、このライブラリの中に入っているXML_Unserializerというもので、なんとなくできました。
そういうわけで、XML_Unserializerを利用して、PEARの第3回の後半部分を作ってみました。
<lwws3-3.php>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>東京のお天気</title>
<style type="text/css">
<!--
body {
font-size: 14px;
}
.content {
width:300px;
}
-->
</style>
</head>
<body>
<div class="content">
<?php
function lwws($city,$day){
$req = "http://weather.livedoor.com/forecast/webservice/rest/v1";
$req .= "?city=".$city."&day=".$day;
require_once("XML/Unserializer.php");
$xml_data = file_get_contents($req);
$parser = new XML_Unserializer(array(’parseAttributes’ => true));
$parser->unserialize($xml_data);
$XML = $parser->getUnserializedData();
$ret = '<div class="lwws">';
$ret .= "<div>".$XML['title']."</div>";
$ret .= "<div><img src=\"".$XML['image']['url']."\" alt=\"".$XML['image']['title']."\"></div>";
$ret .= "<div>".$XML['description']."</div>";
$ret .= "<div>最高気温".$XML['temperature']['max']['celsius']."度</div>";
$ret .= "<div>最低気温".$XML['temperature']['min']['celsius']."度</div>";
$ret .= "</div>";
return $ret;
}
$city = "63";
$day = "tomorrow";
echo lwws($city,$day);
?>
</div>
</body>
</html>
これでいいのかなあ・・・?
できたものは、
http://net.verse.jp/hima/lwws3-3.php
PHP4.4.x:チカッパ!レンタルサーバー
http://syoboi.com/test/lwws3-3.php
PHP 5.2.x:さくらインターネット
不安を残しつつ、第3回終了。

アフィリエイトは儲かんないってば
