Web ページから「コンテンツ」を抽出するためにBeautiful Soupを使用しています。私は何人かの人々が以前にこの質問をしたことを知っています、そして彼らは皆美しいスープを指摘されました、そしてそれが私がそれを始めた方法です.
ほとんどのコンテンツを正常に取得できましたが、コンテンツの一部であるタグでいくつかの問題に直面しています。(私は基本的な戦略から始めています: ノードに x-chars を超えるものがある場合、それはコンテンツです)。例として、次の html コードを見てみましょう。
<div id="abc">
some long text goes <a href="/"> here </a> and hopefully it
will get picked up by the parser as content
</div>
results = soup.findAll(text=lambda(x): len(x) > 20)
上記のコードを使用して長いテキストを取得すると、タグで中断されます (識別されたテキストは「そして願わくば..」から始まります)。そこで、次のようにタグをプレーンテキストに置き換えようとしました:
anchors = soup.findAll('a')
for a in anchors:
a.replaceWith('plain text')
Beautiful Soup は文字列を NavigableString として挿入し、len(x) > 20 で findAll を使用すると同じ問題が発生するため、上記は機能しません。最初に正規表現を使用して html をプレーン テキストとして解析し、すべてクリアします。不要なタグを削除してから、Beautiful Soup を呼び出します。しかし、同じコンテンツを 2 回処理することは避けたいと思います。これらのページを解析して、特定のリンク (Facebook の共有と非常によく似ています) のコンテンツのスニペットを表示できるようにしています。速くなると思います。
私の質問: Beautiful Soup を使用して「タグをクリア」し、「プレーン テキスト」に置き換える方法はありますか。そうでない場合、そうするための最良の方法は何ですか?
ご提案いただきありがとうございます。
更新: Alex のコードは、サンプルの例で非常にうまく機能しました。また、さまざまなエッジケースを試しましたが、すべて正常に機能しました(以下の変更を加えて)。そこで、実際の Web サイトで試してみたところ、困惑する問題に遭遇しました。
import urllib
from BeautifulSoup import BeautifulSoup
page = urllib.urlopen('http://www.engadget.com/2010/01/12/kingston-ssdnow-v-dips-to-30gb-size-lower-price/')
anchors = soup.findAll('a')
i = 0
for a in anchors:
print str(i) + ":" + str(a)
for a in anchors:
if (a.string is None): a.string = ''
if (a.previousSibling is None and a.nextSibling is None):
a.previousSibling = a.string
elif (a.previousSibling is None and a.nextSibling is not None):
a.nextSibling.replaceWith(a.string + a.nextSibling)
elif (a.previousSibling is not None and a.nextSibling is None):
a.previousSibling.replaceWith(a.previousSibling + a.string)
else:
a.previousSibling.replaceWith(a.previousSibling + a.string + a.nextSibling)
a.nextSibling.extract()
i = i+1
上記のコードを実行すると、次のエラーが発生します。
0:<a href="http://www.switched.com/category/ces-2010">Stay up to date with
Switched's CES 2010 coverage</a>
Traceback (most recent call last):
File "parselink.py", line 44, in <module>
a.previousSibling.replaceWith(a.previousSibling + a.string + a.nextSibling)
TypeError: unsupported operand type(s) for +: 'Tag' and 'NavigableString'
HTMLコードを見ると、「最新の状態に保つ..」には以前の兄弟がありません(アレックスのコードを見るまで、以前の兄弟がどのように機能したかわかりませんでした。テストに基づいて、「テキスト」を探しているように見えますですから、前の兄弟がいない場合、a.previousSibling is None と a;nextSibling is None の if ロジックを通過していないことに驚いています。
私が間違っていることを教えてください。
-エコグニウム