2010-10-23

Blogger Glass、ラベルで検索したい

一覧から記事を表示できるようにはなった。しかし、一覧だけから特定の記事を探すのはシンドい。Google の存在に慣れた身にとって「探す == 検索」であって欲しい。Blogger Glass にも「検索」機能が必要だ。

Blogger Data API では、データのいわゆる全文検索には対応していない(→ Blogger API Reference Guide)。可能なのはカテゴリを指定してフィードの内容を絞り込むことだけ。ここでいうカテゴリとは Blogger (の投稿画面など)ではラベルと呼ばれているもの。

たとえラベルによる検索だけだったとしても、何もないよりはマシだ。適切にラベル付けがされていれば効果的な絞り込みができるし、適切でない場合も多少の助けにはなる。

そんなわけで、今回はラベル検索を実装してみる。

調査

カテゴリによる検索

Google Data API (プロトコル) では、フィードを要求する際のパラメータとしてカテゴリを指定できる。これまでにも実装の中で使ってきた max-resultsstart-index などと同様に URL に埋め込む形で利用する。

これはそのまま GData ライブラリでも利用できる。具体的にはこうなる。

(カテゴリによる絞り込み)
        client = gdata.blogger.client.BloggerClient()
        q = gdata.blogger.client.Query(categories=[label.encode('utf-8')])
        feed = client.get_posts(blog_id, query=q)

この例では label にラベル文字列が入っている。複数のラベルで絞り込む場合(AND 結合)は gdata.blogger.client.Query 生成の際に categories に複数のラベルを詰めれば良い。OR 結合で指定する場合はラベルを "|" でつないた文字列を詰める。たとえば、'imac' と 'macbook' のどちらか一方をラベルに持つ記事を探すのであれば categories=['imac|macbook'] をわたす。

デザイン(意匠と設計)

検索結果画面

一般に検索結果は複数の記事になるから、その表示も一覧表示が適している。欲を言えば Google の検索結果のように記事の抜粋も付けたいところだが、現段階ではそこまでは望まない。よって、画面そのものは「一覧画面」と同様になる。また、結果が多数の場合は複数のページに分かれることになるから、これも「一覧画面」と同様にページ切り替えの仕組みも必要だ。唯一の違いは、「検索結果画面」にはどんな検索語(ラベル)で検索したかを表示すべきだという点だ。これは「view-header」の部分に表示する。

リクエスト形式

リクエスト形式として /search/ を追加する。以下に、これをふくめた定義ずみ全リクエスト形式を示す。

Blogger Glass 全リクエスト形式
リクエスト 機能
/ page=0 を指定した場合と同様。
/?page=<number> number で指定したページの一覧を表示する。
/post/ 最新の記事の内容を表示する。
/post/?id=<id> id で指定した記事の内容を表示する。
/search/?label=<string> ラベル string で記事を絞り込んむ。結果が複数ページにわたる場合は、最初のページ(ページ番号 0)を開く。
/search/?label=<string>&page=<number> ラベル string で記事を絞り込んだ結果のうち、number で指定したページを開く。
/settings/ 設定変更のための画面を開く。

実装

新規に追加したのは、SearchViewHandler (後述)を定義する src/searchview.py と「検索結果画面」の src/searchview.html だ。

src/app.yaml には新しいリクエスト形式 (/search/) を追加。src/info.py には「検索結果画面」に表示する情報を詰めるためのクラス(SearchViewInfo)を追加。また、「一覧画面」と「検索結果画面」で共通になるページ切り替えの仕組みは src/util.py に移動させた。src/postview.html への変更はラベルに検索リクエストへのリンクを張るためのものだ。

SearchViewHandler

結果として、ほぼ「一覧画面」の MainHandler と同じコードになった。違いはクエリ(gdata.blogger.client.Query)生成時にラベルを指定している程度だ。fill_viewinfo() をリファクタリングしてくくり出すことを考えても良いかも。

この実装における注意点は、1 つは GData Python ライブラリのバグ(後述)で、もう 1 つは、クエリにラベル文字列を追加する際にエンコードを指定する、という点だ。つまり、label がラベル文字列だったとして、このままクエリにわたすのではなく、label.encode('utf-8') でわたさなければならない、ということ。さもないと、GData ライブラリの奥で以下のようなエラーが出る。

UnicodeEncodeError: 'ascii' codec can't encode characters in position 6-13: ordinal not in range(128)

そう言えば、以前同じような現象に遭遇したことがあった(→ Ruby で書いたフィルタを Python で書き直す #2)。文字列のエンコードの問題には、こっちが忘れた頃に出くわすなあ。

GData Python ライブラリのバグ?

実は、今回の実装の過程で、GData Python ライブラリのバグだと思われるものにぶつかった。それは上述のようにクエリにカテゴリを指定しても絞り込みが行われないというものだ。原因は gdata/client.py 中にあった。

(gdata/client.py のオリジナル; 827 行付近)
 759: class Query(object):
[...]   [...snip...]
 824:   def modify_request(self, http_request):
 825:     _add_query_param('q', self.text_query, http_request)
 826:     if self.categories:
 827:       http_request.uri.query['categories'] = ','.join(self.categories)

この 827 行目は正しくはこうなるようだ。

(gdata/client.py 修正版; 827 行目)
 827:       http_request.uri.query['category'] = ','.join(self.categories)

要は http_request.uri.query に詰められたキーと値が最終的に Google Data API にわたるが、このキー名が間違っているのだ。複数形の "categories" ではなく単数形の "category" がプロトコルとして正しいクエリ文字列だ。

ま、次のバージョンでは直ってくるだろう。

追記 (@2010-10-24)

このバグはすでに問題として報告されていて、かつすでに修正されているようだ。といっても修正されたのは最近(この 10 月に入ってから)のようだけど。

  • Issue 315 (gdata-python-client; Project Hosting on Google Code)

今後の展望

Blogger Glass はブログを「見る」ことに特化したアプリだ。その意味では「検索」機能は重要な機能だと言える。今回実装した「検索」機能は、とくにそのユーザ体験において必要最低限のものにも到達していない。なにしろ、個々の記事を開いたときにしか検索機能を使うことができないのだ、ユーザにとって使いやすいものではない。せめて、ラベルの一覧表示は欲しい。できれば一覧の他にタグクラウドのような表示も欲しい。また、ラベルを複数指定できればさらに実用性が高まるだろう。GData ライブラリ(と API)ではカテゴリを複数指定できる。これに関して足りないのは単純にアプリ側の作り込みなのだ。

一歩前進すれば、より遠くが見えるようになる。ゴールのように見えていた場所は、単なる中継地点でしかなかったことがわかる。

とはいえ、記事の一覧と個々の記事の内容が独自のスタイルで表示できるようになったことで、Blogger Glass は実用性のあるアプリになった。今回、指定できるラベルが 1 つに限定されているとは言え、ラベルによる絞り込み(検索)ができるようになり、さらに実用性は高まったと言える。もう記事の投稿の時以外にオリジナルの Blogger の方を開く必要はないかも。

さっき数えたら、Blogger Glass に関係する記事が 28 本になっていた。そろそろ全体の「まとめ記事」を書いて整理した方が良いな。前ばっかり見ていると、いつまでたっても近付かないゴールに(なにしろゴールが動くからな)やる気を削がれかねない。来し方を振り返り積み重ねたものを実感することで、また一歩を踏み出すモチベーションになる。

関連リンク

関連記事

0 件のコメント:

コメントを投稿