如何用Python和Xpath爬取雅虎财经5天股票历史价格?
解决重复获取首日股价的问题
你遇到的核心问题是代码里的URL根本没随着日期变化——你的start_url没有预留格式化占位符(比如{}),所以url = start_url.format(start.strftime("%Y%m%d"))这一行完全没生效,每次循环请求的都是同一个当前报价页面,自然输出的都是同一天的价格。
下面给你两种可行的修改方案,按需选择:
方案一:一次性获取过去5天数据(更高效)
直接请求股票的历史数据页面,一次性提取时间范围内的所有日线数据,避免多次请求:
import requests from lxml import html from datetime import datetime, timedelta # 计算时间范围:取最近7天(多留2天排除周末/节假日休市) end_date = datetime.now() start_date = end_date - timedelta(days=7) # 转换为Unix时间戳(Yahoo Finance接口需要) period1 = int(start_date.timestamp()) period2 = int(end_date.timestamp()) # 构造历史数据页面URL url = f"https://in.finance.yahoo.com/quote/HINDUNILVR.NS/history?period1={period1}&period2={period2}&interval=1d&filter=history&frequency=1d&includeAdjustedClose=true" page = requests.get(url) tree = html.fromstring(page.content) # 提取历史表格中的收盘价(XPath对应页面结构,若页面更新需微调) rows = tree.xpath('//table[@data-test="historical-prices"]/tbody/tr') prices = [] for row in rows[:5]: close_price = row.xpath('./td[5]/span/text()') # 第5列对应收盘价 if close_price: prices.append(close_price) # 输出结果 for price in prices: print(price)
方案二:循环请求单个日期数据(贴合你的原始思路)
如果坚持要按天循环请求,需要构造每个日期对应的历史数据URL,确保每次请求的页面是对应日期的:
import requests from lxml import html from datetime import datetime,timedelta # 起始日期(替换成你需要的开始日期) start = datetime(2024, 5, 20) prices = [] for _ in range(5): # 构造单个日期的历史数据URL:只请求当天的范围 period1 = int(start.timestamp()) period2 = int((start + timedelta(days=1)).timestamp()) url = f"https://in.finance.yahoo.com/quote/HINDUNILVR.NS/history?period1={period1}&period2={period2}&interval=1d&filter=history&frequency=1d&includeAdjustedClose=true" page = requests.get(url) tree = html.fromstring(page.content) # 提取当天收盘价 close_price = tree.xpath('//table[@data-test="historical-prices"]/tbody/tr/td[5]/span/text()') if close_price: prices.append(close_price[0]) # 日期往前推一天 start -= timedelta(days=1) # 反转列表,让结果按从新到旧的顺序展示 prices.reverse() print([[price] for price in prices])
注意事项
- Yahoo Finance的页面结构可能会更新,如果XPath提取不到数据,需要打开页面检查元素,调整XPath路径。
- 股市在周末、节假日休市,这些日期不会有数据,代码里加了空值判断避免报错。
内容的提问来源于stack exchange,提问作者MUKUNDHAN JAYARAMAN




