Web2.0 - Google検索がAjax対応
いつから対応してたか不明ですが、Googleの検索結果がAjax対応されてます。検索結果で次へを押した時に、再読み込みの気配なく次のページが表示されていたので調べてみました。
IEだとJavaScriptが吐き出されないので、Firefoxのみかも知れません。またgoogle.comでもJavaScriptが出てきませんでした。日本語サイト(www.google.co.jp)だけが対応ってことなんでしょうか。
<06.03.07追記> 記事を書いた時点ではFirefoxのみと思っていたのですが(私の環境ではFirefoxでのみJavaScriptが出力されていたため。)、別の環境のFirefoxでは、Ajax(JavaScript)が出力されませんでした。調べてみたところ、どうやらブラウザがどうとかいうのではなく、Cookieから判断していて、一部の環境にのみ公開されてるような感じです。
GoogleにアクセスするとPREFという名前のCookieが発行されるのですが、このCookieの値次第でJavaScriptが吐き出されたり・吐き出されなかったりするようです。記事を書いた時点のIEに設定されていたCookie(PREF)はJavaScriptを出力しない値だったようです。
Firefoxに設定されていたCookieをIEのgoogle.co.jpのCookieに上書きしたところAjax検索となりましたので、FirefoxだけでなくIEでもAjaxな検索ができるようです。
同様にgoogle.comのCookieに上書きしてもJavaScriptが表示されたので、日本語サイトだけではなくgoogle.comでもAjaxな検索に対応していました。
ただ、具体的にどういう状況で発行されたPREFの場合にAjax(JavaScript)が表示されるのかが不明です。今回は強制的にFirefoxのCookieをIEに上書きしましたが、そもそもGoogleは、User-AgentがFirefoxの場合に発行しているのかも知れませんし、Accept-Language(言語)がja(日本語)の場合に発行しているのかも知れません。
詳細不明ですが、一部のIDを持つ人用にベータ公開してるのかもしれません。最初の結果ページを表示するために、今までは1リクエストだった通信がAjaxにすることによって3リクエスト程度の通信になるため、負荷を考えて制限しているのかもしれません。 </06.03.07追記>
<06.03.08追記> PREFについて別の日の記事に書きました。 </06.03.08追記>
Ajaxが実行されているのは、現在表示されている検索結果の次ページを先読みしている部分です。具体的には検索結果を表示した際、非同期で次の検索結果を取りに行っています。
通常Ajaxだけで画面の書き換えを行うと、戻るボタンが利かなくなりそうな気もしますが、隠しフレームにデータを読み込ませることで対応しています。
GoogleのJavaScriptは難読化されてますが、時間かければ解析できると思います。
解析したコードをそのまま載せるのは怒られそうなので、抜粋して気になったポイントをご紹介します。
- JavaScriptの入り口は、次へリンクの
onClickと画面表示時のonLoadです。onLoadは主に戻るボタンや進むボタンでページ遷移した際に使用されます - 最初の検索結果を表示した時点で次のページがあれば先読みを行います
- 次へを押すと同時に、先読みしたキャッシュから結果を表示してます。サーバに読み込みにいかないため検索結果の表示は早くなっています
- その後
Ajax(XMLHttpRequest)を使って、次の検索結果を読み込みに行ってます - たぶん、不具合だと思いますが、最後のページを読み込んだ際はキャッシュを構築しないため、戻るボタンがうまく動きません。具体的には最終ページで戻るボタンを押すと前のページではなく、2ページ分前に戻ってしまいます。例えば検索結果が4ページあり、4ページ目まで進んでから戻るボタンを押すと、2ページ目に戻ります。これは4ページ目を表示した時点で、今いるページ番号を3ページ目と誤認識しているためです
- もうひとつ、
XMLHttpRequestと同時に送信しているリクエストがありました。画像のロード機能(imgタグのsrc属性)を使って、検索クエリーをGoogleに送っています。セッションIDみたいな文字列(_eiという変数名)と検索クエリーをoutput=nobackendsというパラメータを付けて送信しています。nobackends単品でGoogle検索しても何にも出てこないのですが、恐らく検索結果を返さないパラメータのようです。検索ワードをトラッキングするためのクエリーでしょうか。Firefox1.5では画面からの設定として消えてしまいましたがabout:configよりdom.disable_image_src_setをtrueにすることで、JavaScriptによる画像の書き換えが禁止され、トラッキングリクエストは送信されなくなります(ただし、この設定を行うとJavaScriptによる画像の書き換えが全てオフになってしまいまいますので、注意して下さい。PrefBarでカスタマイズできるようにしておくのもいいかも知れません) - 検索結果のHTML内にある
contentというidのdivタグを書き換えます。XMLHttpRequestの結果内にある"tratspaws"と"dnepaws"というコメントの間で書き換えるのですが、逆さから読むと"swapstart"と"swapend"ってなってます。逆さにする意味がよく分かりませんでしたが、これも難読化の一環なのかもしれません。 私の環境からだとIEではJavaScriptが吐き出されませんでしたが、XMLHttpRequestオブジェクトを作成する際、MS用のXMLHttpRequestの作成を試みていますので、どうにかすればIEでもAjax検索が出来るのかも知れません。↓こんな感じです。/* MS用のXMLHttpRequestオブジェクト集 */ var MSXMLHTTPS = ["MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "MICROSOFT.XMLHTTP.1.0", "MICROSOFT.XMLHTTP.1", "MICROSOFT.XMLHTTP"]; /* XMLHttpRequestオブジェクトの作成関数 */ function getXMLHTTP() { var xmlhttp = null; if (window.ActiveXObject) { for (var i = 0; i < MSXMLHTTPS.length; i++) { var xmlobj = MSXMLHTTPS[i]; try{ xmlhttp = new ActiveXObject(xmlobj); break; } catch(e) { } } }else if (window.XMLHttpRequest) { try{ xmlhttp = new XMLHttpRequest(); } catch(e) { } } return xmlhttp; }- 先読み時のURLは、通常のURLとは違い、
/searchではなく/prefetchです。何が違うかというと出力されるHTMLのリンク先がそれぞれのパス(/searchだったらリンク先は/search、/prefetchだったらリンク先は/prefetch)で表示されてるのと、出力されるJavaScriptが違っているくらいでした。先読みと言えば、google.comで先読み機能が実装されていました(過去の記事)。この機能は危険があるのでオフにしています。 - 画面には隠し
iframeが存在します。hifという名前です(hidden iframeの略かな)。このiframeに先読みした検索結果を展開しています。画面に出ないのに何故フレームがあるのかな、と思いましたが、戻るボタンで前のページを表示させるためのようです。PrefBarをカスタマイズして、Frameのオン・オフ(browser.frames.enabled)を切り替えられるようにしているのですが、オフにすると次へ次へと進んでも、戻るボタンの履歴が増えません。フレームにデータを読み込ませることで、ページを進めているようです - 戻るボタンが押された時には、HTML内にある
"state"というこれまた隠しinputフィールドに読み込ませていた値からキャッシュを復元します。stateは隠しフレームを開く時に、書き込まれているようです
まだきちんと理解できてませんが、かなり細かく作られている印象です。(不具合ありですが)戻るボタンへの対応に気を遣っているところは、さすがグーグルといったところでしょうか。
進むボタンを押した時点で履歴が増えない点(Firefoxの仕様?)と、同じくリロードボタンを押した時点で正しく検索位置を復元している点がいまいち理解できてないので、もう少し見てみたいと思います。

