Beautiful Soup の replaceWith で string が更新されない
# -*- coding: utf-8 -*- from BeautifulSoup import BeautifulSoup soup = BeautifulSoup("<b>git</b>") print soup # => <b>git</b> print soup.b # => <b>git</b> print soup.b.string # => git soup.find(text='git').replaceWith('Git') print soup # => <b>Git</b> print soup.b # => <b>Git</b> print soup.b.string # => git
上記のように replaceWith を実行すると、
要素の innerText が更新されているように見えるけれど、
string で参照すると、更新されていない。
また同じように新しくタグの要素を作成し置き換えた場合も
一見うまくいっているように見えるけれど、string で参照すると
None が返ってくる。
# -*- coding: utf-8 -*- from BeautifulSoup import BeautifulSoup, Tag soup = BeautifulSoup("<dc:subject>git</dc:subject>") print soup.find('dc:subject') # => <dc:subject>git</dc:subject> print soup.find('dc:subject').string # => git new_tag = Tag(soup, "dc:subject") new_tag.insert(0, 'Git') soup.find('dc:subject').replaceWith(new_tag) print soup.find('dc:subject') # => <dc:subject>Git</dc:subject> print soup.find('dc:subject').string # => None
これは何だろう…と思って、わかんないかもしれないけれど
ソースでも見てみるか、と思いつつちょっと検索したら全く同じ話がでてきた。
That is indeed a bug in all versions before the just released
Beautiful Soup 3.0.8. Before that, Tag.string wasn't updated when the
tree was manipulated. Beautiful Soup 3.0.8 calculates Tag.string when
it is accessed using a property, so that bug is entirely fixed.
3.0.8 is available on the Beautiful Soup home page, but hasn't yet
been added to any distro packages. There hasn't been a 3.1.x release
based on the 3.0.8 changes, so that bug is still in 3.1.x.
使っていた Beautiful Soup は 3.0.8 だったけれど、
easy_install でいれたのでよく分からないが、
全く同じ現象が起こっているからまだバグが直っていないのを使っているようだ。
とりあえず renderContents で対応することにした。
print soup.b.renderContents() # => Git print soup.find('dc:subject').renderContents() # => Git