Stellaqua - TOMの技術日記 このページをアンテナに追加 RSSフィード

2010年08月21日

[][]Webサイト内のよく使われているひらがなをへのへのもへじにしちゃうWebサービスを作ってみた

やってきました、誰得Webサービスのコーナー! 今回は、今北シリーズの第3弾、へのへのもへじ自動生成サービスです。

いまきたもへじ

WebサイトURLを入れると、そのサイトで多く使われているひらがなで、へのへのもへじ的に顔を作っちゃうというサービスです。

URLを入れる代わりに、ひらがなで直接入力する事もできるので、顔っぽくなりそうな言葉を入れてみて楽しむ事もできちゃいます。

ちなみに、"へのへのもへじ"だと、"じ"が顔の輪郭になりますが、輪郭を適当なひらがなにしちゃうと、他のパーツと重なっちゃって輪郭にならない可能性が高いので、輪郭の代わりに、もう1文字増やして耳になるようにしています。

耳がそれっぽく見えるような文字を選ぶのはなかなか難しいですが、ぜひ色々試してみて下さいね。

今回も画像生成するようにしていますが、「へのへのもへじと言えば落書きの代名詞…落書きするものと言えば、やっぱノートだよね〜」って事で、ノートの端っこに落書きした風に仕上げてみました。

最初は「へのへのもへじと言えばカカシ!」と思ってカカシの画像素材を探したんですが、都合よく顔の部分だけ空白になっているものなど無く…自分でイラストを描ける訳でもなく…画像素材の部分はいつも苦しめられますね…。*1

という訳で、ぜひ遊んでみて下さいね〜。

*1:素材をさっくり作ってくれるような協力者を随時募集中です。(笑)

2010年06月13日

[][]Webサイトブログの文章を元に四字熟語を自動生成するサービスを作ってみた

今回は、今北シリーズ(?)の第2弾として四字熟語バージョンを作ってみました。

今北四字熟語

これは何?

「今来た私にサイトの内容を四字熟語で教えて下さい」的なサービスです。

URLを入力して"作成する"ボタンを押すと、該当サイトの内容を元に四字熟語を自動生成してくれます。

試しにこのブログで試してみたところ、こんな四字熟語になりました。

作事思表

これは、「作る事は思想を表す事だ」という意味です。(勝手に解釈) 自分の中で、Webエンジニアとして何かを作って公開する事は、そのまま自身の実力だったり考え方だったりを表現する事だと思っているので、この四字熟語は適当にできたにしては案外良くできている感じがして気に入っています。

ちなみに、今北川柳では色紙に書いたっぽい画像を生成するようにしていたんですが、今回は家訓的なモノをイメージして、巻物に書いた感じの画像にしてみました。

「○○のブログ訓」みたいな感じでブログパーツとして画像を貼ってもらったりすると結構面白いかもしれないですね。

どんな仕組みなの?

コア部分の仕組みとしては、該当URLのサイト内容を読み込んで、漢字だけを抜き出して数をカウントして、多く使われている順に4つ並べているだけです。

一番最初にテストで書いたコードは以下の通り。

<?php
$body = file_get_contents('http://d.hatena.ne.jp/stellaqua/');
$body = mb_convert_encoding($body, 'utf-8', 'euc-jp');
preg_match_all('/[一-龠]/u', $body, $matches);
$results = $matches[0];
$results = array_count_values($results);
natsort($results);
$results = array_reverse($results);
$results = array_slice($results, 0, 4);
var_dump($results);
?>

ロジック部分は、これがベースになっていて、後は今北川柳から色々流用して作っています。

array_count_valuesとかあんまり使った事なかったんですが、なかなか便利で色々使えそうですね。

こんな感じで、サイトの内容をごにょごにょして何かしらの形として自動生成するというのは、他にも応用が利きそうなので、また"今北シリーズ"として色々考えてみたいと思います。


そんな訳で、ぜひ遊んでみて下さいね〜。

2010年05月06日

[][]TopHatenarのランキングを周期表っぽく並べたものを作ってみた

何かふいに思い付いて、TopHatenarのはてなダイアリーのランキングを元素の周期表みたいに並べたもの*1を作ってみました。

ランキング周期表

何の意味があるかって? 何の意味もありません。(笑)

元々、アイデアのネタの一つとして「周期表の形式で何かを並べたら面白いものが作れないかな。」と思っていたのがあって、「ちょうど順番に並んでいるものだし、何かのランキングを周期表に見立てて並べたら面白いかも…。」ぐらいの軽い気持ちで、勢いに任せて作ってみたものです。

内部的には、必要な情報の位置をURLとXPathを使って指定して取ってくるような作りにしてあって、設定ファイルさえいじれば、色んなランキングの周期表が作れるので、徐々に対象を増やしていこうかなと思っています。*2

ちなみに、元素記号的な感じになっているアルファベット数文字は、この周期表内で被らないようにしながら、はてなIDを省略したものですが、はてなーの皆さんならその数文字だけで誰だか分かるかもしれませんね。( ̄ー ̄)

あとは、せっかく元素のメタファーを持たせたので、その絡みで何か面白い事ができないか考えたりはしていますが、このWebサービスが発展の方向に向かうかどうかは…現時点では未定です…。

とりあえず思い付いたら、すぐに作ってすぐ公開をモットーに、また色々作っていこうかなと思います。

*1:ランタノイド・アクチノイドは一つの元素という扱いにしています。

*2:TopHatenarのランキングはAPIが無さそうだったので、スクレイピングして情報を取ってきている為、TopHatenar側のHTML構成変更などがあった場合、予告なく当サービスを停止する場合があるのでご了承の程を。

2010年05月01日

[][]コメント投票機能・Twitter連携機能など付けてみました

BEAR連載のおかげで、できる事の幅も広がってきたので、今まで作ってきたWebサービスリニューアル大作戦の第一弾として、今北川柳をBEARベースに置き換えつつ、機能拡張してリニューアルしてみました。

追加した機能のご紹介

Twitter連携

作成された川柳を、@imakitasenryuでつぶやくようにしました。フォローしてもらうと、意味が分かりそうで分からない川柳がいっぱい流れてくると思います。(笑)

面白い川柳があったら返信またはRT(QT)してもらうと、その川柳への投票になります。コメント付きで返信・RTすると、ちゃんと投票コメントとして反映されるようになっています。

返信・RTする場合、以下のような書式でないと正しくコメントを抽出できない事があるので、ご注意下さい。

コメント投票機能

今まで川柳への投票は、はてなスターの機能を使っていたんですが、いかんせん敷居が高いのか全く投票に使ってもらえなかったので(^^;、自前で投票機能を実装しました。

「面白い!」と思ったら、"天晴+"ボタンを押すと、その川柳に投票する事ができます。また、"天晴+"ボタンの隣の吹き出しボタンを押してコメントフォームにコメントを入力してから投票すると、コメント付きで投票する事もできます。

コメント表示機能

川柳を色紙画像で表示する個別表示画面で、投票されたコメントを吹き出しで表示するようにしました。鬱陶しいと思ったら"コメントを非表示にする"のリンクをクリックすれば、表示を止める事ができます。表示設定はCookieに保存されるので、次回訪れた時も設定がそのまま引き継がれるようになっています。

APIの追加

ブログなんかで簡単に紹介してもらえるように、画像のAPIは前バージョンからあったのですが、今回、テキストベースのAPIも作ってみました。現在、以下のAPIが利用可能です。

画像取得API(URLを指定)
http://www.stellaqua.com/imakitasenryu/api/images.php?url={対象サイトのURL}[&size=small]
画像取得API(IDを指定)
http://www.stellaqua.com/imakitasenryu/api/images.php?id={川柳ID}[&size=small]
テキスト取得API(URLを指定)
http://www.stellaqua.com/imakitasenryu/api/texts.php?url={対象サイトのURL}[&format=(xml|json|jsonp&callback={コールバック関数})]
テキスト取得API(IDを指定)
http://www.stellaqua.com/imakitasenryu/api/texts.php?id={川柳ID}[&format=(xml|json|jsonp&callback={コールバック関数})]
コメント取得API
http://www.stellaqua.com/imakitasenryu/api/comments.php?id={川柳ID}[&format=(xml|json|jsonp&callback={コールバック関数})][&_start={表示ページ}]

テキスト取得APIのレスポンスは以下のような感じです。(XMLの場合)

<?xml version="1.0" encoding="utf-8"?>
<results>
    <senryu>
        <id>52e85875124208d7c40ff10d16d7bae0</id>
        <createdtime>2010-05-01T14:55:14+0900</createdtime>
        <sourceurl>http://news.google.co.jp/</sourceurl>
        <sourcetitle>Google ニュース</sourcetitle>
        <votecount>0</votecount>
        <commentcount>0</commentcount>
        <texts>
            <text1>出席し</text1>
            <text2>訴えている</text2>
            <text3>謝罪する</text3>
        </texts>
        <links>
            <imageurl>http://www.stellaqua.com/imakitasenryu/api/images.php?id=52e85875124208d7c40ff10d16d7bae0</imageurl>
            <entryurl>http://www.stellaqua.com/imakitasenryu/api/texts.php?id=52e85875124208d7c40ff10d16d7bae0</entryurl>
            <commenturl>http://www.stellaqua.com/imakitasenryu/api/comments.php?id=52e85875124208d7c40ff10d16d7bae0</commenturl>
            <tweeturl>http://www.twitter.com/imakitasenryu/status/13173910635</tweeturl>
        </links>
    </senryu>
</results>

コメント取得APIのレスポンスは以下のような感じです。(XMLの場合)

<?xml version="1.0" encoding="utf-8"?>
<results>
    <pager>
        <totalResults>1</totalResults>
        <startIndex>1</startIndex>
        <itemsPerPage>1</itemsPerPage>
        <firstpageurl></firstpageurl>
        <nextpageurl></nextpageurl>
        <prevpageurl></prevpageurl>
        <lastpageurl></lastpageurl>
    </pager>
    <comments>
        <comment>
            <id></id>
            <createdtime>2010-05-01T15:00:00+0900</createdtime>
            <targetid>52e85875124208d7c40ff10d16d7bae0</targetid>
            <body>コメントしてみたよ</body>
            <targeturl>http://www.stellaqua.com/imakitasenryu/api/texts.php?id=52e85875124208d7c40ff10d16d7bae0</targeturl>
            <via>http://www.stellaqua.com/imakitasenryu/api/texts.php?id=52e85875124208d7c40ff10d16d7bae0</via>
        </comment>
        <comment>
            :
        </comment>
            :
    </comments>
</results>

レスポンスコードは、200(OK)・400(呼び出し方の不正)・403(高負荷によるアクセス規制)・500(サーバエラー)のいずれかが返ってきます。

こんなAPIを公開したところで何かに使えるのかどうか全くもって不明ではありますが、まぁこれを使って何かを作ろうという奇特な方が現れた時の為に公開しておきます。(笑)

ちなみに、川柳を作成する対象URLを指定してアクセスした時に、対象サイトの内容のキャッシュが無い場合、レスポンスに数秒掛かる事があるのでご注意下さい。

その他こだわった点とか

細かい事なんですが、今回のリニューアルに伴ってタイトルからα表記を外して、ついでにfaviconも作ってみました。ドットを置いていくタイプのfavicon作成Webサービスで、5分くらいで作ったやっつけにしてはそれなりなモノができたので満足しています。

あと、コメントの表示は結構こだわってみました。ボワンと現れて、スーっと消えていく感じが結構気にいっています。最初はニコニコ動画風な流れるコメントにしようかとも思ったんですが、何か今や目新しさも無くなった感もあるし、あんまりやり過ぎても鬱陶しくなるだけかなと思って、今の形に落ち着きました。

この辺りのアニメーションと、Ajaxのデータのやり取りでjQueryをふんだんに使ってみたんですが、色々と勉強になりました。Webサービスにちょっとした彩りを添えるのにはjQueryは使い易くって非常に良いですね。

それから、川柳の元になる単語を拾ってくる時に、数字の読みをきちんと行うようにしてみました。

MeCabで普通に数字を読ませると一桁ずつでしか読んでくれないので、"123"を"イチニサン"と読んでしまうんですが、こういうのをちゃんと"ヒャクニジュウサン"と読めるように、自前で専用のクラスを作って変換をするようにしてみました。これで、数字を含む単語でもそれなりに抽出できるようになったのではないかと思います。

その他困った点とか

TwitterのOAuth対応は以前に試した事があったので、そこでの苦労はあまり無かったんですが、RTを取り込んで投票に反映させる機能が大変でした…。

以下、ハマりどころ…。

  • 公式RTは、自分のつぶやきの内のどのつぶやきがRTされたかは分かるけど、誰からRTされたのかはAPIで取得できない…。(仕方がないので、公式RTを投票に使うのは諦めた。)
  • 非公式RTだと書式が決まってないから、コメント部分だけ抜き出そうとすると、どうするのがベストか分からない…。(仕方がないので、最初に出てきた"RT"より前の部分をコメントと決め打ちしちゃう事にした。)
  • 非公式RTだと、どのつぶやきに対する返信か分からないから、どの川柳に対する投票なのか特定できない…。(仕方がないので、元のつぶやきに含ませてあるURLから川柳のIDを取得する事にした。)
  • 非公式RTで元のつぶやきのURLを短縮URLにしないで入れてもらおうとすると、コメントに使える文字数が少なくなってしまう…。(仕方がないので、短縮URLの場合は展開してからIDを取得する実装を入れた。)

Twitterも今やインフラとしての利用価値が大きいから、できるだけTwitterからもWebサービスに参加できる間口は広げたいんですが、自由度が高過ぎる故に、Webサービスとして欲しい情報を拾ってこようと思うと妥協しなきゃいけない部分が多くて悶々としますな…。

Twitter連携は突っ込むと泥沼にハマりそうな感もあるので、そこそこの線で妥協しときたいと思います…。


そんな訳で、色々と機能追加してより遊べるようになったかと思うので、「これからも 今北川柳 よろしくね♪」(一句)

*1:"RT"or"QT"が1回("RT:"とかコロン付きでもOK)、コメントが"RT"or"QT"より前にある、元のつぶやきの中のURLが含まれる(短縮URLでもOK)、という条件を満たしていれば大丈夫なはずです。

2010年03月02日

[][][][]BEARで始めるWebアプリケーション開発 その8「リンクを使ってリソース同士を接続する」

今回は、リソース同士を接続する事ができる"リンク"の機能について学習します。

今回の題材

今までは"逆さ語"を題材としてきたんですが、現状の逆さ語の仕様だとリソース同士がリンクしていなくて、題材としてはよろしくないので、他の題材を探す事にしました。

という訳で色々考えた末、リンク機能の面白さが分かるようなものがいいかなという事で、はてなブックマークの人気エントリを題材にしてみる事にしました。

はてなブックマークの人気エントリは以下のような形で、特定のURLを含むページの人気エントリをRSSで取得する事ができます。

http://b.hatena.ne.jp/entrylist?sort=count&url=http://d.hatena.ne.jp/stellaqua/&mode=rss

ただ、このRSSにはブックマークコメントは入っていないので、コメントを見る為には該当のブックマークページを見に行かなくてはいけません。

一方、特定のページに付けられたブックマークコメントは、以下のようなURLでRSSを取得する事ができます。

http://b.hatena.ne.jp/entry/rss/http://d.hatena.ne.jp/stellaqua/20090305/1236222223

という事は、人気エントリのリソースにブックマークコメントのリソースをリンクしてやれば、人気エントリのブックマークコメントが一気に取れるんじゃね?…って事で、実際にやってみましょう。

人気エントリのリソースを作る

App/Ro/bookmarks.phpというファイル名にして、onReadメソッドを以下のようにしました。

<?php
    public function onRead($values)
    {
        $resource = BEAR::dependency('BEAR_Resource');
        $uri = 'http://b.hatena.ne.jp/entrylist?sort=count&url=http://d.hatena.ne.jp/stellaqua/&mode=rss';
        $options['cache']['life'] = 60 * 60 * 3;
        $params = array('uri' => $uri, 'options' => $options);
        $result = $resource->read($params)->getBody();
        return $result;
    }
?>

毎回RSSを取得しにいくと重たくなってしまうので、今回は3時間のキャッシュを保存する設定を追加しました。

BEARはこのように、リソース、ページ、テンプレート変数など、様々な場所でいとも簡単にキャッシュを利かせる事ができるので、多くのAPIを使うようなマッシュアップサイトでも、それなりな負荷に耐えられるWebアプリケーションを簡単に作る事ができそうですね。

ブックマークコメントのリソースを作る

続いてブックマークコメントのリソースを作ります。App/Ro/comments.phpというファイル名にして、onReadメソッドを以下のようにしました。

<?php
    public function onRead($values)
    {
        $resource = BEAR::dependency('BEAR_Resource');
        $uri = 'http://b.hatena.ne.jp/entry/rss/'.$values['link'];
        $options['cache']['life'] = 60 * 60 * 3;
        $params = array('uri' => $uri, 'options' => $options);
        $results = $resource->read($params)->getBody();
        return $results;
    }
?>

$values['link']には、bookmarksリソースからリンク機能を介してブックマーク先のURLが渡ってくるので、それを使ってブックマークコメントを取得するURLを構築しています。

人気エントリリソースからブックマークコメントリソースへリンクを張る

あとはリンク元となるbookmarksリソースのonLinkメソッドに、commentsリソースへのリンク設定を書いてやる事で、リンク機能が使えるようになります。

<?php
    public function onLink ( $values )
    {
        $links['comments'] = array(
                                   'uri' => 'comments',
                                   'values' => array('link' => $values['link']),
                                  );
        return $links;
    }
?>

当然、更に別のリソースへのリンクを書く事もできますし、commentsリソースにonLinkを書けばcommentsリソースから更にリンクする事もできます。

リンク機能を使ってページから情報を取得する

このようにリンク設定を行ったリソースから関連データを取得するのは非常に簡単で、ページから以下のような感じでごっそりと必要な情報を取ってくる事ができます。

<?php
    public function onInit(array $args)
    {
        $uri = 'bookmarks';
        $params = array('uri' => $uri);
        $this->_resource->read($params)->link('comments')->set();
    }
?>

これだけで、きちんと階層構造を持って必要な情報が取ってこれます。あとは、テンプレート側で以下のようにループを回してやれば、はてブ人気エントリのブックマークコメント一覧の完成です。

{foreach from=$bookmarks item="bookmark"}
    <p>{$bookmark.title}</p>
    <ul>
    {foreach from=$bookmark.comments item="comment"}
        <li>{$comment.description|default:''}(id:{$comment.title})</li>
    {/foreach}
    </ul>
{/foreach}

上記テンプレートから若干書き換えた後のものですが、実際に動作させてみた画面は以下の通り。

f:id:stellaqua:20100302223400j:image

こんな風に、外部API同士を組み合わせたサーバサイドのマッシュアップが非常に簡単にできるのがBEARの強みだと思います。

もちろん内部リソースとも全く同じ形で組み合わせる事ができるので、外部APIから何かしら情報を取ってきて、それに内部リソースをリンクして付加価値を付けて、Webアプリケーションとして公開…なんて事がお手軽にできそうですね!

次回は?

BEARはフォーム関連の機能は、PEAR::QuickFormが使われているんですが、QuickFormは使った事がなくてあまりよく分かっていないので、次回から何回かはフォーム関連の機能について学習していきたいと思います。

余談

今回、元々は"最新はてブられコメント一覧"が欲しいと思って、はてブを題材にして、その過程で色々調べてて知ったんですが、はてブの特定URL以下のページの最新ブックマーク一覧って、"http://b.hatena.ne.jp/bookmarklist/?url=〜"で取れるんですね。

記事の中で挙げたentrylistだとソート基準が、"今まで1件もブックマークされていないページが初めてブックマークされた日時"になるようで、古いページにブックマークが付けられてもなかなか気付けなかったんですが、これで、はてブられ状況をリアルタイムで追う事ができそうです。