今や、あなたは解析木内を、どのように検索すれば良いか知っています。しかし、解析木を修正し、再出力したいことがあるかもしれません。
要素を親の contents の外側に切り取ることが出来ます、しかし、ドキュメントの残りの部分は、切り取った要素へのリファレンスを持ち続けます。
Beautiful Soup は、解析木の内部的な一貫性を維持する間に、解析木を修正するための様々な方法を提供します。
属性値を変更する
タグオブジェクトの属性値を修正するために、ディクショナリの代入を使用出来ます。
from BeautifulSoup import BeautifulSoup
soup = BeautifulSoup("<b id="2">Argh!</b>")
print soup
# <b id="2">Argh!</b>
b = soup.b
b['id'] = 10
print soup
# <b id="10">Argh!</b>
b['id'] = "ten"
print soup
# <b id="ten">Argh!</b>
b['id'] = 'one "million"'
print soup
# <b id='one "million"'>Argh!</b>
また、属性値を削除したり、新しい属性値を追加したり出来ます:
del(b['id']) print soup # <b>Argh!</b> b['class'] = "extra bold and brassy!" print soup # <b class="extra bold and brassy!">Argh!</b>
要素の除去
要素への参照を持つと、
extract を使用して、要素を解析木の外側に切り取ることが出来ます。このコードは、ドキュメントから、全てのコメントを除去します:
from BeautifulSoup import BeautifulSoup, Comment
soup = BeautifulSoup("""1<!--The loneliest number-->
<a>2<!--Can be as bad as one--><b>3""")
comments = soup.findAll(text=lambda text:isinstance(text, Comment))
[comment.extract() for comment in comments]
print soup
# 1
# <a>2<b>3</b></a>
このコードはドキュメントの部分木全体を刈り取ります:
from BeautifulSoup import BeautifulSoup
soup = BeautifulSoup("<a1></a1><a><b>Amazing content<c><d></a><a2></a2>")
soup.a1.nextSibling
# <a><b>Amazing content<c><d></d></c></b></a>
soup.a2.previousSibling
# <a><b>Amazing content<c><d></d></c></b></a>
subtree = soup.a
subtree.extract()
print soup
# <a1></a1><a2></a2>
soup.a1.nextSibling
# <a2></a2>
soup.a2.previousSibling
# <a1></a1>
extract メソッドは、1つの解析木を2つの互いに素な解析木に変換します。航行メソッドが変更され、そのため、木は決して元に戻らないように見えます:
soup.a1.nextSibling # <a2></a2> soup.a2.previousSibling # <a1></a1> subtree.previousSibling == None # True subtree.parent == None # True
1つの要素を別の要素に置換する
replaceWith メソッドは、1ページの要素を抽出し、異なる要素と置換します。新しい要素は、タグや、可航オブジェクトで構いません。
The new element can be a
Tag (possibly with awhole parse tree beneath it) or a
NavigableString.もし、変更前のプレーン文字を
replaceWith に渡せば、文字は、NavigableString に変わります。航行メンバーは、ドキュメントが最初の場所で、上記方法で解析されたかように変更されます。
ここに、シンプルな例を示します:
from BeautifulSoup import BeautifulSoup
soup = BeautifulSoup("<b>Argh!</b>")
soup.find(text="Argh!").replaceWith("Hooray!")
print soup
# <b>Hooray!</b>
newText = soup.find(text="Hooray!")
newText.previous
# <b>Hooray!</b>
newText.previous.next
# u'Hooray!'
newText.parent
# <b>Hooray!</b>
soup.b.contents
# [u'Hooray!']
あるタグを別のタグで置換する、より複雑な例を示します:
from BeautifulSoup import BeautifulSoup, Tag
soup = BeautifulSoup("<b>Argh!<a>Foo</a></b><i>Blah!</i>")
tag = Tag(soup, "newTag", [("id", 1)])
tag.insert(0, "Hooray!")
soup.a.replaceWith(tag)
print soup
# <b>Argh!<newTag id="1">Hooray!</newTag></b><i>Blah!</i>
ドキュメントの一部から要素を切り取り、他の場所に組み込むことさえ出来ます:
from BeautifulSoup import BeautifulSoup
text = "<html>There's <b>no</b> business like <b>show</b> business</html>"
soup = BeautifulSoup(text)
no, show = soup.findAll('b')
show.replaceWith(no)
print soup
# <html>There's business like <b>no</b> business</html>
新しい要素の追加
タグクラスと、解析クラスは
insert と呼ばれるメソッドをサポートします。これは、ちょうど、Pythonのリストの
insert メソッドのように動作します:インデックスをタグの
contents メンバーに渡し、新しい要素をその箇所に組み込みます。これは、前のセクションで、ドキュメント中のタグを新しいタグで置換する時、実演済みです
スクラッチから、解析木全体を構築するために、
insert を使うことが出来ます:from BeautifulSoup import BeautifulSoup, Tag, NavigableString
soup = BeautifulSoup()
tag1 = Tag(soup, "mytag")
tag2 = Tag(soup, "myOtherTag")
tag3 = Tag(soup, "myThirdTag")
soup.insert(0, tag1)
tag1.insert(0, tag2)
tag1.insert(1, tag3)
print soup
# <mytag><myOtherTag></myOtherTag><myThirdTag></myThirdTag></mytag>
text = NavigableString("Hello!")
tag3.insert(0, text)
print soup
# <mytag><myOtherTag></myOtherTag><myThirdTag>Hello!</myThirdTag></mytag>
1つの解析木中、一箇所だけで、要素が生じます。
もし、
If you
give
insert an element that's already connected to a soup object, itgets disconnected (with
extract) before it gets connectedelsewhere.
この例の中で、
NavigableString をsoupの2番目の場所に挿入しようとしましたが、 NavigableString を再び挿入することは出来ませんでした。NavigableString は移動してしました:tag2.insert(0, text) print soup # <mytag><myOtherTag>Hello!</myOtherTag><myThirdTag></myThirdTag></mytag>
この現象は、要素が前もって、全く異なるスープオブジェクトに属していたとしても起きます。
要素は1つの
parent や、1つの nextSibling などしか持っておらず、要素は同時に1箇所にしか存在出来ないためです。
0 件のコメント:
コメントを投稿