我正在使用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/