Zend_Service_Flickrを利用して猫画像をRSS Readerに渡してみる

社会で暮らしていくってストレス対策で猫画像が必要になりますよね?

http://www.flickr.com/services/feeds/photos_public.gne?format=rss_200_enc&tags=kitten
http://www.flickr.com/services/feeds/photos_public.gne?format=rss_200_enc&tags=cat

ってことで、上のようなRSSを購読していたのですが、どうも使い勝手が悪い! kitten と cat、cats、猫とたくさんのタグが個別に購読すると同じ写真が複数のところで乗ってくるんですよね。

マージして購読するのをZend_Service_Flickrを使って作ってみたいと思います。

データ取得

<?php
require_once 'Zend/Service/Flickr.php';

$flickr = new Zend_Service_Flickr('MY_API_KEY');

$data_list = array();

$results = $flickr->tagSearch("cat");
foreach ($results as $result) {
	$data_list[ $result->id ] = $result;
}
$results = $flickr->tagSearch("cats");
foreach ($results as $result) {
	$data_list[ $result->id ] = $result;
}
$results = $flickr->tagSearch("");
foreach ($results as $result) {
	$data_list[ $result->id ] = $result;
}
$results = $flickr->tagSearch("kitten");
foreach ($results as $result) {
	$data_list[ $result->id ] = $result;
}

ほぼサンプルそのままです!
http://framework.zend.com/manual/ja/zend.service.flickr.html

一番大変なのはFlickrのサイトでAPIキーを取得するところですね(笑) アメリカのYAHOOのアカウントをとってクレジットカードを入れて。。。すげー大変。。。

DBに保存

<?php
foreach ($data_list as $data) {
	$uri = str_replace( "sizes/t/", "", $data->Thumbnail->clickUri );

	$sql = "INSERT cat_list values(
		{$data->id}, 
		'{$data->title}', 
		'{$data->datetaken}', 
		'{$data->ownername}', 
		'{$uri}', 
		'{$data->Square->uri}', 
		'{$data->Thumbnail->uri}', 
		'{$data->Small->uri}', 
		'{$data->Medium->uri}', 
		'{$data->Large->uri}', 
		'{$data->Original->uri}',
		now()
	 )";

	$ret = mysql_query( $sql );
	if( $ret ){
		echo "insert:{$data->id}<br />\n";
		get_image($data);
	}
}

こんな感じでそのままデータをDBに保存。get_imageはローカルに画像を落とす場合に利用します。

画像ダウンロード

<?php
function get_image( $data ){
	$no = $data->id;
	if( isset( $data->Original->uri ) ){
		$path = $data->Original->uri;
	} elseif( $data->Large->uri ){
		$path = $data->Large->uri;
	} elseif( $data->Medium->uri ){
		$path = $data->Medium->uri;
	} elseif( $data->Small->uri ){
		$path = $data->Small->uri;
	}

	$get_file = file_get_contents($path, FILE_BINARY);

	// dir
	$dirname = "images/" . substr( $no, 0, strlen( $no ) - 6 ) . '000000';
	if( !is_dir( $dirname ) ){
		mkdir($dirname);
	}

	$path_info = pathinfo($path);
	$save_file = $dirname . "/" . $no . "." . $path_info['extension'];

	$item['file'] = $save_file;

	$fp = fopen($save_file, 'w');
	fwrite($fp, $get_file, 320000000);
	fclose( $fp );
}

本当はローカルに落とさない方がいいと思います。このサンプルだと一番でかいファイルをダウンロードしていますが、RSSで見るのであればSmallぐらいのサイズがお勧めです。

ただし本番が消されているのかの確認ができないので、iPhoneとかにとりあえず突っ込む以外はローカルにダウンロードしない方がいいかなって思います。

RSS吐き出し

<?php
include("feedcreator.class.php");

$rss = new UniversalFeedCreator();
$rss->useCached();
$rss->title = "Flickr 猫";
$rss->description = "Flickr 猫";
$rss->link = "http://www.flickr.com/";
$rss->syndicationURL = "http://www.flickr.com/";

$image = new FeedImage();
$image->title = "Flickr new Cats";
$image->url = "http://l.yimg.com/g/images/flickr_logo_gamma.gif";
$image->link = "http://www.flickr.com/";
$image->description = "Flickr";
$rss->image = $image;

// データ取得
$sql = "SELECT * FROM cat_list ORDER BY get_date DESC LIMIT 200";
$res = mysql_query( $sql );
while($row = mysql_fetch_array($res, MYSQL_ASSOC)) {	
	$image_uri = $row['small_uri'];
//	$image_uri = "http://example.net/cats/images/" . substr( $row['id'], 0 , strlen( $row['id'] ) - 6 ) . '000000/' . $row['id'] . '.jpg';

	$item = new FeedItem();
	$item->title = $row['title'];
	$item->link = $row['uri'];
	$item->description = '<a href="' . $row['uri'] . '" target="_blank"><img src="' . $image_uri . '"></a>';
	$item->date = strtotime( $row['datetaken'] );
	$item->source = $row['uri'];
	$item->author = $row['ownername'];

	$rss->addItem($item);
}

$rss->saveFeed("RSS1.0", "feed.xml");

RSSへの出力は「feedcreator.class.php」を使わせてもらいました。コメントアウトしている部分を切り替えることで自前のダウンロードした画像に差し替えることができます。

感想

対した処理ではないのですが、ローカルに画像を落とすのかは結構悩みました。マナー的にはサーバーから取得した方がいいのですが、キャッシュとしてダウンロードした方が早いのよね。。。サーバーに容量があれば一番でかいのとスモールを落としてってのでもいいのですがGoogleReaderで管理しているので自分サーバーにはあまり依存しないように本番を今は見に行っています。

あと30分間隔でスクリプトを現在動かしていますが、今後の画像の登録状況みて調整したいと思います。

あっ、Flickrの謎なところでIDが大きければ新しい画像でもなく、現地時間で飛んでくるので時間が新しければ新しい画像でもなく。。。結局重複しない画像が見つかった時間を基準にしています。INSERTで失敗したらすでにある画像っていうものすごいだめな処理をしています(反省)