私は過去にこれについていくつかの調査を行い、最終的にこのアプローチ [pdf]を Python で実装しました。私が実装した最終バージョンでは、アルゴリズムを適用する前に、head/script/iframe 要素、隠し要素などを削除するなどのクリーンアップも行いましたが、これが核心でした。
これは、「リンクリスト」ディスクリミネーターの (非常に) 単純な実装を備えた関数です。これは、リンクとテキストの比率が高い要素 (つまり、ナビゲーションバー、メニュー、広告など) を削除しようとします。
def link_list_discriminator(html, min_links=2, ratio=0.5):
"""Remove blocks with a high link to text ratio.
These are typically navigation elements.
Based on an algorithm described in:
http://www.psl.cs.columbia.edu/crunch/WWWJ.pdf
:param html: ElementTree object.
:param min_links: Minimum number of links inside an element
before considering a block for deletion.
:param ratio: Ratio of link text to all text before an element is considered
for deletion.
"""
def collapse(strings):
return u''.join(filter(None, (text.strip() for text in strings)))
# FIXME: This doesn't account for top-level text...
for el in html.xpath('//*'):
anchor_text = el.xpath('.//a//text()')
anchor_count = len(anchor_text)
anchor_text = collapse(anchor_text)
text = collapse(el.xpath('.//text()'))
anchors = float(len(anchor_text))
all = float(len(text))
if anchor_count > min_links and all and anchors / all > ratio:
el.drop_tree()
私が使用したテスト コーパスでは、実際には非常にうまく機能しましたが、高い信頼性を実現するには、多くの微調整が必要です。