python - 在循环中调用 extract 时跳过的元素

标签 python html loops beautifulsoup

我正在使用extract删除循环中的 HTML 元素,但这会导致元素被跳过。

例如,

data = """<div><p class="1">1</p><p class="2">2</p><p class="3">3</p></div>"""
soup = BeautifulSoup(data)
div = soup.div
for p in div.contents: # or use for p in div.children:, with the same result
    print(p)
    if '2' in p.attrs['class']:
        p.extract()
    print(p)
    print("\n")

从下面的输出中我们可以看到<p class="3">3</p>未打印。

<p class="1">1</p>
<p class="1">1</p>

<p class="2">2</p>
<p class="2">2</p>

但是,我可以看到div在循环结束后被修改了:

div
<div><p class="1">1</p><p class="3">3</p></div>

为什么第三个元素没有打印?

最佳答案

当调用.extract时,div.contents列表被修改,长度缩短1。然后下一个元素成为当前元素,并在以下情况下被跳过:迭代器向前移动。一般来说,避免在迭代列表时修改列表。

一种解决方案是当您计划提取元素时复制 div.contents 进行迭代。元素对象仍将引用原始 div.contents 列表,因此调用 p.extract 仍将修改原始列表,但不会打乱别名列表的顺序。正在被迭代。

from bs4 import BeautifulSoup

data = """<div><p class="1">1</p><p class="2">2</p><p class="3">3</p></div>"""
soup = BeautifulSoup(data, "html.parser")
div = soup.div

for p in div.contents[:]:
#                    ^~~
    print(p)

    if '2' in p.attrs['class']:
        p.extract()

    print(p, "\n")

print("after:", div.contents)

输出:

<p class="1">1</p>
<p class="1">1</p>

<p class="2">2</p>
<p class="2">2</p>

<p class="3">3</p>
<p class="3">3</p>

after: [<p class="1">1</p>, <p class="3">3</p>]

关于python - 在循环中调用 extract 时跳过的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59004792/

相关文章:

python - 使第二列的数据保留在第二列

python - 带有群图的 Seaborn PairGrid

html - 在 GWT 中将小部件(按钮)添加到 HTML5 Canvas

html - 将垂直旋转的文本与水平文本对齐

php - 在已经运行的查询循环中从第二个表调用循环查询

python - 通过 FFI 调用 Rust 函数时发生访问冲突

python - 正则表达式:查找单词但不允许重复

javascript - 点击子元素

c - 这个循环是无限的,但它不应该是 - C

java - 如何从文本文件中搜索名称