求助:使用Beautiful Soup抓取WSJ外汇历史价格表格失败的问题排查
问题分析与解决方案
错误原因
- 动态数据加载:WSJ的历史价格表格并非静态嵌入在初始HTML中,而是页面加载完成后通过AJAX请求动态渲染生成的。你用
requests.get()获取的只是页面的初始骨架代码,并不包含表格的实际数据,因此BeautifulSoup无法定位到目标标签。 - 选择器语法疏漏:代码1中
soup.select('cr_dataTable')缺少类选择器的前缀.,正确写法应为soup.select('.cr_dataTable'),但这并非核心问题——即便修正选择器,由于初始HTML里不存在该表格,结果依然为空。
解决方案
方法1:直接调用数据API(推荐)
通过浏览器开发者工具抓包,可找到WSJ获取历史价格的真实API接口,直接请求该接口能拿到结构化的CSV/JSON数据,比解析HTML更高效稳定。
示例代码:
import requests # 可调整参数:num_rows控制返回行数,range_days控制时间范围 params = { "num_rows": "30", "range_days": "30", "symbol": "AUDNZD" } api_url = "https://www.wsj.com/market-data/quotes/fx/AUDNZD/historical-prices/download" response = requests.get(api_url, params=params) # 解析CSV格式响应 lines = response.text.splitlines() # 跳过表头行,遍历数据行 for line in lines[1:]: date, close_price, open_price, high, low, change = line.split(',') print(f"日期: {date.strip()}, 收盘价: {close_price.strip()}, 涨跌幅: {change.strip()}")
方法2:使用Selenium模拟浏览器加载
若不想分析API,可借助Selenium模拟浏览器完整加载页面,等待动态数据渲染完成后再解析HTML。
示例代码:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from bs4 import BeautifulSoup url = "https://www.wsj.com/market-data/quotes/fx/AUDNZD/historical-prices" # 初始化Chrome浏览器(需提前安装对应版本的chromedriver) driver = webdriver.Chrome() driver.get(url) # 等待表格加载完成,最长等待10秒 wait = WebDriverWait(driver, 10) wait.until(EC.presence_of_element_located((By.CLASS_NAME, "cr_dataTable"))) # 获取加载完成后的页面源码 page_source = driver.page_source soup = BeautifulSoup(page_source, "html.parser") # 解析表格数据 table_rows = soup.find('table', class_='cr_dataTable').find_all('tr')[1:] # 跳过表头 for row in table_rows: cols = row.find_all('td') date = cols[0].text.strip() close_price = cols[1].text.strip() change = cols[5].text.strip() print(f"日期: {date}, 收盘价: {close_price}, 涨跌幅: {change}") # 关闭浏览器 driver.quit()
后续爬取注意事项
- 区分静态/动态页面:先通过
Ctrl+U查看页面源码,若找不到目标数据,说明是动态加载页面,需抓API或用浏览器模拟。 - 开发者工具抓包:用浏览器F12打开Network面板,筛选XHR/Fetch请求,定位加载数据的接口,分析请求参数和响应格式。
- 反爬应对:请求API时添加合理的请求头(如
User-Agent),避免频繁请求触发反爬机制导致IP被封。
内容的提问来源于stack exchange,提问作者aclark904
相关产品推荐
相关产品推荐

