雅虎财经url无效

我已经使用以下URL从雅虎财经获取历史数据很长一段时间了,但从昨天开始停止工作。

https://ichart.finance.yahoo.com/table.csv?s=SPY

当浏览到这个网站时说:

马上回来…

感谢您的耐心等待。

我们的工程师正在尽快解决问题。

但是,由于这个问题自昨天以来依然存在,我开始认为他们已经停止了这项服务?

我的SOsearch只是指出了这个话题 ,这是相关的https虽然…

有没有人遇到这个问题? 我该如何解决这个问题? 他们是否提供了不同的访问他们的历史数据?

看起来他们已经开始添加一个必需的cookie,但是您可以很容易地检索这个cookie,例如:

GET https://uk.finance.yahoo.com/quote/AAPL/history 

以下面的forms回应标题:

 set-cookie:B=xxxxxxxx&b=3&s=qf; expires=Fri, 18-May-2018 00:00:00 GMT; path=/; domain=.yahoo.com 

您应该能够阅读并附加到您的.csv请求:

 GET https://query1.finance.yahoo.com/v7/finance/download/AAPL?period1=1492524105&period2=1495116105&interval=1d&events=history&crumb=tO1hNZoUQeQ cookie: B=xxxxxxxx&b=3&s=qf; 

注意crumb查询参数,这似乎对应于您的cookie在某种程度上。 你最好的select是从HTML中scrape这个。 如果你看HTML的响应,你可以做一个正则expression式search: "CrumbStore":\{"crumb":"(?<crumb>[^"]+)"\}并且提取crumb匹配的组。

它看起来像是一旦你有这个面值的价值,虽然你可以使用它与下一年的任何符号/股票相同的cookie ,这意味着你不应该过于频繁scrape


要获得当前的报价只是加载:

https://query1.finance.yahoo.com/v8/finance/chart/AAPL?interval=2m

附:

  • AAPL取代您的股票报价
  • 间隔[1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo]
  • 可选的period1查询参数与你的历元范围开始date,例如period1=1510340760
  • 可选的period2查询参数与你的历元范围结束date,例如period2=1510663712

在此论坛中: https : //forums.yahoo.net/t5/Yahoo-Finance-help/Is-Yahoo-Finance-API-broken/td-p/250503/page/3

尼克松说:

大家好 – 这个function已经被财务小组终止了,他们不会重新引入这个function。

我设法找出一个.NET类来从Yahoo Finance获得有效的令牌(cookie和crumb)

从完整的Yahoo Finance获取历史数据的完整API库,您可以访问Github上的YahooFinanceAPI

这里是抓取cookies和面包屑的类

Token.cs

 using System; using System.Diagnostics; using System.Net; using System.IO; using System.Text.RegularExpressions; namespace YahooFinanceAPI { /// <summary> /// Class for fetching token (cookie and crumb) from Yahoo Finance /// Copyright Dennis Lee /// 19 May 2017 /// /// </summary> public class Token { public static string Cookie { get; set; } public static string Crumb { get; set; } private static Regex regex_crumb; /// <summary> /// Refresh cookie and crumb value Yahoo Fianance /// </summary> /// <param name="symbol">Stock ticker symbol</param> /// <returns></returns> public static bool Refresh(string symbol = "SPY") { try { Token.Cookie = ""; Token.Crumb = ""; string url_scrape = "https://finance.yahoo.com/quote/{0}?p={0}"; //url_scrape = "https://finance.yahoo.com/quote/{0}/history" string url = string.Format(url_scrape, symbol); HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); request.CookieContainer = new CookieContainer(); request.Method = "GET"; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { string cookie = response.GetResponseHeader("Set-Cookie").Split(';')[0]; string html = ""; using (Stream stream = response.GetResponseStream()) { html = new StreamReader(stream).ReadToEnd(); } if (html.Length < 5000) return false; string crumb = getCrumb(html); html = ""; if (crumb != null) { Token.Cookie = cookie; Token.Crumb = crumb; Debug.Print("Crumb: '{0}', Cookie: '{1}'", crumb, cookie); return true; } } } catch (Exception ex) { Debug.Print(ex.Message); } return false; } /// <summary> /// Get crumb value from HTML /// </summary> /// <param name="html">HTML code</param> /// <returns></returns> private static string getCrumb(string html) { string crumb = null; try { //initialize on first time use if (regex_crumb == null) regex_crumb = new Regex("CrumbStore\":{\"crumb\":\"(?<crumb>.+?)\"}", RegexOptions.CultureInvariant | RegexOptions.Compiled, TimeSpan.FromSeconds(5)); MatchCollection matches = regex_crumb.Matches(html); if (matches.Count > 0) { crumb = matches[0].Groups["crumb"].Value; } else { Debug.Print("Regex no match"); } //prevent regex memory leak matches = null; } catch (Exception ex) { Debug.Print(ex.Message); } GC.Collect(); return crumb; } } } 

更新1 6月17日
学分到@ Ed0906
修改crumb正则expression式模式为Regex("CrumbStore\":{\"crumb\":\"(?<crumb>.+?)\"}"

下载历史数据的URL现在是这样的:

https://query1.finance.yahoo.com/v7/finance/download/SPY?period1=1492449771&period2=1495041771&interval=1d&events=history&crumb=9GaimFhz.WU

请注意,上述url不适用于您或其他人。 你会得到这样的东西:

 { "finance": { "error": { "code": "Unauthorized", "description": "Invalid cookie" } } } 

看来,雅虎现在正在使用一些哈希来阻止人们像访问数据一样访问数据。 URL随每个会话而变化,所以很有可能您不能使用固定的URL来完成此操作。

您需要做一些报废以从主页面获取正确的URL,例如:

https://finance.yahoo.com/quote/SPY/history?p=SPY

对于那里的python爱好者,我更新了tradingWithPython库中的yahooFinance.py。

还有一个基于Ed0906技巧的示例笔记本 ,演示了如何逐步获取数据。 看到它

我在同一条船上 慢慢到达那里。 历史价格页面上的下载链接仍然有效。 所以我添加了导出cookies扩展到Firefox,login到雅虎,倾销的cookies。 使用来自交互式会话的crumb值,我能够检索值。 这是testingperl脚本的一部分工作。

 use Time::Local; # create unix time variables for start and end date values: 1/1/2014 thru 12/31/2017 $p1= timelocal(0,0,0,1,0,114); $p2= timelocal(0,0,0,31,11,117); $symbol = 'AAPL'; # create variable for string to be executed as a system command # cookies.txt exported from firefox # crumb variable retrieved from yahoo download data link $task = "wget --load-cookies cookies.txt --no-check-certificate -T 30 -O $symbol.csv \"https://query1.finance.yahoo.com/v7/finance/download/$symbol?period1=$p1&period2=$p2&interval=1d&events=history&crumb=7WhHVu5N4e3\" "; #show what we're executing print $task; # execute system command using backticks `$task`; #output is AAPL.csv 

自动化我所做的工作需要一段时间。 希望雅虎能够简化或给出一些指导,如果他们真的打算让人们使用它。

对于java爱好者。

您可以通过这种方式从URLConnection访问您的Cookie。

  // "https://finance.yahoo.com/quote/SPY"; URLConnection con = url.openConnection(); ... for (Map.Entry<String, List<String>> entry : con.getHeaderFields().entrySet()) { if (entry.getKey() == null || !entry.getKey().equals("Set-Cookie")) continue; for (String s : entry.getValue()) { // store your cookie ... } } 

现在你可以search雅虎网站的面包屑:

 String crumb = null; InputStream inStream = con.getInputStream(); InputStreamReader irdr = new InputStreamReader(inStream); BufferedReader rsv = new BufferedReader(irdr); Pattern crumbPattern = Pattern.compile(".*\"CrumbStore\":\\{\"crumb\":\"([^\"]+)\"\\}.*"); String line = null; while (crumb == null && (line = rsv.readLine()) != null) { Matcher matcher = crumbPattern.matcher(line); if (matcher.matches()) crumb = matcher.group(1); } rsv.close(); 

最后,设置cookie

 String quoteUrl = "https://query1.finance.yahoo.com/v7/finance/download/IBM?period1=1493425217&period2=1496017217&interval=1d&events=history&crumb=" + crumb ... List<String> cookies = cookieStore.get(key); if (cookies != null) { for (String c: cookies) con.setRequestProperty("Cookie", c); } ... con.connect(); 

完整的PHP示例 ,基于这篇文章和相关资源:

 function readYahoo($symbol, $tsStart, $tsEnd) { preg_match('"CrumbStore\":{\"crumb\":\"(?<crumb>.+?)\"}"', file_get_contents('https://uk.finance.yahoo.com/quote/' . $symbol), $crumb); // can contain \uXXXX chars if (!isset($crumb['crumb'])) return 'Crumb not found.'; $crumb = json_decode('"' . $crumb['crumb'] . '"'); // \uXXXX to UTF-8 foreach ($http_response_header as $header) { if (0 !== stripos($header, 'Set-Cookie: ')) continue; $cookie = substr($header, 14, strpos($header, ';') - 14); // after 'B=' } // cookie looks like "fkjfom9cj65jo&b=3&s=sg" if (!isset($cookie)) return 'Cookie not found.'; $fp = fopen('https://query1.finance.yahoo.com/v7/finance/download/' . $symbol . '?period1=' . $tsStart . '&period2=' . $tsEnd . '&interval=1d' . '&events=history&crumb=' . $crumb, 'rb', FALSE, stream_context_create(array('http' => array('method' => 'GET', 'header' => 'Cookie: B=' . $cookie)))); if (FALSE === $fp) return 'Can not open data.'; $buffer = ''; while (!feof($fp)) $buffer .= implode(',', fgetcsv($fp, 5000)) . PHP_EOL; fclose($fp); return $buffer; } 

用法

 $csv = readYahoo('AAPL', mktime(0, 0, 0, 6, 2, 2017), mktime(0, 0, 0, 6, 3, 2017)); 

我是这项服务的作者

基本信息在这里

每日价格

您需要熟悉RESTFUL服务。

https://quantprice.herokuapp.com/api/v1.1/scoop/day?tickers=MSFT&date=2017-06-09

历史价格

你必须提供一个date范围:

https://quantprice.herokuapp.com/api/v1.1/scoop/period?tickers=MSFT&begin=2012-02-19&end=2012-02-20

如果你不提供开始或结束,它将使用最早或最近的date:

https://quantprice.herokuapp.com/api/v1.1/scoop/period?tickers=MSFT&begin=2012-02-19

多个代号

你可以用逗号分开代号:

https://quantprice.herokuapp.com/api/v1.1/scoop/period?tickers=IBM,MSFT&begin=2012-02-19

速率限制

所有请求的速率限制为每小时10个请求。 如果你想注册一个完整的访问API在微博上给我发送DM。 您将收到一个API密钥以添加到URL中。

我们正在build立一个没有利率付费订阅的PayPal帐户。

可用的代号列表

https://github.com/robomotic/valueviz/blob/master/scoop_tickers.csv

我也正在从EDGAR提供基础数据和公司数据。 干杯。

VBA

下面是一些VBA函数,它们下载并提取cookie / crumb对,并将它们返回到Collection ,然后使用它们下载特定代码的csv文件内容。

包含的项目应该有一个对“Microsoft XML,v6.0”库的引用(其他版本可能没有问题,只需对代码稍作修改)。

 Sub Test() Dim X As Collection Set X = FindCookieAndCrumb() Debug.Print X!cookie Debug.Print X!crumb Debug.Print YahooRequest("AAPL", DateValue("31 Dec 2016"), DateValue("30 May 2017"), X) End Sub Function FindCookieAndCrumb() As Collection ' Tools - Reference : Microsoft XML, v6.0 Dim http As MSXML2.XMLHTTP60 Dim cookie As String Dim crumb As String Dim url As String Dim Pos1 As Long Dim X As String Set FindCookieAndCrumb = New Collection Set http = New MSXML2.ServerXMLHTTP60 url = "https://finance.yahoo.com/quote/MSFT/history" http.Open "GET", url, False ' http.setProxy 2, "https=127.0.0.1:8888", "" ' http.setRequestHeader "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" ' http.setRequestHeader "Accept-Encoding", "gzip, deflate, sdch, br" ' http.setRequestHeader "Accept-Language", "en-ZA,en-GB;q=0.8,en-US;q=0.6,en;q=0.4" http.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36" http.send X = http.responseText Pos1 = InStr(X, "CrumbStore") X = Mid(X, Pos1, 44) X = Mid(X, 23, 44) Pos1 = InStr(X, """") X = Left(X, Pos1 - 1) FindCookieAndCrumb.Add X, "Crumb" '====================================== X = http.getResponseHeader("set-cookie") Pos1 = InStr(X, ";") X = Left(X, Pos1 - 1) FindCookieAndCrumb.Add X, "Cookie" End Function Function YahooRequest(ShareCode As String, StartDate As Date, EndDate As Date, CookieAndCrumb As Collection) As String ' Tools - Reference : Microsoft XML, v6.0 Dim http As MSXML2.XMLHTTP60 Dim cookie As String Dim crumb As String Dim url As String Dim UnixStartDate As Long Dim UnixEndDate As Long Dim BaseDate As Date Set http = New MSXML2.ServerXMLHTTP60 cookie = CookieAndCrumb!cookie crumb = CookieAndCrumb!crumb BaseDate = DateValue("1 Jan 1970") If StartDate = 0 Then StartDate = BaseDate UnixStartDate = (StartDate - BaseDate) * 86400 UnixEndDate = (EndDate - BaseDate) * 86400 url = "https://query1.finance.yahoo.com/v7/finance/download/" & ShareCode & "?period1=" & UnixStartDate & "&period2=" & UnixEndDate & "&interval=1d&events=history&crumb=" & crumb http.Open "GET", url, False http.setRequestHeader "Cookie", cookie http.send YahooRequest = http.responseText End Function 

我使用了一个使用fopen()来访问财务数据的php脚本,下面是我修改后的代码片段,

创build开始date和结束date的时间戳:

 $timestampStart = mktime(0,0,0,$startMonth,$startDay,$startYear); $timestampEnd = mktime(0,0,0,$endMonth,$endDay,$endYear); 

强制fopen()发送硬编码值所需的cookie:

 $cookie="YourCookieTakenFromYahoo"; $opts = array( 'http'=>array( 'method'=>"GET", 'header'=>"Accept-language: en\r\n" . "Cookie: B=".$cookie."\r\n" ) ); $context = stream_context_create($opts); 

使用fopen()获取csv文件:

 $ticker="TickerSymbol"; $crumb="CrumbValueThatMatchesYourCookieFromYahoo"; $handle = fopen("https://query1.finance.yahoo.com/v7/finance/download/".$ticker."?period1=".$timestampStart."&period2=".$timestampEnd."&interval=1d&events=history&crumb=".$crumb."", "r", false, $context); 

现在你可以在这个while循环之前完成所有的魔法了:

 while (!feof($handle) ) { $line_of_text = fgetcsv($handle, 5000); } 

确保在上面的$ticker片段中为$ticker$crumb$cookie设置您自己的值。 遵循Ed0906关于如何检索$crumb$cookie

对于那些Excel / VBA用户,我已经使用上述build议来开发一个VBA方法来从更新后的雅虎网站中提取历史价格。 下面列出了关键的代码片段,我也提供了我的testing工作手册。

首先,请求获取Crumb和Cookie值,然后尝试从Yahoo提取数据以获取价格。

 Dim strUrl As String: strUrl = "https://finance.yahoo.com/lookup?s=%7B0%7D" 'Symbol lookup used to set the values Dim objRequest As WinHTTP.WinHttpRequest Set objRequest = New WinHttp.WinHttpRequest With objRequest .Open "GET", strUrl, True .setRequestHeader "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8" .send .waitForResponse strCrumb = strExtractCrumb(.responseText) strCookie = Split(.getResponseHeader("Set-Cookie"), ";")(0) End With 

请参阅下面的雅虎历史价格提取链接到我的网站获取示例文件,以及我用于从雅虎网站提取历史安全价格的方法的更多详细信息

python

我用这个代码来获取cookie(从修复 – 雅虎财务复制):

 def get_yahoo_crumb_cookie(): """Get Yahoo crumb cookie value.""" res = requests.get('https://finance.yahoo.com/quote/SPY/history') yahoo_cookie = res.cookies['B'] yahoo_crumb = None pattern = re.compile('.*"CrumbStore":\{"crumb":"(?P<crumb>[^"]+)"\}') for line in res.text.splitlines(): m = pattern.match(line) if m is not None: yahoo_crumb = m.groupdict()['crumb'] return yahoo_cookie, yahoo_crumb 

那么这段代码得到回应:

 cookie_tuple = get_yahoo_crumb_cookie() url_kwargs = { 'symbol': stock.symbol, 'timestamp_end': int(time.time()), 'crumb': cookie_tuple[1], # yahoo cookie crumb -> str } url_price = 'https://query1.finance.yahoo.com/v7/finance/download/' \ '{symbol}?period1=0&period2={timestamp_end}&interval=1d&events=history' \ '&crumb={crumb}'.format(**url_kwargs) response = requests.get(url_price, cookies={'B': cookie_tuple[0]}) 

这看起来不错, http://blog.bradlucas.com/posts/2017-06-03-yahoo-finance-quote-download-python/

我发现另一个不需要cookies的雅虎网站,但生成jason输出: https ://query1.finance.yahoo.com/v7/finance/chart/YHOO ? range = 2y & interval = 1d & indicators = quote & includeTimestamps = true

从这里指出: https : //www.stock-data-solutions.com/kb/how-to-load-historical-prices-from-yahoo-finance-to-excel.htm

事实certificate,他们似乎支持'perod1'和'period2'(在unix时间)参数,可以用来代替'时间间隔'。

 String quoteSite = "https://query1.finance.yahoo.com/v7/finance/chart/" + symbolName + "?" + "period1=" + period1 + "&period2=" + period2 + "&interval=1d&indicators=quote&includeTimestamps=true"; 

下面parsingJason对我的看法:

 JSONObject topObj = new JSONObject(inp); Object error = topObj.getJSONObject("chart").get("error"); if (!error.toString().equals("null")) { System.err.prinltn(error.toString()); return null; } JSONArray results = topObj.getJSONObject("chart").getJSONArray("result"); if (results == null || results.length() != 1) { return null; } JSONObject result = results.getJSONObject(0); JSONArray timestamps = result.getJSONArray("timestamp"); JSONObject indicators = result.getJSONObject("indicators"); JSONArray quotes = indicators.getJSONArray("quote"); if (quotes == null || quotes.length() != 1) { return null; } JSONObject quote = quotes.getJSONObject(0); JSONArray adjcloses = indicators.getJSONArray("adjclose"); if (adjcloses == null || adjcloses.length() != 1) { return null; } JSONArray adjclose = adjcloses.getJSONObject(0).getJSONArray("adjclose"); JSONArray open = quote.getJSONArray("open"); JSONArray close = quote.getJSONArray("close"); JSONArray high = quote.getJSONArray("high"); JSONArray low = quote.getJSONArray("low"); JSONArray volume = quote.getJSONArray("volume"); 

我在同一条船上。 我设法从雅虎下载了一些vb.net的frankencode,我从谷歌,SOF和一些头疼的东西上做了一些零碎的工作。

但是,我发现了Intrinio(注册了),注册了,我的免费账户每天都能获得500个历史数据,而且数据更多,而且比雅虎更准确。 我重写了Intrinio API的代码,我很高兴作为一个蛤。

顺便说一下,我不工作,或与Intrinio有任何关系,但他们节省了我的屁股大好时机…

有一个修复,我发现工作得很好。 请看我的post:

雅虎财经的API / URL不工作:Python的修复Pandas DataReader ,我按照https://pypi.python.org/pypi/fix-yahoo-finance中的步骤:$ pip install fix_yahoo_finance –upgrade –no-cache -dir(同时也升级了pandas_datareader以确保)并testing正常:

 from pandas_datareader import data as pdr import fix_yahoo_finance data = pdr.get_data_yahoo('BHP.AX', start='2017-04-23', end='2017-05-24') 

另外请注意,最后2个数据列的顺序是“调整closures”和“音量”,所以为了我的目的,我已经将列重置为原始顺序:

 cols = ['Date', 'Open', 'High', 'Low', 'Close', 'Volume', 'Adj Close'] data = data.reindex(columns=cols) 

对于Python 3用户更改为

url =' https://query1.finance.yahoo.com/v7/finance/download/AAAP? period1= 1494605670& period2= 1495815270& interval= 1d& events= history& crumb= IJ.ilcJlkrZ '

url =' https: //chartapi.finance.yahoo.com/instrument/1.0/AAAP/chartdata;type=quote;range= 10d/csv/ '

响应= request.urlopen(url)response = requests.get(url,cookie = {'B':cookie})response.text

数据格式是完全不同的,但至less现在工作得很好

从google finance api获取当前和历史数据是可能的。 对我来说非常好。

你实际上不需要做2个请求来获取雅虎数据。 我使用这个链接https://ca.finance.yahoo.com/quote/AAAP/history?period1=1474000669&period2=1505536669&interval=1d&filter=history&frequency=1d

你可以从这个抓取cookie,但是它包含了Json格式的历史报价数据。 在我下载这个页面之后,我把Json的数据从这个数据中解脱出来。 保存一个url请求。

使用Javascript

查找cookie;

 match = document.cookie.match(new RegExp('B=([^;]+)')); alert (match[1]); 

find碎屑;

 i=document.body.innerHTML.search("CrumbStore") if (i>=0) alert (document.body.innerHTML.substr(i+22,11)) 

find移动的碎屑;

 i=document.body.innerHTML.search('USER={\"crumb\":'); if (i>=0) alert(document.body.innerHTML.substr(i+15,11)); 

最好等待页面(例如https://finance.yahoo.com/quote/goog )先加载,然后再检查;

 document.readyState 

到目前为止所提到的另一种方法(雅虎,Google和Intrinio)是从Alpha Vantage免费获取历史数据。 他们的networking服务提供每日,每日,调整的股票价格和50多个技术指标。 他们甚至可以免费通过Deriscope直接发送到Excel。 (我是后者的作者。)

    Interesting Posts