Posts Tagged ‘fac2010’

    はてなブックマーク - Google Base Data APIで商品検索
    このエントリーをはてなブックマークに追加

    Fusic 平田です。
    1回くらいはさっさと当たれーとか思ってたら、ここまで引っ張りました。

    前提

    本題の前に。
    数日前に弊社の化学系新卒君が書いたAmazon APIの記事
    これとの繋がりが微妙にあるような話です。

    要は商品検索をいろいろ調べたり調べてもらったりしていたのです。
    Amazonだと多種多様の商品調べられてすごく便利、なんですが。
    1時間で2000アクセス~だと、あまり思い切ってリクエスト投げられない。
    # amazletでも最近引っかかっていましたし。
    てことでGoogle先生に頼ってみたところ、思いのほかいい感じだったのでご紹介。

    Google Base Data API

    Google Product Searchと言えばピンと来る人もいるでしょうか。
    旧Froogleだったりしながら未だにbetaなのですが。
    このデータ群を検索するためのAPIがGoogle Base Data APIです。
    # 商品に限らずいろいろ検索できます。

    とりあえず使ってみる

    # 以下のリンクはIEやFirefoxで開くとより分かりやすいです。
    仕組みは単純で、クエリを投げたら結果がFeedで返ってきます。
    例えば「モンスターハンターポータブル」で検索してみると
    www.google.com/base/feeds/snippets/?bq=モンスターハンターポータブル
    こんな感じです。

    突っ込んだ使い方

    bq=で渡す値をいろいろ変えることで、いろいろ検索できます。

    例えば中古品だけを探したい場合。
    スペース空けて後ろに[condition:used]を追加すればOK。
    「モンスターハンターポータブル」を中古のみ検索

    値段で絞りたい場合は[price >= 2000 JPY]とか付ければいいです。
    「モンスターハンターポータブル」を2000円以上で検索

    これらは組み合わせて使えるので[condition:new][isbn][price <= 1000 JPY]とか後ろに付ければ
    「デジタルカメラで新品でISBNコード持って(書籍かCDあたり)て1000円以内」
    とかもできます。

    更に値段でソートしたければ後ろにorderbyとsortorderを渡せばいいです。
    「更に値段の昇順でソートした結果」

    プログラムで取ってくる

    単にリクエスト投げてFeedを受け取るだけなので、割と簡単です。
    例えば引数でクエリの値を渡すようなプログラムだとこんな感じになります。

    #!/usr/bin/env perl
    use warnings;
    use strict;
    use Furl;
    use XML::Feed;
    use URI::Escape;
     
    if (@ARGV != 1) {
        die 'Usage: perl /path/to/snippet.pl [bq parameter]';
    }
     
    # 引数を受け取る
    my $query = shift;
     
    # Furl初期化
    my $furl = Furl->new(
        agent => 'Sample script for Google Base Data API',
        timeout => 10,
    );
     
    # リクエスト送信
    my $request_url = 'http://www.google.com/base/feeds/snippets/';
    my $res = $furl->get($request_url . '?bq=' . uri_escape($query));
     
    # レスポンスのXMLをパース
    my $feed = XML::Feed->parse(\$res->content);
     
    # SnippetのURLとタイトルを表示
    foreach my $entry ( $feed->entries ) {
        my $snippet_url = $entry->id;
        my $title = $entry->title;
        print "$snippet_url : $title \n";
    }
     
    exit;

    で、実行すると

    debility@xebius:~/works$ perl ./snippet.pl "デジタルカメラ [condition:new][isbn][price <= 1000 JPY]"
    http://www.google.com/base/feeds/snippets/9861142365767353685 : 55才から楽しむデジタルカメラで写真工房 Windows XP版 お父さんお母さんのための 押すだけ撮影から卒業・デジカメで思い出を残そう
    http://www.google.com/base/feeds/snippets/8908453582924256996 : デジタルカメラとパソコンを合わせて使える本
    http://www.google.com/base/feeds/snippets/12581094022531619238 : デジタルカメラ批判序説 あるいは、デジタルカメラで写真は撮れない
    http://www.google.com/base/feeds/snippets/1086636419406988656 : FMVでもっと楽しむデジタルカメラ わかりやすい図解入り
    http://www.google.com/base/feeds/snippets/13607998448764488416 : デジタルカメラ進化論
    http://www.google.com/base/feeds/snippets/10565006307493625118 : デジタルカメラで「趣味」を撮ってらくらく印刷
    http://www.google.com/base/feeds/snippets/13954829398014624305 : 大人のためのはじめてのデジタルカメラ 賢い選び方と快適活用術
    http://www.google.com/base/feeds/snippets/16925320360818721412 : デジタルカメラエクスプレス Vol.1
    http://www.google.com/base/feeds/snippets/13769101776078837942 : デジタルカメラエクスプレス Vol.2
    http://www.google.com/base/feeds/snippets/11531105340749645450 : デジタルカメラLabs Vol.1
    http://www.google.com/base/feeds/snippets/16563827664371922494 : いっきにわかるデジタルカメラの買い方・使い方―あなたのパソコンライフをいっきにひろげるデジタルカメラのすべて
    http://www.google.com/base/feeds/snippets/15904047532666634991 : 今日から上達デジタルカメラスーパー活用!
    http://www.google.com/base/feeds/snippets/8964847794878919955 : デジタルカメラ選び方・撮り方・楽しみ方 最新43機種の○と×がイッキにわかる!
    http://www.google.com/base/feeds/snippets/7419790109938360232 : デジタルカメラマガジン No.4
    http://www.google.com/base/feeds/snippets/6668800394078123731 : Best GearデジタルカメラSpecial ミラーレス一眼の真価キャッチせよ!激変のコンデジ
    http://www.google.com/base/feeds/snippets/5458330732187518314 : デジタルカメラマガジン Vol.16
    http://www.google.com/base/feeds/snippets/3282137698886167565 : デジタルカメラを始めよう
    http://www.google.com/base/feeds/snippets/16178408780302372761 : こんなに簡単デジタルカメラ徹底活用術 撮影・プリント・レタッチ・Web・デジカメの基本がよくわかる!すぐできる!
    http://www.google.com/base/feeds/snippets/15687552409826306759 : 55歳から楽しむデジタルカメラで写真三昧
    http://www.google.com/base/feeds/snippets/15331179909448343256 : デジタルカメラを始めよう
    http://www.google.com/base/feeds/snippets/6890264039679668486 : こんなに簡単デジタルカメラ&デジカメ写真のためのパソコン活用術 日本でいちばんやさしく丁寧な解説本
    http://www.google.com/base/feeds/snippets/6673485326686974641 : デジタルカメラを始めよう―For Windows & Macintosh (2002年版)
    http://www.google.com/base/feeds/snippets/5869285652009149385 : デジタルカメラを始めよう (2003年)
    http://www.google.com/base/feeds/snippets/3661117677961004259 : 中高年のための最新デジタルカメラ使いこなし術
    http://www.google.com/base/feeds/snippets/12355831548414530192 : 超図解ビギナーズデジカメ

    てな具合です。
    他の言語でも実装は非常に簡単でしょう。

    制限

    リクエスト制限については
    code.google.com/apis/base/faq.html#Limits

    > The Google Base data API supports up to approximately 5 queries per second, per user.

    てことで秒間5クエリくらいまでOKなので、だいぶ思い切って投げられます。多い日も安s

    てことで

    次の方にバトンタッチ。

      はてなブックマーク - PostgreSQLで数え年計算
      このエントリーをはてなブックマークに追加

      まさかまさかの4回目。いま宝くじを買えば3億当確の安元です。
      最近肩こりがひどいので、昨日からピップマグネループつけてます。
      そちらのレビューはまた今度。ビバ!プラシーボ!!

      さて本題。
      最近めっきり聞くことも少なくなった「数え年」。皆さんご存じでしょうか?
      ウィキペディアさんに聞いてみました

      数え年(かぞえどし)とは年齢や年数の数え方の一つである。生まれた時点、基点となる最初の年を「1歳」、「1年」とし、以降元日(1月1日)を迎えるごとにそれぞれ1歳、1年ずつ加える(例:12月31日に出生した場合、出生時に1歳で翌日(1月1日)に2歳となる。また1月1日に出生した場合は、2歳になるのは翌年の1月1日になる)。数え歳とも、単に数えともいう。
      これに対し、誕生日前日午後12時に加齢、加年する数え方を満年齢、満という。本稿においては主に年齢に関する事柄について記述する。

      これ日本独自のものかと思ってましたが、アジア圏ではそれなりに使われているそうです。
      私が必要となった数え年は、「1月1日」での年齢加算ではなく
      「4月1日」での年齢加算でした。いかにも日本の企業で必要になりそうですね!

      年齢を計算してみましょう

      誕生日から一般的な年齢計算を行いましょう

      ここで一番大切なのは「1979-09-02」ですね!私の誕生日です!

      SELECT句の2行目
      age関数が返してくる値は経過年月日ですね。
      SELECT句の3行目
      age関数の結果から「年」だけを切り出したものこれが「満年齢」になります。

      1月1日で年齢を加算する

      数え年ということは、「1月1日」で年齢が加算されるということです。
      ということは、何月に生まれようとも誕生日を「1月1日」生まれにしてしまえば
      みんな一緒に歳をとれますね!

      SELECT句2行目が示すように、
      誕生日から年だけ切り出し「-01-01」を付け足すことで無理矢理「1月1日」に強制しています
      やや乱暴ですが、これで数え年はでました。

      4月1日で年齢を加算する

      では日本ではよく使う「4月1日」を基準に考える「年度」で歳を取りましょう。

      ここで問題になるのは1月〜3月生まれの人々です。
      先ほどのように全員「4月1日」生まれに強制してしまいたいのですが、単純に年を切り出すと
      1月〜3月生まれは1歳進んでしまいます。
      この3ヶ月が邪魔なので、みんな誕生日を3ヶ月巻き戻して考えてしまいましょう。
      3月生まれは前年の12月生まれに、4月生まれは同年1月生まれになりますね。
      これで年をそろえることができます。

      1920年8月生まれは90歳 3月生まれは91歳と差が出ているのがわかります。

      PostgreSQLでは、日付計算が「 + ’1months’」のように月単位や年単位での計算ができます。

      長々とSQLを書いてきましたが、システム内で頻繁に年度計算を利用する場合は
      関数化してSQLに組み込むと使い勝手がよくなるのでご検討ください。

      それでは肩がこってきたのでこの辺で。

        はてなブックマーク - CakePHP 静的コンテンツのURLについて
        このエントリーをはてなブックマークに追加

        こんにちは、一年前に買ったデニムのサイズが合わなくなってきた島田です。

        皆さん食べ過ぎには注意しましょう。。。
        (俺が悪いんじゃない、会社周辺に美味しいお店が多いからいけないんだ!!)

        では、早速本題。

        CakePHP環境下で静的コンテンツは、通常『インストールフォルダ/app/webroot』の配下に設置しますよね。

        /app/webroot/test/index.html

        にファイルを設置すれば、

        example.com/test/index.html
        example.com/test/

        といった感じのURLでアクセスできます。

        ではこの状態で、 example.com/test (『/』なし)にアクセスするとどうでしょう?

        どん!

        example.com/app/webroot/test/

        そうなんです。

        『/app/webroot/』 が付いた状態にリダイレクトされちゃうんです。
        mod_rewite をとおさず直接アクセスしてますねぇ。

        画像やCSSファイルへのパスは、相対的位置関係が変わらないので、表示が崩れるということはありませんが、なんだか気持ち悪い。。。
        同じ情報のページに2URLからアクセス出来るのはSEO的に良くないし、
        Google Analytics などでアクセスログを取得しているときは、同一コンテンツなのに集計結果がわかれてしまう。。。

        ということで、こいつを解決しちゃいます。

        まずは Apache のログを見てみよう

        問題の解決に移る前にまず Apache のログを見てみましょう。

        192.168.0.1 - - [19/Dec/2010:23:08:06 +0900] "GET /test HTTP/1.1" 301 354 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; ja-jp) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4"
        192.168.0.1 - - [19/Dec/2010:23:08:07 +0900] "GET /app/webroot/test/ HTTP/1.1" 200 928 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; ja-jp) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4"

        301エラーを返したあとで、『/app/webroot/test/』にリダイレクトしています。

        簡単にいうとこんな感じです。

        1. スラッシュなしでアクセスしたため、Apache がファイルとして『test』を検索
        2. ファイルは見当たらなかったがディレクトリは見つかったので、クライアントに301エラーとリダイレクトメッセージ(『/』つきのURL)を返す
        3. リダイレクトメッセージにあるURLに再度リクエストを投げる
        4. コンテンツを表示

        2. で返ってくる『リダイレクトメッセージ』を直してリダイレクト先を変えてやればいいのか思いきや、
        それだと直接『example.com/app/webroot/test/』にアクセスされてしまう。。。

        というわけで、今回は

        example.com/app/webroot/test/

        に飛んできたURLを

        example.com/test/

        にリダイレクトさせるという方法で問題を解決しちゃいます。

        .htaccess を改変しよう

        CakePHP ではデフォルトで 3つの .htaccess が設置されていますが、今回は『インストールフォルダ/app/webroot/.htaccess』を改変します。

        <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
        </IfModule>

        インストール時のままだとこんな感じです。
        これをこんな感じに改変します。

        <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
        RewriteCond %{THE_REQUEST} "^(.+?) (.*?)/app/webroot/(.*?) (.+?)$"
        RewriteRule ^(.*?)$ %2/%3 [R=301,L]

        </IfModule>

        THE_REQUEST とは 先程のログの 『”GET /app/webroot/test/ HTTP/1.1″』 の部分を返します。
        要するにホストネーム以下のURLに /app/webroot/ が含まれていたら、それを省いたものへリダイレクトすると書かれています。

        Apache のログはこんな感じ

        192.168.0.1 - - [19/Dec/2010:23:18:06 +0900] "GET /test HTTP/1.1" 301 354 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; ja-jp) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4"
        192.168.0.1 - - [19/Dec/2010:23:18:06 +0900] "GET /app/webroot/test/ HTTP/1.1" 301 342 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; ja-jp) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4"
        192.168.0.1 - - [19/Dec/2010:23:18:07 +0900] "GET /test/ HTTP/1.1" 200 928 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; ja-jp) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4"

        二回リダイレクトして目的のURLにたどりついているのがわかります。

        最後に

        今回の解法は、Rewriteの条件を追加していますので、どうしてもその部分にコストが追加でかかってしまいます。
        レスポンススピードをシビアに求められるコンテンツには向かない場合もありますので、注意してください。

        それでは、また次回お会いしましょう。
        さようなら。

        追記

        RewriteRule でURLを書き換えた時、自動的に URLエンコード が行われてしまいます。
        クエリ文字列に特殊文字を含む場合、意図しないURLに書き変わってしまいますので、 NEフラグを指定してエンコードを行わないようにした方がよいでしょう。

        <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
        RewriteCond %{THE_REQUEST} "^(.+?) (.*?)/app/webroot/(.*?) (.+?)$"
        RewriteRule ^(.*?)$ %2/%3 [R=301,L,NE]

        </IfModule>