如何修改Python代码获取雅虎财经资产负债表的详细展开数据?
解决雅虎财经资产负债表展开数据爬取问题
我来帮你搞定这个问题——雅虎财经的资产负债表默认只显示汇总数据,那些明细行是折叠状态的,你现在的代码只能抓取页面初始加载的静态内容,而展开后的明细是通过动态加载(AJAX)生成的,所以自然拿不到。下面给你两种实用的解决方案:
方法一:用Selenium模拟点击展开(适合不想研究API的场景)
Selenium可以模拟浏览器的真实操作,点击"Expand All"按钮后等待动态内容加载完成,再抓取完整的表格数据。
步骤&代码示例
- 先安装依赖包:
pip install selenium numpy
同时要下载对应浏览器的驱动(比如ChromeDriver),确保驱动路径能被Python识别到。
- 修改后的完整爬取代码:
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 import numpy as np # 初始化Chrome浏览器(可替换为Firefox等) driver = webdriver.Chrome() # 替换为目标股票的资产负债表页面,比如苹果(AAPL) url = "https://finance.yahoo.com/quote/AAPL/balance-sheet?p=AAPL" driver.get(url) try: # 等待"Expand All"按钮加载完成并点击 expand_btn = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Expand All')]")) ) expand_btn.click() # 等待明细数据加载(也可以用更精准的元素等待条件) driver.implicitly_wait(5) # 对接你原来的解析逻辑 table_rows = driver.find_elements(By.XPATH, "//div[@data-test='fin-row']") parsed_rows = [] for table_row in table_rows: parsed_row = [] el = table_row.find_elements(By.XPATH, "./div") none_count = 0 for rs in el: try: text = rs.find_element(By.XPATH, ".//span").text parsed_row.append(text) except: parsed_row.append(np.NaN) none_count += 1 if none_count < 4: parsed_rows.append(parsed_row) finally: # 关闭浏览器 driver.quit() # 查看结果 for row in parsed_rows: print(row)
方法二:直接调用雅虎财经API(更高效,推荐)
雅虎财经网页的财务数据其实是通过官方API获取的,直接请求API可以绕过动态渲染的问题,速度更快也更稳定。
代码示例
import requests import numpy as np # 替换为目标股票代码 ticker = "AAPL" # API地址:modules参数可选balanceSheetHistory(年度数据)或balanceSheetHistoryQuarterly(季度数据) url = f"https://query1.finance.yahoo.com/v10/finance/quoteSummary/{ticker}?modules=balanceSheetHistory" # 添加请求头避免被拦截 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" } response = requests.get(url, headers=headers) data = response.json() # 解析资产负债表结构化数据 balance_sheet = data["quoteSummary"]["result"][0]["balanceSheetHistory"]["balanceSheetStatements"] parsed_rows = [] for statement in balance_sheet: row = [] # 按需提取字段,比如现金、应收账款、存货等 row.append(statement.get("cash", {}).get("raw", np.NaN)) row.append(statement.get("netReceivables", {}).get("raw", np.NaN)) row.append(statement.get("inventory", {}).get("raw", np.NaN)) row.append(statement.get("totalCurrentAssets", {}).get("raw", np.NaN)) parsed_rows.append(row) # 打印解析结果 for row in parsed_rows: print(row)
说明
- API返回的是JSON格式的结构化数据,你可以根据需求自由提取任意字段,比解析HTML灵活得多。
- 一定要添加
User-Agent请求头,否则很容易被网站拦截。
原代码问题分析
你原来的代码只解析了页面初始HTML中的表格行,但雅虎财经的明细行默认是隐藏的,只有点击"Expand All"后才会通过AJAX加载到页面DOM中,所以初始HTML里根本没有这些行,自然抓取不到。
内容的提问来源于stack exchange,提问作者Seyl




