如何修改VBA的objRequest传递账号密码登录Yahoo Finance下载数据
解决Yahoo Finance需登录才能下载历史股价的VBA代码修改方案
近期Yahoo Finance已限制未登录用户下载历史股票价格数据,原有下载宏会返回“用户未登录”提示。要解决这个问题,不能直接简单POST账号密码到登录页——Yahoo的登录流程需要处理CSRF令牌和会话Cookie,以下是完整的修改方案:
核心思路
- 先访问Yahoo登录页面,获取登录所需的CSRF令牌和初始Cookie
- 携带令牌、账号密码提交登录请求,保存登录后的有效会话Cookie
- 使用该会话Cookie发起股价数据下载请求
完整VBA代码
Sub DownloadYahooStockDataWithLogin() Dim stockTicker As String Dim startDate As String, endDate As String Dim frequency As String Dim resultFromYahoo As String ' 配置参数 stockTicker = "AAPL" ' 替换为目标股票代码 startDate = "1609459200" ' 起始时间戳(Unix时间) endDate = "1735689600" ' 结束时间戳(Unix时间) frequency = "1d" ' 数据频率:1d=日K,1wk=周K,1mo=月K Dim loginHttp As Object, dataHttp As Object Dim loginUrl As String, postData As String Dim csrfToken As String, cookies As String ' 1. 初始化登录请求对象,获取CSRF令牌和初始Cookie Set loginHttp = CreateObject("WinHttp.WinHttpRequest.5.1") loginUrl = "https://login.yahoo.com" With loginHttp .Open "GET", loginUrl, False .Send .WaitForResponse ' 提取CSRF令牌(从页面HTML中匹配) csrfToken = ExtractCSRFToken(.ResponseText) ' 保存初始Cookie cookies = .GetResponseHeader("Set-Cookie") End With If csrfToken = "" Then MsgBox "无法获取CSRF令牌,登录失败" Exit Sub End If ' 2. 提交登录请求 postData = "username=你的Yahoo账号&passwd=你的Yahoo密码&csrfToken=" & csrfToken & "&sessionIndex=0" With loginHttp .Open "POST", "https://login.yahoo.com/login", False .SetRequestHeader "Content-Type", "application/x-www-form-urlencoded" .SetRequestHeader "Cookie", cookies .Send postData .WaitForResponse ' 更新会话Cookie(登录后的有效Cookie) cookies = cookies & "; " & .GetResponseHeader("Set-Cookie") End With ' 3. 携带登录Cookie请求股价数据 Dim tickerURL As String tickerURL = "https://query1.finance.yahoo.com/v7/finance/download/" & stockTicker & _ "?period1=" & startDate & _ "&period2=" & endDate & _ "&interval=" & frequency & "&events=history" Set dataHttp = CreateObject("WinHttp.WinHttpRequest.5.1") With dataHttp .Open "GET", tickerURL, False .SetRequestHeader "Cookie", cookies .Send .WaitForResponse resultFromYahoo = .ResponseText ' 这里可以添加将resultFromYahoo写入Excel工作表的代码 ' 例如:Sheets("Sheet1").Range("A1").Value = resultFromYahoo MsgBox "数据下载完成" End With ' 清理对象 Set loginHttp = Nothing Set dataHttp = Nothing End Sub ' 辅助函数:从登录页面HTML提取CSRF令牌 Function ExtractCSRFToken(htmlText As String) As String Dim regex As Object Set regex = CreateObject("VBScript.RegExp") With regex .Pattern = """csrfToken"":""([^""]+)""" .Global = False .IgnoreCase = True End With Dim matches As Object Set matches = regex.Execute(htmlText) If matches.Count > 0 Then ExtractCSRFToken = matches(0).SubMatches(0) Else ExtractCSRFToken = "" End If End Function
注意事项
- 替换代码中的
你的Yahoo账号和你的Yahoo密码为实际账号密码 - 时间戳需转换为Unix时间格式(从1970年1月1日到目标日期的秒数)
- 如果Yahoo更新登录页面结构,可能需要调整
ExtractCSRFToken函数中的正则表达式 - 频繁请求可能触发Yahoo的反机制,建议控制请求频率
内容的提问来源于stack exchange,提问作者Kurt Fichthorn
相关产品推荐
相关产品推荐

