私は新聞で政治指導者の出来事を抽出する小さなプロジェクトを行っています。時々政治家が言及され、リンクのある親も子もいません。(意味的に悪いマークアップのためだと思います)。
そこで、最も近いリンクを見つけて抽出できる関数を作成したいと思います。以下の場合、検索文字列はRasmussen
であり、必要なリンクは次のとおり/307046
です。
#-*- coding: utf-8 -*-
from bs4 import BeautifulSoup
import re
tekst = '''
<li>
<div class="views-field-field-webrubrik-value">
<h3>
<a href="/307046">Claus Hjort spiller med mrkede kort</a>
</h3>
</div>
<div class="views-field-field-skribent-uid">
<div class="byline">Af: <span class="authors">Dennis Kristensen</span></div>
</div>
<div class="views-field-field-webteaser-value">
<div class="webteaser">Claus Hjort Frederiksens argumenter for at afvise
trepartsforhandlinger har ikke hold i virkeligheden. Hans rinde er nok
snarere at forberede det ideologiske grundlag for en Løkke Rasmussens
genkomst som statsministe
</div>
</div>
<span class="views-field-view-node">
<span class="actions">
<a href="/307046">Ls mere</a>
|
<a href="/307046/#comments">Kommentarer (4)</a>
</span>
</span>
</li>
'''
to_find = "Rasmussen"
soup = BeautifulSoup(tekst)
contexts = soup.find_all(text=re.compile(to_find))
def find_nearest(element, url, direction="both"):
"""Find the nearest link, relative to a text string.
When complete it will search up and down (parent, child),
and only X levels up down. These features are not implemented yet.
Will then return the link the fewest steps away from the
original element. Assumes we have already found an element"""
# Is the nearest link readily available?
# If so - this works and extracts the link.
if element.find_parents('a'):
for artikel_link in element.find_parents('a'):
link = artikel_link.get('href')
# sometimes the link is a relative link - sometimes it is not
if ("http" or "www") not in link:
link = url+link
return link
# But if the link is not readily available, we will go up
# This is (I think) where it goes wrong
# ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
if not element.find_parents('a'):
element = element.parent
# Print for debugging
print element #on the 2nd run (i.e <li> this finds <a href=/307056>
# So shouldn't it be caught as readily available above?
print u"Found: %s" % element.name
# the recursive call
find_nearest(element,url)
# run it
if contexts:
for a in contexts:
find_nearest( element=a, url="http://information.dk")
以下の直接呼び出しは機能します。
print contexts[0].parent.parent.parent.a['href'].encode('utf-8')
参考までに、申し訳ありませんがコード全体がbitbucketにあります:https ://bitbucket.org/achristoffersen/politikere-i-medierne
(BeautifulSoup 4を使用したps)
編集:SimonSapinは私に最も近いものを定義するように頼みます:最も近いとは、どちらの方向でも、検索語から最も少ないネストレベルであるリンクを意味します。上記のテキストではa href
、drupalベースの新聞サイトによって作成されたものは、検索文字列が見つかったタグの直接の親でも子でもありません。とてもBeautifulSoupが見つかりません。
私は、「最も少ない文字」が離れていることもしばしば機能すると思います。その場合、soulutionはfindとrfindと一緒にハッキングされる可能性がありますが、私は本当にBSを介してこれを実行したいと思います。これはうまくいくので:contexts[0].parent.parent.parent.a['href'].encode('utf-8')
それをスクリプトに一般化することが可能でなければなりません。
編集:多分私はBeautifulSoupソリューションを探していることを強調する必要があります。@ erik85によって提案されているように、BSをカスタム/単純な幅優先探索と組み合わせると、すぐに面倒になると思います。