爬取雅虎财经ESG数据时BeautifulSoup无法返回完整HTML怎么办
问题根因
BeautifulSoup本身没有解析故障,拿不到完整HTML的核心原因有两个:
- 原生
requests默认请求头的User-Agent带有爬虫标识,会被雅虎财经的反爬机制拦截,返回截断的异常页面而非正常站点内容 - 雅虎财经的ESG板块数据是前端JavaScript动态渲染生成的,
requests只能拉取页面初始的静态HTML骨架,不会执行页面内的JS脚本,传给BeautifulSoup的内容本身就缺失动态加载的ESG数据部分
修复方法
第一步:先补全模拟浏览器的请求头,绕过基础反爬
先给请求加上正常浏览器的请求头,测试是否能拿到完整静态内容:
import requests from bs4 import BeautifulSoup headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36", "Accept-Language": "en-GB,en;q=0.9" } resp = requests.get( "https://uk.finance.yahoo.com/quote/XOM/sustainability?p=XOM&.tsrc=fin-srch", headers=headers ) soup = BeautifulSoup(resp.content, "html.parser") # 打印内容长度判断是否拿到目标数据所在的DOM print(len(str(soup)))
如果补完请求头后,依然搜索不到ESG评分、环境风险这类相关DOM节点,说明目标数据为动态加载,需要使用可执行JS的工具获取渲染后的完整页面。
第二步:使用支持JS渲染的工具拉取完整页面
推荐使用Playwright驱动无头浏览器,等页面动态内容全部加载完成后再提取HTML,再交给BeautifulSoup解析:
- 先安装依赖:
pip install playwright beautifulsoup4 playwright install chromium
- 可直接运行的示例代码:
from playwright.sync_api import sync_playwright from bs4 import BeautifulSoup 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/125.0.0.0 Safari/537.36" ) page.goto("https://uk.finance.yahoo.com/quote/XOM/sustainability?p=XOM&.tsrc=fin-srch") # 等待ESG评分节点加载完成,确保拿到完整渲染的页面 page.wait_for_selector("div[data-testid='esg-cf-rating']", timeout=10000) full_html = page.content() browser.close() soup = BeautifulSoup(full_html, "html.parser") # 后续正常编写解析逻辑提取ESG数据即可 esg_rating = soup.find("div", {"data-testid": "esg-cf-rating"}).text.strip() print(f"当前XOM的ESG评级为:{esg_rating}")
更高效的替代方案
不需要解析HTML,打开浏览器开发者工具抓包,可以找到页面加载ESG数据时调用的后端接口,直接请求接口返回的结构化JSON数据,解析效率更高,也不会遇到动态渲染的问题。
注意事项
- 解析器选择
html.parser即可满足需求,更换lxml等其他解析器无法解决源HTML内容缺失的问题 - 请求频率不要过高,否则会触发雅虎财经的IP封禁,返回验证码或者空内容
内容的提问来源于stack exchange,提问作者Hanuman Rajagopal Kuntamukkula
相关产品推荐
相关产品推荐

