はじめまして.新入社員のjokagiです.ウノウ株式会社に入社して丁度1週間のまだ右も左も分からない新入社員です.よろしくお願いいたします.
さてみなさまよくご存じ(?)当番制のウノウラボですが,今日が私が当番だということに夕方気づいたので!!さっきネタを作りました. というか当番とかいうわりに日付が変わってしまいましたがみなさま気にせず興味のある方だけ生ぬるく読んでください.
お題
今回はServices_Photozouの公開をしようかと思ったのですが,見て楽しいものを用意できませんでした.そこで気を取り直して自分が欲しかったPEAR::Services_Technorati(以後Services_Technorati)を用いてキーワード「unoh」を検索し,その結果をSmartyでさくっとRSSとHTMLにするサンプルを作ってみました.
Technorati(テクノラティ)はブログに特化した検索などが行えるサイトです(日本サイトとしてTechnorati JAPANがあります).より詳細な情報についてはTechnorati: About Usが参考になると思います.
TechnoratiのAPI Keyの取得
今回のネタを自分のところで実験するにはAPI Keyを取得する必要があります.
API Keyの取得は残念ながらTechnorati Japanにはないようなので,本家で英語を読みながら頑張ります.
といってもTechnorati Japanでアカウントを作成していれば,http://www.technorati.com/developers/apikey.htmlにアクセスし,ログインすれば(ログイン後はさっきのURLに再度アクセスしましょう)API Keyを取得できます.
文章らしい文章は読まなくていいので簡単です.
API Keyの規約はhttp://www.technorati.com/developers/apikey.htmlにAPI Keyと合わせて記述されていますので、そちらを読むようにしてください.
※規約についてのご指摘をいただきました
とりあえず画面推移をキャプチャーしてみました. 参考にしてみてください.
Developer Centerにアクセス.右上のSign Inをクリックしてログイン.
ログイン直後の画面
パッケージの準備
今回検索結果のキャッシングにPEAR::Cache_Lite(以後Cache_Lite)を使用します. PEARの数あるウェブサービス系パッケージでは定番の組み合わせです. PEARがコマンドラインで管理できる環境なら
pear install --alldeps Cache_Lite Services_Technorati
Services_Technoratiの使い方
取り立てて難しいことはありません.staticメソッドのfactoryでインスタンスオブジェクトを生成し,それを用いて検索など情報取得をします. 下記は「unoh」で検索し,print_r()で出力をする例です.
$ php -r ' require_once "Services/Technorati.php"; $client = &new Services_Technorati( "<あなたのAPI Key>", $cache); print_r( $client->search("unoh"));' Array ( [version] => 1.0 [document] => Array ( [result] => Array ( [query] => unoh [querycount] => 556 [rankingstart] => 0 ) [item] => Array ( [0] => Array ( [weblog] => Array ( [name] => Twisted Mind [url] => http://d.hatena.ne.jp/Voluntas [rssurl] => http://d.hatena.ne.jp/Voluntas/rss [atomurl] => [inboundblogs] => 11 [inboundlinks] => 23 [lastupdate] => 2006-10-05 16:47:17 GMT ) [title] => [dojo] [excerpt] => ■[dojo] 20:13 ウノウラボ Unoh Labs: DoJoで簡単にクロスドメインAjaxを実現 http://labs.unoh.net/2006/10/dojoioscriptsrcioajax... とてもわかりやすい説明:-) 画像が出てくるのがカッコイイ。 [created] => 2006-10-06 11:13:44 GMT [permalink] => http://d.hatena.ne.jp/Voluntas/20061006#1160133224 ) [1] => Array ( [weblog] => Array ( [name] => devworks [url] => http://d.hatena.ne.jp/devworks [rssurl] => http://d.hatena.ne.jp/devworks/rss [atomurl] => [inboundblogs] => 6 [inboundlinks] => 11 [lastupdate] => 2006-10-06 12:08:18 GMT ) [title] => [Ajax]DoJoで簡単にクロスドメインAjaxを実現 [excerpt] => ■[Ajax]DoJoで簡単にクロスドメインAjaxを実現 ウノウラボ Unoh Labs: DoJoで簡単にクロスドメインAjaxを実現 XMLHttpRequestはセキュリティ上の問題から、他のドメインに対してリクエストを送ることがで... [Dojo] JavaScriptのみでクロスドメインXMLHttpRequest Kawa.net Blog(ゆうすけブログ)/ウェブリブログ 内部でiframeを使用しているようです。 技術的には非常に興味があるのですが、今は「どう業務に使おう? 」と考え中です。 [created] => 2006-10-06 01:11:58 GMT [permalink] => http://d.hatena.ne.jp/devworks/20061006/1160097118 ) (略)
はい配列が取得できました. ってことでこの配列を再構成し,Smartyに渡せば自由な形式で出力できますね. その辺りを含めて実装してみます.
Smartyを絡めて出力する
今回はRSS 2.0とHTMLを出力するようにしてみました.CLIで実行ではなくHTTPアクセスを前提にしたのでGETで引数(?type=<type>)を付加することで出力形式を切り替えます(type=xmlでRSSを,type=htmlでHTMLを出力します). ついでにCache_Liteで4時間検索結果のキャッシングを行います. これ以上ちょっとずつ実装していくとエントリが長くなるので一気にやっちゃいます. 実装はちょっとイマイチ感もありますが,ざっとこんな感じにしてみました.
index.php
<?php require_once 'Services/Technorati.php'; require_once 'Smarty.class.php'; require_once "Cache/Lite.php"; $cache_lifetime = 4 * 60 * 60; // 4時間 $type = isset($_GET['type'])? $_GET['type']: 'html'; $type = in_array($type, array('xml', 'html'))? $type: 'html'; header("Content-Type: text/$type; charset=UTF-8"); $options = array( 'cacheDir' => dirname(__FILE__).'/tmp/services_technorati/', 'lifeTime' => $cache_lifetime, 'pearErrorMode' => CACHE_LITE_ERROR_DIE ); $cache = &new Cache_Lite( $options); $client = &new Services_Technorati('<あなたのAPI Key>', $cache); $search_result = $client->search('unoh'); $feed_items = array(); foreach ($search_result['document']['item'] as $index=>$item) { $feed_item = array(); $feed_item['title'] = sprintf( '%s - %s', $item['title'], $item['weblog']['name']); $feed_item['link'] = $item['permalink']; $feed_item['permlink'] = sprintf('%d-%s', $index, md5($item['permalink'])); $feed_item['author'] = $item['weblog']['name']; $feed_item['body'] = $item['excerpt']; $feed_item['datetime'] = date( 'r', strtotime( $item['created'])); $feed_items[] = $feed_item; } $feed = array( 'encoding'=>'UTF-8', 'generator'=>'elf.no-ip.org', 'datetime'=>date('r')); $site = array(); $site['feed'] = $feed; $site['title'] = 'Topic of unoh'; $site['link'] = sprintf('http://%s%s', $_SERVER['HTTP_HOST'], $_SERVER['PHP_SELF']); $site['description'] = 'Topics about unoh searched with technorati.'; $site['language'] = 'ja'; $site['items'] = $feed_items; $smarty = &new Smarty; $smarty->template_dir = dirname( __FILE__); $smarty->compile_dir = dirname( __FILE__).'/tmp/smarty/templates_c'; $smarty->assign('site', $site); $smarty->display("feed_{$type}.tpl"); ?>
次にRSS用Smartyテンプレートです.
feed_xml.tpl
<?xml version="1.0" encoding="{$site.feed.encoding|escape:"html":"UTF-8"}" ?> <rss version="2.0" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:admin="http://webns.net/mvcb/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" > <channel> <title>{$site.title|escape:"html":"UTF-8"}</title> <link>{$site.link|escape:"html":"UTF-8"}</link> <description>{$site.description|escape:"html":"UTF-8"}</description> <dc:language>{$site.language|escape:"html":"UTF-8"}</dc:language> <generator>{$site.feed.generator|escape:"html":"UTF-8"}</generator> <lastBuildDate>{$site.feed.datetime|escape:"html":"UTF-8"}</lastBuildDate> {foreach item=item from=$site.items} <item> <title>{$item.title|escape:"html":"UTF-8"}</title> <link>{$item.link|escape:"html":"UTF-8"}</link> <content:encoded>{$item.body|escape:"html":"UTF-8"}</content:encoded> <pubDate>{$item.datetime|escape:"html":"UTF-8"}</pubDate> <guid isPermaLink="false">{$item.permlink|escape:"html":"UTF-8"}</guid> </item> {/foreach} </channel> </rss>
escapeとか入りまくりで見づらいかもしれませんが気にしないでください(ちゃんと読みたい方はエディタにでもコピペしてください).
実は恥ずかしながらRSSには精通していないのでRSS Validatorでエラーが出ない程度の内容になっています. おかしなところはコメントをいただければと思います.
ちなみにこれを書いていて気づいたのですが,いつのまにかSmartyのescape修飾で文字コードの指定ができるようになってたのですね. すばらしい.
最後はHTML用Smartyテンプレートです.
feed_html.tpl
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><?xml version="1.0" encoding="{$site.feed.encoding|escape:"html":"UTF-8"}" ?> <html lang="{$site.language|escape:"html":"UTF-8"}"> <head> <meta http-equiv="Content-Type" content="text/html; charset={$site.feed.generator|escape:"html":"UTF-8"}" /> <meta generator="{$site.feed.generator|escape:"html":"UTF-8"}" /> <title>{$site.title|escape:"html":"UTF-8"}</title> </head> <body> <h1>{$site.link|escape:"html":"UTF-8"}</h1> <div id="description">{$site.description|escape:"html":"UTF-8"}</div> <div id="lastBuildDate">Build date:{$site.feed.datetime|escape:"html":"UTF-8"}</div> <hr /> <div id="items"> <ul> {foreach item=item from=$site.items} <li><div class="item"> <div class="title"> <a href="{$item.link|escape:"html":"UTF-8"}">{$item.title|escape:"html":"UTF-8"}</a> ({$item.datetime|escape:"html":"UTF-8"}) </div> </div> <div class="body">{$item.body|escape:"html":"UTF-8"}</div> </li> {foreachelse} <li>no item.</li> {/foreach} </ul> </div> </body> </html>
実行してみる
まずindex.php,feed_xml.tpl,feed_html.tplを同一ディレクトリに保存します. 次に一時ファイルを保存するためのディレクトリを作成し,パーミッションの調整をします.
$ mkdir -p tmp/{smarty/templates_c,services_technorati} $ chmod o+w tmp/{smarty/templates_c,services_technorati}
さくらインターネットの共有サーバーなどのようにPHP CGIなどでsuexecされた環境ではパーミッションの設定は必要ないかもしれません.
また,パーミッションの追加は場合によっては「o+w」ではなく「a+w」などを求める環境もあるかもしれません(滅多にないと思いますが).
上記ファイル群を使用した実行サンプルはとりあえずhttp://elf.no-ip.org/php/dev/services_technorati/にとりあえず置いておきます.
Services_Technoratiは他に何ができるのか?
後から気づいたのですがServices_Technoratiは簡易的ではありますが,有志が作成した日本語マニュアルがあります(いつもながらありがとうございます). これとhttp://www.technorati.com/developers/api/をあわせて参照するとある程度何をどうすればいいか理解できるかもしれません.
終わり
次回までにはServices_Photozouで何か面白いことができたらいいなぁ~~~と思いますが,どうなるかわかりません. 期待せずに待っていてください.
最後に今更ではありますが,もしタグではなく検索結果をRSSで取得する方法をご存じの方がいらっしゃったら恥ずかしいのでこっそり教えてください. それではあでゅー.