2013-03-16 5 views
6

は、次のPythonのセッションをご検討ください:のfind()replaceWith後の()(BeautifulSoupを使用して)動作しません

>>> from BeautifulSoup import BeautifulSoup 
>>> s = BeautifulSoup("<p>This <i>is</i> a <i>test</i>.</p>"); myi = s.find("i") 
>>> myi.replaceWith(BeautifulSoup("was")) 
>>> s.find("i") 
>>> s = BeautifulSoup("<p>This <i>is</i> a <i>test</i>.</p>"); myi = s.find("i") 
>>> myi.replaceWith("was") 
>>> s.find("i") 
<i>test</i> 

は、4行目の後に( "I")s.findの行方不明出力に注意してください!

この理由は何ですか?回避策はありますか?

EDIT:実際には、例があるユースケース、実証していません:挿入された部分は自明でないhtmlコード自体が含まれているときはいつでも

myi.replaceWith(BeautifulSoup("wa<b>s</b>")) 

を、私はあなたが何かでこの構文を置き換えることができるかが表示されませんelse。ちょうど持っている

myi.replaceWith("wa<b>s</b>") 

は、エンティティごとにhtml特殊文字を置き換えます。

+0

'someTag'に置き換えるのではなく、' sometag.renderContents() 'と置き換える必要があるのはなぜですか? – BrenBarn

+0

さて、別の例を追加して具体的にしてみましょう。(私はもう一度編集しました) – thomas

答えて

5

簡単な答え:replaceWithに電話した後、sに電話をかけてs = BeautifulSoup(s.renderContents())を再生して清掃してください(コメントは、ここでの主な質問ではありません)。その後、findに再度アクセスできます。

3

問題は、BeautifulSoupオブジェクトはドキュメント全体と見なされるようです。 findは、各要素にその要素の後の次の要素を求める文書を反復処理します。しかし、それがあなたのBeautifulSoup("was")に届くと、そのオブジェクトはそれがドキュメント全体だと思うので、それは後に何もないと言います。これにより検索が早すぎます。

BeautifulSoupは他のBeautifulSoupオブジェクトの中にBeautifulSoupオブジェクトを持つように設計されているとは思いません。回避策はそれをしないことです。なぜ、すでに動作している2番目のフォームの代わりに1番目のフォームを使用する必要があると思いますか?要素をHTMLの一部のビットで置き換える場合は、BeautifulSoupオブジェクトではなく、置き換えにTagを使用します。

+0

私の例は明確ではないことを認めますが、なぜこの奇妙な構造が必要なのでしょうか? – thomas

+0

しかし、あなたの説明はまったく正しいです、ありがとう!しかし、回避策があることは素晴らしいことです。 (解決策としてあなたの答えに印をつけないので、私と怒ってはいけません。) – thomas

+0

@thomas:同様の問題に関するバグ報告があります[ここ](https://bugs.launchpad.net/beautifulsoup/+バグ/ 1105148)。コメントは解決されていると言われていますが、それでも私には壊れているようで、そこの説明は理解できません。あなたはそのバグにコメントし、あなたの例を示し、彼らが何を言っているのかを見たいかもしれません。 – BrenBarn

2

私はこの問題を解決する回避策を見つけました。これはreversed()ないと動作しないことに、注意してください

from BeautifulSoup import BeautifulSoup 
s = BeautifulSoup("<p>This <i>is</i> a <i>test</i>.</p>") 
myi = s.find("i") 
s2 = BeautifulSoup("wa<b>s</b>") 
myi_id = myi.parent.contents.index(myi) 
for c in reversed(s2.contents): 
    myi.parent.insert(myi_id + 1, c) 
myi.extract() 

:私は完全な例を与えることをPythonスクリプトとして再びコード全体を繰り返します。スキップすると、要素の順序を変更するだけでなく、あなたは本当に順序を変更したい場合は、次のように記述する必要があります:

for c in list(s2.contents): 
    myi.parent.insert(myi_id + 1, c) 

誰かが説明していただけます、なぜスキップlist()<b>s</b>を省略するのだろうか?

+0

あなたが 'list'を必要とする理由は、[ここ](http://www.crummy。com/software/BeautifulSoup/bs3/documentation.html#%20a%20Brand%20New%20Elementの追加):要素はドキュメント内の1か所にしか存在しません。 'insert'を実行すると、他の場所に挿入するために' s2.contents'から最初の要素が削除されます。したがって、あなたはそれを反復する間に 's2'を修正しています。 – BrenBarn

関連する問題