AutoPagerizeの全文系SITEINFO

AutoPagerizeのSITEINFOについての考察でいうparagraph系はHTMLのドキュメントから繰り返し部分をみつけるアプローチでそれなりにいけるのでEntryFullText系が何とかならないかとちょっとやってみた。
Webページの本文抽出 (nakatani @ cybozu labs)を参考にしてjsでてきとうに書く。句読点を含むノードの親で文字数が多いやつっていう安直な実装。

var candidates= {};
var nodes = $x('//*[not(self::script) and text()[ contains(self::text(), "、") or contains(self::text(), "。")  ] ]');

nodes.map( function (node) {
// traverse the parents while parentNode has multiple children.
// to skip the structure like <div><font>...</font></div>.
  var e = node;
  do {
      e = e.parentNode;
  } while ( e.childNodes.length == 1 );

  var k = nodePositionList(e).join("/");

  if ( ! candidates[k] ) {
    candidates[k] = { node: e, weight: 0, me : node};
  }
  var w = 0;
  if ( node.offsetWidth > 0 ) {
    w = node.textContent.length * node.offsetWidth;
  }
  candidates[k].weight +=       w;
} );

for ( var i in candidates ) {
 candidates[i].weight = Math.log( candidates[i].weight ) / Math.LOG10E
}

candidates;


function nodePositionList(e) {
    var positionList = [];
    while ( e && e.nodeName.toLowerCase() != 'html' ) {
      var i = get_position(e);
        positionList.push( e.nodeName.toLowerCase() + "[" + i + "]" );
        e = e.parentNode;
    }
    return positionList.reverse();
}

 function get_position(node) {
        var xpath = './preceding-sibling::' + node.nodeName.toLowerCase();
        var n = xN(xpath, node);
        return n + 1;
    }

    function evalXPath(xpath, context, resultType) {
        try {
            var doc = (context instanceof Document) ?
                            context : context.ownerDocument;
            return doc.evaluate(xpath, context, null, resultType, null)
        } catch (e) {
            trace(e, xpath, context);
        }
    }

    function x(xpath, context) {
        var snapshot = evalXPath(xpath, context, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
        var nodes = [];
        for (var i = 0; i < snapshot.snapshotLength; i++ ) {
            nodes.push(snapshot.snapshotItem(i));
        }
        return nodes;
    }
    function xN(xpath, context) {
        var nodes = x(xpath, context);
        return nodes.length;
    }

cnetではうまくいったのでzuzara : ブログの記事本文を抽出するスクリプトをつくってみたに従ってはてなブックマーク - 過去の人気エントリーでやってみて気がついたこと。

検索だと、コメントのほうが長くて情報量多いんだからそっちが本文だと思ってもいい気もするけどAutoPagerizeの場合、生成したルールがほかのページにも適用されるので、ほかのページでは当然コメントのほうが本文より長いのはレアケースなので困る。

  • AutoPagerizeは(いまのところ)半自動で人間が介在する(ことを前提にしている)ので大きな誤りは人間が訂正することができる。
  • プロジェクト管理機能付きグループウェア「TUTOS」 - GIGAZINEのように、本文よりナビゲーションのほうがバイト数が多いものがある。レンダリング後の面積もナビゲーションのほうが大きい。ただ横幅が一番でかいところは普通本文になってる。これはブラウザでやってると容易に取れる情報なので役に立てるべきか。あとで役に立ててみる。立ててみたらとりあえずGIGAZINEではうまく機能するようになったけどほか不明。こないだもだったけどなんか自動化する方法考えないと。
  • "次のページ"という概念があるものだけが対象になるので、自然とシステムで生成されているページが対象になる。手書きのものはあんまり次のページという概念がない。手書きだとファイル増えると面倒だからか。
  • 日本語以外でまったく機能しない。
  • ページの構造がparagraphなのかEntryFullTextなのか判別する必要がある。

本文はドキュメントの構造とは無関係だから難しいことしないといけなそう。


どうでもいいけど http://japan.cnet.com/news/biz/story/0,2000056020,20360096,00.htm?ref=rss:title=cnet とかブログに貼られるとけっきょくrssから見にきたのかどうかわかんなくなったりするね。