May 30, 2007

HTMLドキュメントを解析して特徴的なループを見つけるBookmarklet

- 全てのDOMノードを列挙する
- ノードは次のように文字列化される。

0: /html[0]/body[0]/div
1: /html[0]/body[0]/div[0]/div
2: /html[0]/body[0]/div[0]/div[0]/ul[0]/li
3: /html[0]/body[0]/div[0]/div[0]/ul[0]/li
4: /html[0]/body[0]/div[0]/div[0]/ul[0]/li
5: /html[0]/body[0]/div[0]/div[0]/ul[0]/li


直前の階層までは添え字つき、最後のノードはタグ名のみにする。
class名、id名は排除する。各々のサイトのルールで記述されたruleよりも
タグのネスト構造の方が変化に強いし機械的に抽出しやすいのではないか?

出現回数でソートする。li要素2-5はループであることが分かる。
しかし、例えばリストの中に複数のリンクが含まれていた場合は、

/html[0]/body[0]/div[0]/div[0]/ul[0]/li[3]/a[0]
/html[0]/body[0]/div[0]/div[0]/ul[0]/li[3]/a[1]
/html[0]/body[0]/div[0]/div[0]/ul[0]/li[3]/a[2]
/html[0]/body[0]/div[0]/div[0]/ul[0]/li[3]/a[3]


というようなループも見つけることができるだろう。
この場合は「より短いパスでのループ」の方がスコアが高くなるようにする。

ループと思われるノード
この場合は/html[0]/body[0]/div[0]/div[0]/ul[0]/liの中身を解析する
例えばこんな感じに。
[
    {level:6, length:(下位のtextNodeのlengthの合計), text: textNodeを連結したもの }
    {level:6, length:(下位のtextNodeのlengthの合計), text: textNodeを連結したもの }
    {level:6, length:(下位のtextNodeのlengthの合計), text: textNodeを連結したもの }
]


- そのノードの配下に含まれる文章の長さが大きいほどスコアが加算される。
- link rel="next"から次のページを取得、同様に解析を行ってtextの内容で重複をチェックする
-- 例えば10件中9件が同じであればスコアを0.1倍に減らす。
-- 変化がないループはタグクラウドのような共通のパーツであると考えられる。
-- 次のページを見たときに内容が変化している箇所がメインコンテンツ部分。
-- ループから見て一つ親のノードがページの主要なコンテンツであると考えられる。
- offsetHeight,offsetWidthを使って描画サイズを調べる?ただしブラウザじゃないと無理。

というようなことを昨晩思いついたのでとりあえず、JavaScriptで書いてみた。
コードはこんな感じ、今のところ重み付けはなくて出現回数のカウントだけ。

http://la.ma.la/misc/js/guess_loop.js

ブックマークレットにして試せるようにしてみたのがこちら。

guess loop

書き忘れ、forEachとか使ってるのでFirefoxオンリーです。
Posted at 14:36 | WriteBacks (5) | Edit
Edit this entry...

wikieditish message: Ready to edit this entry.
















A quick preview will be rendered here when you click "Preview" button.