You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用BeautifulSoup的find_all按标签列表查询时无法获取后续目标

问题描述

执行以下代码:

from bs4 import BeautifulSoup
soup = BeautifulSoup("<html><body><p>111</p><p>before<ul><li>222</li></ul>after</p></body></html>", "lxml")
soup.find_all(["p", "li"])

得到结果:

[<p>111</p>, <p>before</p>, <li>222</li>]

期望结果中能包含“after”文本,要么作为第二个<p>元素的一部分,要么作为列表的第四个条目。

疑问1:这是预期行为吗?有没有办法获取“after”文本?

另外执行print(soup.prettify())后得到以下结果:

<html>
 <body>
  <p>
   111
  </p>
  <p>
   before
  </p>
  <ul>
   <li>
    222
   </li>
  </ul>
  after
 </body>
</html>

此时<ul>和“after”不再属于第二个<p>元素,推测是无效HTML导致的,但仍有疑问:

疑问2:除了丢弃“after”外,有没有办法处理这种情况?


解答

1. 这是预期行为

HTML规范中,<p>是块级元素,不能嵌套其他块级元素(比如<ul>)。lxml作为HTML解析器会自动修正这种无效嵌套:当遇到<p>内部的<ul>时,会直接闭合前面的<p>标签,把<ul>移到<p>外面,原<p>的闭合标签会被忽略,导致“after”变成<body>下的独立文本节点,不在任何<p>或<li>标签内,所以soup.find_all(["p", "li"])无法捕获它。

2. 获取“after”文本的方法

  • 提取所有文本节点:直接获取<body>下的所有非空白文本内容
    text_nodes = [node for node in soup.body.stripped_strings]
    print(text_nodes)  # 输出: ['111', 'before', '222', 'after']
    
  • 定位兄弟文本节点:找到<ul>之后的相邻文本节点
    ul_tag = soup.find("ul")
    after_text = ul_tag.next_sibling.strip()
    print(after_text)  # 输出: 'after'
    
  • 换用html5lib解析器:该解析器对无效HTML的容错性更强,会保留原嵌套结构
    先安装依赖:pip install html5lib
    执行代码:
    from bs4 import BeautifulSoup
    soup = BeautifulSoup("<html><body><p>111</p><p>before<ul><li>222</li></ul>after</p></body></html>", "html5lib")
    print(soup.find_all(["p", "li"]))
    # 输出: [<p>111</p>, <p>before<ul><li>222</li></ul>after</p>, <li>222</li>]
    

3. 保留原结构意图的手动修正(基于lxml)

如果必须用lxml解析,可手动调整DOM结构,把“after”归回原<p>:

from bs4 import BeautifulSoup
soup = BeautifulSoup("<html><body><p>111</p><p>before<ul><li>222</li></ul>after</p></body></html>", "lxml")

second_p = soup.find_all("p")[1]
ul_tag = soup.find("ul")
# 提取after文本并添加到第二个p中
after_text = ul_tag.next_sibling.strip()
second_p.append(after_text)
# 将ul移回第二个p内部
second_p.append(ul_tag)

print(soup.find_all(["p", "li"]))
# 输出: [<p>111</p>, <p>beforeafter<ul><li>222</li></ul></p>, <li>222</li>]

内容的提问来源于stack exchange,提问作者steffen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 21:22:28