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

为何使用BeautifulSoup提取标签时结果数量多于实际存在的标签?

问题:BeautifulSoup解析牛津词典页面时返回标签数量多于页面实际显示

我用Python的BeautifulSoup从牛津学习者词典提取单词音频,代码如下:

#!/bin/python3

import sys
import requests
from bs4 import BeautifulSoup

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.5',
    'DNT': '1',
    'Connection': 'keep-alive',
    'Upgrade-Insecure-Requests': '1',
    'Sec-Fetch-Dest': 'document',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-Site': 'none',
    'Sec-Fetch-User': '?1',
}

response = requests.get(sys.argv[1], headers=headers)

print("HTTP Response Status Code:", response.status_code)

soup = BeautifulSoup(response.content, "html.parser")

print(list(soup.find(class_="phonetics")))

运行命令:

./english_audio.py "https://www.oxfordlearnersdictionaries.com/definition/english/hello_1?q=hello"

发现BeautifulSoup返回的标签数量比浏览器页面实际显示的多,请问原因是什么?


原因分析及解决建议

核心原因

  1. 原始HTML与浏览器渲染DOM的差异
    requests获取的是服务器直接返回的原始HTML,而浏览器会执行页面中的JavaScript动态生成内容,同时自动修复不规范的HTML(比如补全未闭合标签)。此外,BeautifulSoup在解析时也会自动修正语法错误、补全缺失结构,这会导致解析后的标签数量比你在浏览器Elements面板看到的渲染后DOM要多。

  2. 页面存在隐藏元素
    原始HTML中可能包含一些通过CSS(如display: none)隐藏的元素,这些元素在浏览器页面上不可见,但requests能获取到完整的HTML内容,所以BeautifulSoup会解析出这些隐藏标签,造成数量差异。

  3. HTML解析器的特性
    你使用的是Python内置的html.parser,它对不规范HTML的容错和修正逻辑和浏览器不同,可能会生成额外标签来保证DOM结构完整性。换成lxml或html5lib这类解析器,结果可能更接近浏览器的渲染结构。

解决建议

  • 对比原始HTML与页面源代码
    直接打印response.text查看requests获取的原始HTML,再和浏览器中「查看页面源代码」(不是Elements面板的DOM)对比,确认额外标签是否本来就存在于原始响应中。

  • 处理动态加载内容
    如果页面的音频元素是通过JavaScript动态加载的,仅用requests无法获取到,这时需要用Selenium、Playwright这类工具模拟浏览器执行JS后,再获取完整的DOM进行解析。

  • 更换解析器
    安装lxml或html5lib后,修改BeautifulSoup的初始化代码:

# 使用lxml解析器
soup = BeautifulSoup(response.content, "lxml")
# 或使用html5lib解析器
soup = BeautifulSoup(response.content, "html5lib")

这类解析器的HTML修正逻辑更接近浏览器,能减少不必要的额外标签。

  • 精准定位音频元素
    牛津词典的音频链接通常存放在带有audio_play_button类的标签的data-src属性中,直接定位这类元素可以避免无关标签的干扰:
phonetics = soup.find(class_="phonetics")
if phonetics:
    audio_buttons = phonetics.find_all(class_="audio_play_button")
    for btn in audio_buttons:
        audio_url = btn.get("data-src")
        if audio_url:
            print("音频链接:", audio_url)

内容的提问来源于stack exchange,提问作者Amirreza A.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 10:57:25