使用BeautifulSoup爬取Shazam页面返回结构异常无法定位目标元素
问题原因
无法提取目标内容是三个问题叠加导致的:
- BeautifulSoup解析器拼写错误:代码中填写的解析器参数为
lmxl,正确的lxml解析器拼写为lxml,拼写错误会直接导致解析逻辑异常。 - 页面为JavaScript动态渲染:Shazam全球Top200榜单、页面h1标题、带指定class的内容块等所有核心元素,都是前端JavaScript在浏览器环境运行后才会插入到DOM结构中的。直接用
requests.get只能获取页面初始的空HTML骨架,不会执行任何JS脚本,自然拿不到渲染后的实际内容。 - 请求缺少合法身份标识:requests默认的请求UA特征非常明显,会直接被Shazam的反爬策略识别,返回的是拦截后的异常页面,而非普通用户看到的正常站点内容。
解决方案
方案1:直接调用站点数据接口(推荐,效率最高)
Shazam加载榜单时会调用内置公开JSON接口,直接请求该接口就能拿到结构化的榜单数据,不需要解析HTML,稳定性和运行效率都更高。
示例代码:
import requests # 页面加载时拉取榜单数据的内置接口 chart_url = "https://www.shazam.com/shazam/v3/en-US/US/web/-/tracks/world-chart-world" # 携带真实浏览器请求头,避免被反爬拦截 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" } resp = requests.get(chart_url, headers=headers) resp.raise_for_status() chart_data = resp.json() # 直接遍历返回的JSON即可拿到所有榜单信息 for rank, track in enumerate(chart_data["tracks"], start=1): track_name = track["title"] artist = track["subtitle"] print(f"第{rank}位:{track_name} - {artist}")
如果后续接口地址发生变动,可以打开浏览器开发者工具的「网络」面板,筛选Fetch/XHR请求,找到返回榜单数据的请求替换对应地址即可。
方案2:用无头浏览器渲染页面后解析
如果确实需要提取渲染后的HTML页面元素,可以用Playwright这类无头浏览器工具,模拟真实浏览器加载页面、执行完所有JS脚本后再提取内容。
先安装依赖:
pip install playwright playwright install chromium
示例代码:
from bs4 import BeautifulSoup from playwright.sync_api import sync_playwright target_url = "https://www.shazam.com/charts/top-200/world" with sync_playwright() as p: # 启动无头浏览器 browser = p.chromium.launch(headless=True) page = browser.new_page( user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" ) # 跳转到目标页,等待所有网络请求加载完成 page.goto(target_url, wait_until="networkidle") # 获取渲染完成的完整HTML源码 full_html = page.content() browser.close() # 注意解析器正确拼写为lxml soup = BeautifulSoup(full_html, "lxml") # 此时即可正常提取h1、携带指定class属性的各类目标元素 page_title = soup.find("h1").text print(page_title)
注意:爬取站点内容请遵守目标站点的robots协议和相关使用条款,控制请求频率,避免对站点正常运行造成影响。
内容的提问来源于stack exchange,提问作者Tayla Corney
相关产品推荐
相关产品推荐

