使用BeautifulSoup后,replaceWith()后的find()无效
请看下面的Python会话:
>>> 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行之后,s.find("i")没有输出!
这是为什么呢?有没有解决办法?
补充说明:其实,这个例子没有展示出实际的用例,实际情况是:
myi.replaceWith(BeautifulSoup("wa<b>s</b>"))
每当插入的部分包含复杂的HTML代码时,我不知道该如何用其他语法来替换它。仅仅使用
myi.replaceWith("wa<b>s</b>")
会把HTML中的特殊字符替换成实体。
3 个回答
2
我想我找到了一种解决办法,可以解决我遇到的问题。下面我会把整个代码再写一遍,作为一个完整的例子:
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()
请注意,如果不使用 reversed()
,这个方法是行不通的。如果你跳过这一步,不仅仅是元素的顺序会改变。如果你真的想改变顺序,你需要写以下代码:
for c in list(s2.contents):
myi.parent.insert(myi_id + 1, c)
有人能解释一下,为什么不使用 list()
会导致 <b>s</b>
被省略吗?(请在评论里回答,因为这不是这里的主要问题。)
3
这个问题看起来是因为一个 BeautifulSoup
对象被认为是整个文档。find
方法会遍历文档,询问每个元素后面还有什么元素。但是当它遇到你的 BeautifulSoup("was")
时,这个对象认为自己就是整个文档,所以它会说后面没有东西。这就导致搜索提早结束了。
我觉得 BeautifulSoup
并不是设计来让 BeautifulSoup
对象嵌套在其他 BeautifulSoup
对象里的。解决办法就是不要这样做。你为什么觉得需要用第一种形式,而不是已经能正常工作的第二种形式呢?如果你想用一些 HTML 替换一个元素,应该用 Tag
来替换,而不是用 BeautifulSoup
对象。
5
简单来说:在你调用了 replaceWith
之后,可以通过调用 s = BeautifulSoup(s.renderContents())
来重新生成并清理 s
。这样你就可以再次使用 find
了。