如何爬取airnow.gov的AQI数据?BeautifulSoup4获取aqi节点为空
问题现象
使用BeautifulSoup4爬取指定位置实时AQI数据时,执行以下代码后打印aqi变量只能得到空div标签,手动访问站点时该div内部实际存在包含AQI数值的子元素:
url = "https://www.airnow.gov/?city=Burlingame&state=CA&country=USA" header = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36", "Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8" } response = requests.get(url, headers=header) soup = BeautifulSoup(response.content, "lxml") aqi = soup.find("div", class_="aqi")
根本原因
该站点的AQI数值是JavaScript动态渲染填充的,requests发起请求只能拿到页面初始的静态HTML骨架,JS异步拉取AQI数据、填充到div元素的过程不会在普通请求中执行,所以BeautifulSoup解析初始响应内容时,只能抓到没有内容的空div壳。
可行解决方法
- 优先调用站点数据接口(最稳定高效)
打开浏览器开发者工具的网络面板,刷新页面就能找到站点拉取AQI数据的后端接口,接口直接返回结构化的JSON格式数据,直接构造请求调用接口拿值即可,不需要解析HTML,也不会受前端页面结构改版影响。 - 使用支持JS渲染的爬虫工具
如果需要从页面DOM提取内容,替换requests为可以执行页面JS的工具,等页面渲染完成后再做解析,可选工具包括requests-html、Playwright、Selenium。
以requests-html为例的参考实现:from requests_html import HTMLSession from bs4 import BeautifulSoup url = "https://www.airnow.gov/?city=Burlingame&state=CA&country=USA" header = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8" } session = HTMLSession() resp = session.get(url, headers=header) # 执行页面JS,等待动态内容加载 resp.html.render(timeout=5) soup = BeautifulSoup(resp.html.html, "lxml") aqi = soup.find("div", class_="aqi") - 小细节提醒
你代码里用的Chrome 84版本UA属于比较老旧的版本,部分站点会拦截这类特征明显的旧UA,返回异常页面,建议替换为近期版本的浏览器UA。
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

