在BeautifulSoup中包装所有next_elements

时间:2013-07-12 00:35:35

标签: python beautifulsoup

我有一段像这样的HTML:

<figure>
    <img src=".." alt=".." />
    Some text that I have to wrap in <code>figcaption</code>
</figure>

我正在尝试将<img>后面的所有内容包装在<figcaption>中。这可能吗?

next_elements可以很好地获取我想要的元素,但返回一个生成器,它与wrap方法不能很好地配合。

1 个答案:

答案 0 :(得分:2)

这是一种方法:

>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup("""
... <figure>
...     <img src=".." alt=".." />
...     Some text that I have to wrap in <code>figcaption</code>
... </figure>
... """)
>>> for figure in soup.find_all("figure"):
...     img = figure.find("img")
...     if img is not None:
...         figcaption = soup.new_tag("figcaption")
...         for el in list(img.next_siblings):
...             figcaption.append(el)
...         img.insert_after(figcaption)
... 
>>> soup
<html><body><figure>
    <img alt=".." src=".."/><figcaption>
    Some text that I have to wrap in <code>figcaption</code>
</figcaption></figure></body></html>

有几点需要注意:

  1. 我们使用next_siblings,它只返回我们实际需要的元素,而不是next_elements,它将继续超过figure元素的末尾。

  2. 我们用next_siblings打包list()以创建一个我们可以迭代的浅副本 - 否则,因为将el附加到figcaption的行为会将其从它在文档树中的前一个位置,它将修改我们要迭代的序列,即a bad idea。我们本来可以使用find_next_siblings()(也会返回一个列表),但上面的版本更明确。

  3. 由于我们已经从文档树中以前的位置删除了img的所有下一个兄弟,我们需要做的就是附加figcaptionimg元素后面的(现在包含它们)。

  4. 空白的位置对于人类来说不再是直觉“正确”,但修复它需要大量的额外工作,而且可能不值得。