4

HTMLドキュメントがあり、特定の単語の言及の最大のクラスターに最も近いラッパーであるHTML要素を見つけたいと思います。

次のHTMLを使用します。

<body>
    <p>
        Hello <b>foo</b>, I like foo, because foo is the best.
    <p>
    <div>
        <blockquote>
            <p><strong>Foo</strong> said: foo foo!</p>
            <p>Smurfs ate the last foo and turned blue. Foo!</p>
            <p>Foo foo.</p>
        </blockquote>
    </div>
</body>

機能が欲しい

find_largest_cluster_wrapper(html, word='foo')

...これはDOMツリーを解析し、<blockquote>要素を返します。これは、 fooの言及が最も多く含まれており、最も近いラッパーであるためです。

最初のもの<p>fooを3回、 1回<b>だけ、内部<p>fooを3回、2回と2回、 1回だけ含みます<strong>。しかし、 fooは4回<blockquote>含まれています。もそうですが、これは最も近いラッパーではありません。この要素は言及の数が最も多いですが、クラスターがまばらすぎます。<div><body>

クラスタリングを使用しない単純な実装では、常に<html>または<body>そのようなものが得られます。これは、そのような要素には常に要求された言及の数が最も多く、おそらくそれらに最も近いラッパーであるためです。ただし、単語の密度が最も高いWebページの部分にのみ関心があるため、最大のクラスターを取得するものが必要です。

私は構文解析の部分についてはあまり興味がありません。それはbeautifulsoup4または他のライブラリによってうまく解決される可能性があります。クラスタリングを行うための効率的なアルゴリズムについて疑問に思っています。しばらくググってみたら、クラスタリングパッケージscipy役立つと思いますが、使い方がわかりません。誰かが私に最善の解決策を勧めて、私を正しい方向に追いやることができますか?例は完全に素晴らしいでしょう。


さて、ご指摘のとおり、条件が曖昧なので、一般的にそのような質問に答えるのは難しいでしょう。したがって、より具体的には:

通常、ドキュメントにはそのようなクラスターが1つだけ含まれます。私の意図は、そのようなクラスターを見つけてラッパーを取得し、それを操作できるようにすることです。この言葉はページの他の場所でも言及されている可能性がありますが、私は注目すべきものを探していますそのような言葉のクラスター。注目すべきクラスターが2つ以上ある場合は、外部バイアスを使用して決定する必要があります(ヘッダー、ページのタイトルなどを調べます)。クラスターが注目に値するというのはどういう意味ですか?それはまさに私が今提示したことを意味します-「深刻な」競争相手がいないということです。競合他社が深刻であるかどうかにかかわらず、たとえば10のクラスターと2のクラスターがある場合、その差は80%になります。差が50%を超えるクラスターがあるとしたら、それは注目に値するでしょう。つまり、5のクラスターと5のクラスターの場合、関数は戻りますNone(決定できませんでした)。

4

3 に答える 3

3

だからここにアプローチがあります:

|fitness(node, word) = count of word in node text if node is a leaf
|fitness(node, word) = sum(fitness(child, word) for child in children) / 
                         count of overall elements in node tree

ここにあります:

import lxml.html

node = """<html><body>
    <p>
        Hello <b>foo</b>, I like foo, because foo is the best.
    <p>
    <div>
        <blockquote>
            <p><strong>Foo</strong> said: foo foo!</p>
            <p>Smurfs ate the last foo and turned blue. Foo!</p>
            <p>Foo foo.</p>
        </blockquote>
    </div>
</body></html>"""

node = lxml.html.fromstring(node)

def suitability(node, word):
    mx = [0.0, None]
    _suitability(node, word, mx)
    return mx[1]

def _suitability(node, word, mx):

    children = node.getchildren()
    sparsity = 1
    result = float(node.text_content().lower().count(word))
    for child in children:
        res, spars = _suitability(child, word, mx)
        result += res
        sparsity += spars
    result /= sparsity
    current_max, max_node = mx
    if current_max < result:
        mx[0] = result
        mx[1] = node
    return result, sparsity

print suitability(node, 'foo')

それは私たちに最も適したとしてblockquote要素を与えます。また、スコア関数を調整することで、目的のクラスターのパラメーターを変更できます。

于 2012-11-12T15:32:59.380 に答える
1

図書館ではありませんが、私には考えがあります。

HTML の解析ツリーを構築し、各ノードに次の 2 つの注釈を付けるとどうなるでしょうか。

  1. 含まれる単語の総数。
  2. ターゲット単語が含まれる回数。

次に、ツリーを検索して、最大化するノードを見つけることができますtarget_count / total_count。ツリーの上位の要素にはより多くの単語が含まれるため、これにより最小の包含要素のプロパティが得られます。実際、これにより、ターゲット単語の密度が最も高いノードが得られます。

単純な除算では、必要な結果が得られないことがあります。たとえば、ノードにターゲット単語のコピーが 1 つしか含まれていない場合、密度は非常に高くなりますが、考えているクラスターの概念に対応しない場合があります。この場合、要素に含まれる単語の数をサイズにマップする関数を定義します。クラスターが特定のサイズであることを確認し、大きすぎるクラスター (例: )<body>) にペナルティを課す場合は、次のようになります。

def size(num_words):
   num_words = max(num_words, 40) # where 40 is the min size of a cluster
   if num_words > 1000: # This is too large, so we penalize
     num_words *= 1.5
   return num_words

これでできますtarget_count / size(total_count)

Re: scipy クラスタリング

このクラスタリングはベクトルで機能します。したがって、このパッケージを使用するには、ターゲット単語の出現をベクトルに変換する方法を考え出す必要があります。頭の中でこれを行う良い方法は思いつきませんが、それはそのような方法が存在しないという意味ではありません。

于 2012-11-12T15:38:37.147 に答える
1

これはクラスター分析ではないため、クラスター化パッケージはあまり役に立ちません。

それはより頻繁なパターンマイニングの行にあるので、代わりにそれを調べたいと思うかもしれません.

于 2012-11-12T22:36:04.097 に答える