iPhoneのUIWebViewではてなキーワードを高速置換

blog.yatsu.info: CocoaでTxを使うためのObjcラッパー tx-objc-wrapper で書いたtx-objc-wrapperにはもうひとつHatenaKeywordsというサンプルプログラムがあります。

これはiPhone用のシンプルなブラウザアプリで、開いたWebページのすべてのはてなキーワードをリンクに置換するものです。

このアプリをビルドするには、tx-objc-wrapperディレクトリで以下のようにはてなキーワードCSVをダウンロードします。

% wget http://d.hatena.ne.jp/images/keyword/keywordlist_furigana.csv

そして HatenaKeywords/HatenaKeywords.xcodeproj をXcodeでビルドします。

起動するとUIWebViewでWikipedia日本語版を読み込み、以下のようにキーワードを置換します。緑色がはてなキーワードへのリンクです。


iPhone 3G実機で26万語からTxを構築すると90秒くらいかかります。ラッパーのコードがNSStringへの変換などを含んでいて、その分遅いかもしれません。後でチューニングしようと思います。

2回目に起動すると、前回構築したTxを読み込みます。

以下が実装の主な部分です。

- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
  NSError *error = nil;

  // get the original HTML
  NSString *html = [aWebView stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML;"];
  DDXMLDocument *doc =
    [[DDXMLDocument alloc] initWithHTMLString:html
                      options:HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR
                      error:&error];

  // find text nodes that are not included in a link
  NSArray *nodes = [doc nodesForXPath:@"//*[name(.)!='a']/text()"
                  error:&error];
  for (DDXMLNode *node in nodes) {
    [node setStringValue:[txo replace:[node stringValue]]];
  }

  // generate HTML from DDXMLDocument
  html = [[[NSString alloc] initWithData:[doc XMLData]
                  encoding:NSUTF8StringEncoding]
      autorelease];

  // replace '[[[word]]]' with 'word'
  NSString *linkStr = [NSString stringWithFormat:@"$1"];
  html = [html stringByReplacingOccurrencesOfRegex:@"\\[\\[\\[([^\\]]*)\\]\\]\\]"
                      withString:linkStr];

  // escape quotation marks
  html = [html stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"];

  // make it one line
  html = [html stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"];

  // execute the JavaScript code
  NSString *js = [NSString stringWithFormat:@"document.body.innerHTML = '%@';", html];
  [aWebView stringByEvaluatingJavaScriptFromString:js];
}

このメソッドはUIWebViewの読み込みが終わったときに呼び出され、以下を行います。

  1. JavaScriptを実行しHTML(document.body.innerHTML)を取得する
  2. XPathでリンクの外のテキストノードを取得する
    (KissXML+HTMLを使用)
  3. [Txo replace:] ではてなキーワードを [[[キーワード]]] に置換し、ノードにセット
  4. DDXMLDocumentからHTMLを生成
  5. 正規表現で [[[キーワード]]] をリンクに置換
    (RegexKitLiteを使用)
  6. HTML文字列のクォーテーションマークをエスケープ
  7. HTML文字列を1行にまとめる
  8. JavaScriptでUIWebViewのHTMLを置き換える
いろいろ非効率的なところがあったり、エラー処理がなかったりするので、実際のアプリにするには書き換える必要があります。Webページによってはメモリが足りなくて落ちたり、その他のエラーが出たりすると思うので、ご注意ください。

0 Response to "iPhoneのUIWebViewではてなキーワードを高速置換"

コメントを投稿