Ajax Web ぺージを検索ボットがクロールできるコンテンツを返すようにする

最近は様々な Web サイトで Ajax が当たり前のように使われています。 ページ内のコンテンツをほぼ全てAjaxで別途ロードするようなサイトの場合、検索エンジンのロボットにはすっからかんのページがクロールされてしまいます。 そのために、サーバ側で予めブラウザで画面をロードした後のHTMLを生成して返すのが良いみたいです。 Googleのサイトにも AJAX クロール: ウェブマスターおよびデベロッパー向けガイド - ウェブマスター ツール ヘルプ のようなページがあり、HTML スナップショットをクローラーに提供するように提案されています。 また下記の英語サイトでは具体的な HTML snapshot の実装方法例が出ていて、その中で Java の HtmlUnit というものが紹介されています。 How do I create an HTML snapshot? - Webmasters — Google Developers これを使って実際に今、Nginx とアプリケーションサーバで動かしている Web サイトに、 クローラーのアクセス時だけ Nginx → HtmlUnit の Java Web アプリサーバ → アプリケーションサーバと経由して HTML スナップショットを返すようにしてみました。 HtmlUnit のサイト: http://htmlunit.sourceforge.net/ サーブレットの実装 HtmlStaticServlet クラスは、GET で受け取ったパスをそのまま本来のアプリケーションサーバにリクエストして返すものです。 getAjaxPage メソッド内で FireFox 3.6 で JavaScript オン、CSS オフでアクセスしてロード後2秒間処理させて結果のXHTMLを返しています。 import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.gargoylesoftware.htmlunit.BrowserVersion; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.HtmlPage; public class HtmlStaticServlet extends HttpServlet { private static final String ROOT_URI = "http://localhost:8081"; private static final long serialVersionUID = 172403081095751054L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String url = ROOT_URI + request.getRequestURI(); System.out.println(url); String htmlContent = getAjaxPage(url); response.setContentType("text/html; charset=UTF-8"); PrintWriter writer = response.getWriter(); if (htmlContent != null) { response.setStatus(HttpServletResponse.SC_OK); writer.print(htmlContent); } else { response.setStatus(HttpServletResponse.SC\_NO\_CONTENT); } } private String getAjaxPage(String url) { WebClient webClient = new WebClient(BrowserVersion.FIREFOX\_3\_6); webClient.setJavaScriptEnabled(true); webClient.setCssEnabled(false); webClient.setScriptPreProcessor(new IgonoredGAScriptPreProcessor()); try { HtmlPage page = webClient.getPage(url); webClient.waitForBackgroundJavaScriptStartingBefore(2000); return page.getDocumentElement().asXml(); } catch (Exception e) { return null; } finally { webClient.closeAllWindows(); } } } Google Analyticsの無視 このままだとスナップショット生成時にGoogle Anlyticsへのアクセスが発生してしまいます。 こちらを無視するように JavaScritpのファイルロード時の処理を前もって処理する ScriptPreProcessor クラスのサブクラスを作っておきます。 ...

2012年3月17日 · Toshimitsu Takahashi

Ajax Web アプリケーションを Adobe AIR に移植しようとして気づいたこと

Web サービス(Ajax アプリケーション)を Adobe AIR に移植しようとして気づいたことをメモしておく。 ruby-MySQL のサーバーサイド(ビジネスロジックはなくストレージ機能)は AIR の SQLite データベースで実現する。 気づいたことを徒然なるままに。 AIR は Webkit ベースなので、IE, Firefox, Safari, Opera, Chrome × Win, Mac ブラウザで動いていた Ajax が余裕でそのまま動くと思っていたが、『jQuery のプラグインが動かなかったり、 eval が上手く使えなかったり、:hover が適用されない。』と手痛いことが多い。 Ajax AIR はデバッグがきつい。Firebug が使えないので Trace 地獄になる。Flex (Builder) で開発させたいのが本音だろうなぁ。 ローカルストレージが SQLite なのも微妙。これは Gears でも思ったがローカルストレージを RDB にする意味がわからない。REST や webDAV みたいにあくまでも ターゲット URI を切り替えて使えるような I/F の方が好ましいと思う。 Flex 版も含めての話だが、正式な証明書ではないとしてもインストール時に制作者を表示してほしい。UNKNOWN になってしまうのは。。。 ということでインターフェイスの切り替えで済むような移植を考えていましたが断念しました。 Flex 同様、AIR も バージョン 2 あたりから期待した方がいいかもしれない。 ※蛇足だが Aptana Studio をアップデートしたら AIR の出力がエラーで不能になってしまった。

2009年2月15日 · Toshimitsu Takahashi