<< PEAR:Cache_Liteでキャッシュ管理 | main | その変数、値がはいってますか? >>

2007.03.01 Thursday

クエリーの解析

クエリーを解析してみると、なかなか面白い。
googleやmsnでは、普通に「q=」の次に検索ワードが入っているのだが、
国内では最大手の検索サイトYahooのクエリーストリングを見てみると、なんと・・・
--

Yahooからのクエリーストリングを見てみると、いくつかのパターンに分類される。
http://search.yahoo.co.jp/search?p=%E5%A4%A7%E5%A1%9A%E6%84%9B %E3%83%99%E3%82%B9%E3%83%88%E3%82%A2%E3%83%AB%E3%83%90%E3%83%A0 %E3%83%AC%E3%83%B3%E3%82%BF%E3%83%AB%E3%80%80TSUTAYA&amp;ei=UTF-8&amp;fr=top_v2&amp;x=wrt
http://search.yahoo.co.jp/search?p=KOHJINSHA SA1F00A&amp;fr=top_v2&amp;tid=top_v2&amp;ei=euc-jp&amp;search.x=1&amp;x=8&amp;y=8
http://blog-search.yahoo.co.jp/search?p=skoop %C2%E7%D6%D6%B9%E1%BB%D2&amp;ei=
http://search.yahoo.co.jp/search?p=kohjinsha

一つ目は、文字コードUTF-8指定でp=の次に検索文字列が入っているパターン
二つ目は、文字コードEUC-JP指定でp=の次に検索文字列が入っているパターン
三つ目は、文字コード指定なしで、p=の次に検索文字列が入っていて、その文字エンコードはEUC-JPというパターン
四つ目は、p=の次に検索文字列だけが入っているパターン

よくもこれだけ、バラバラにするもんだなあ、アクセス解析屋さんを困らせたいのか?という思いも浮かんでくるわけですが、
一応は、文字コード指定のあるものはそのまま、mb_convert_encodingで変換すればよいので問題ないのだが、問題なのは、エンコーディング指定のないもの。

実は、q=のみの4つ目のパターンは、あまり目にしないので、実際にどのエンコードで格納されているのかは、現在では分からず、というのが正直なところ。
おおよそ、EUC-JPであろう、ということで、以下のコードを書いてみる。

function 関数名($url)
{
$str = ereg_replace('amp;','&',$url);
$host = parse_url($str,PHP_URL_HOST);
$query = parse_url($str,PHP_URL_QUERY);
parse_str($query,$query_array);

$query_str = "";

// キーにqがあれば、そのまま
if( !empty($query_array["q"] ) ) $query_str = $query_array["q"];

// Yahoo対応
if( (false!==strpos($host,"yahoo.co.jp")) ) {
if( empty($query_array["ei"]) || false!==stristr($query_array["ei"],"EUC-JP") )
$query_str = mb_convert_encoding($query_array["p"],"UTF-8","EUC-JP");

if( "UTF-8" == $query_array["ei"] ) {
$query_str = $query_array["p"];
}
}

if( !empty($query_str) ) {
$query_str = mb_convert_kana($query_str,'s');
$query_str = ereg_replace('[ +,]','|',$query_str);
}

return( $query_str );
}

簡単に説明すると、
この関数に、クエリーストリングの付いたURLを与えると、そこから検索文字列を抜き出して、その値を返す、というもの。
一番最初で、文字列置換をしているのは、Javascript経由でReferrerを取得している関係上、&がエンコードされるので、それをデコード。
parse_urlという関数で、クエリーとホスト名を取得。
そのクエリーを元に、parse_strという関数で、クエリーをさらに分割。
最終的には、分割されたクエリーは、query_arrayという連想配列に格納されます。
連想配列というのは、配列の添字に数字だけではなく、文字が使える、というものです。
上の例では、
query_array["p"]やquery_array["q"]とすると、検索文字列が取得できるわけです。
別に、"p"や"q"は、どこかでdefineしているわけではありません。
Cのプログラマにとっては、カルチャーショックかも。

googleやmsnは、この配列には、UTF-8で文字列が格納されているので、そのままでよいのですが、Yahooでは、上で挙げたように、4つのパターンがあるので、それを解析して、文字列コード変換をしてあげないと、希望の検索文字列が取得できないので、それを上の例のYahooの条件文の中でやっているわけです。

こんなんで、いいんだろうか・・・
という疑問は残りますが、とりあえず、ちゃんと動いているようなので、まあ、いいか。

ちなみに、その下の、mb_convert_kanaのあたりでやっているのは、Webサービスへの検索引数に、そのままOR演算子で、複数キーワードを結合しています。
こうしておくと、呼び出し側で、戻り値をurlencodeかけるだけで、リクエストかければ、Webサービスにヒットするアイテムが得られるます。
汎用性を考えるのであれば、加工しないで、配列のまま戻してあげた方がいいかもしれないかな。
ここでは、利便性をとって、加工した文字列を返しています。

分解しないで、そのまま(スペース区切りで)リクエストすると、一般的には&検索になるので、ほとんどの場合、アイテムにヒットすることはないでしょう。

本当は、構文解析とかまで入れたほうがヒット率は上がるのですが、そこまでは、手が回らん。
ということで、ここまでかな。ひとまずは。

--

テクノラティお気に入りに追加する

Comments

コメント入力は停止しています

海外からと思われるコメントスパムが横行しているため、全記事のコメント入力を停止しています。メッセージのある方は、ホームページの一番下に連絡欄がありますので、そちらからお願いします。

Trackback URL

トラックバックする場合は、
トラックバック元の記事にこのエントリへのリンクを記載してください
このエントリのタイトル「クエリーの解析」
このエントリのリンク「http://kommy.s254.xrea.com/blog/log/eid19.html」