今や、あなたは解析木内を、どのように検索すれば良いか知っています。しかし、解析木を修正し、再出力したいことがあるかもしれません。
要素を親の 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 件のコメント:
コメントを投稿