雅虎财经网址不起作用

Posted

技术标签:

【中文标题】雅虎财经网址不起作用【英文标题】:Yahoo Finance URL not working 【发布时间】:2017-05-17 17:06:24 【问题描述】:

我已经使用以下 URL 从 yahoo Finance 获取历史数据已经有一段时间了,但它从昨天开始停止工作。

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

当浏览到这个网站时,它会说:

马上回来……

感谢您的耐心等待。

我们的工程师正在迅速解决问题。

但是,由于这个问题从昨天开始仍然存在,我开始认为他们停止了这项服务?

我的 SO 搜索只将我指向 this topic,尽管它与 https 相关...

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

【问题讨论】:

似乎在没有任何警告的情况下发生了。什么鬼。 它不再起作用它也发生在我身上,但我做了一个非常简单的解决方法,就是让 URL 直接使用 pandas 获取数据 【参考方案1】:

Yahoo 使用了 Reactjs 前端,这意味着如果您分析从客户端到后端的请求标头,您可以获得它们用于填充客户端存储的实际 JSON。

主机:

query1.finance.yahoo.comHTTP/1.0 query2.finance.yahoo.comHTTP/1.1 (difference between HTTP/1.0 & HTTP/1.1)

如果您打算使用代理或持久连接,请使用query2.finance.yahoo.com。但出于本文的目的,用于示例 URL 的主机并不意味着暗示它正在使用的路径。


基本数据

(将您的符号替换为:AAPL)

/v10/finance/quoteSummary/AAPL?modules=

?modules= 查询的输入:

    [
       'assetProfile',
       'summaryProfile',
       'summaryDetail',
       'esgScores',
       'price',
       'incomeStatementHistory',
       'incomeStatementHistoryQuarterly',
       'balanceSheetHistory',
       'balanceSheetHistoryQuarterly',
       'cashflowStatementHistory',
       'cashflowStatementHistoryQuarterly',
       'defaultKeyStatistics',
       'financialData',
       'calendarEvents',
       'secFilings',
       'recommendationTrend',
       'upgradeDowngradeHistory',
       'institutionOwnership',
       'fundOwnership',
       'majorDirectHolders',
       'majorHoldersBreakdown',
       'insiderTransactions',
       'insiderHolders',
       'netSharePurchaseActivity',
       'earnings',
       'earningsHistory',
       'earningsTrend',
       'industryTrend',
       'indexTrend',
       'sectorTrend']

示例 URL: 查询所有上述模块

https://query2.finance.yahoo.com/v10/finance/quoteSummary/AAPL?modules=assetProfile%2CsummaryProfile%2CsummaryDetail%2CesgScores%2Cprice%2CincomeStatementHistory%2CincomeStatementHistoryQuarterly%2CbalanceSheetHistory%2CbalanceSheetHistoryQuarterly%2CcashflowStatementHistory%2CcashflowStatementHistoryQuarterly%2CdefaultKeyStatistics%2CfinancialData%2CcalendarEvents%2CsecFilings%2CrecommendationTrend%2CupgradeDowngradeHistory%2CinstitutionOwnership%2CfundOwnership%2CmajorDirectHolders%2CmajorHoldersBreakdown%2CinsiderTransactions%2CinsiderHolders%2CnetSharePurchaseActivity%2Cearnings%2CearningsHistory%2CearningsTrend%2CindustryTrend%2CindexTrend%2CsectorTrend

%2C, 的十六进制表示,需要插入到您请求的每个模块之间。 details about the hex encoding bit(如果你在乎的话)


期权合约

/v7/finance/options/AAPL(当前到期) /v7/finance/options/AAPL?date=1679011200(2023年3月17日到期)

示例网址:

https://query2.finance.yahoo.com/v7/finance/options/AAPL(当前到期) https://query2.finance.yahoo.com/v7/finance/options/AAPL?date=1679011200(2023年第17场比赛到期)

任何表示为 UNIX 时间戳的有效未来到期时间都可以在 ?date= 查询中使用。如果您查询当前过期时间,JSON 响应将包含可在 ?date= 查询中使用的所有有效过期时间的列表。 (here is a post explaining converting human-readable dates to UNIX timestamp in Python)


价格

/v8/finance/chart/AAPL?symbol=AAPL&period1=0&period2=9999999999&interval=3mo

&interval= 的可能输入: 1m, 5m, 15m, 30m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo

m (分钟) 间隔限制为 30 天,period1period2 每个请求最多跨越 7 天。超过这些限制中的任何一个都将导致错误并且不会舍入

h(小时) 间隔限制为 730 天,没有跨度限制。超过此值将导致错误并且不会舍入

period1=:您希望开始的日期的 UNIX 时间戳表示。

d(day)wk(week)mo(month) 间隔值小于初始交易日将向上取整至初始交易日。

period2=:您希望结束的日期的 UNIX 时间戳表示。

对于所有时间间隔:大于最后交易日期的值将向下舍入到可用的最新时间戳。

添加上市前和上市后数据

&includePrePost=true

添加股息和分割

&events=div%7Csplit

%7C| 的十六进制数。 , 可以工作,但雅虎内部使用管道

示例网址:

https://query1.finance.yahoo.com/v8/finance/chart/AAPL?symbol=AAPL&period1=0&period2=9999999999&interval=1d&includePrePost=true&events=div%7Csplit

上述请求将返回股票代码 AAPL 每隔 1 天的所有价格数据,包括上市前和上市后数据以及股息和拆分。

注意: period1=period2= 的价格示例 URL 中使用的值是为了演示每个输入的相应舍入行为。`

【讨论】:

嗨@ryder-***s,感谢您的精彩帖子!你能发布你的github链接吗? 您是如何找到“所有”模块的列表的?您能否概述查找模块列表的过程。谢谢! 您是如何发现模块和端点的? @pasta_sauce 我监控了页面加载/交互时发送的网络请求。实际上还有一个额外的端点/ws/fundamentals-timeseries/v1/finance/timeseries/<YOUR_SYMBOL>?... 用于更详细的财务数据(这是构建资产负债表/现金流量/损益表页面的内容),但查询输入的详尽列表对于 SO 帖子来说太大了。此外,您可以通过 edgar 的单个请求从该端点返回整个市场的相同数据。 @not2qubit 我认为您遇到了这样一个事实:雅虎仅按季度免费提供 pegRatio。但是,如果您查询 quarterlyPegRatio,您应该能够获得最后 5 个季度。即:(同时适用于 query1 和 query2,无需指定标题)https://query1.finance.yahoo.com/ws/fundamentals-timeseries/v1/finance/timeseries/GS?symbol=GS&type=quarterlyPegRatio&period1=493590046&period2=1913180947【参考方案2】:

看起来他们已经开始添加所需的 cookie,但您可以相当轻松地检索它,例如:

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

以表单中的标题响应:

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。您最好的选择是从 html 响应到您的初始 GET 请求scrape。在该响应中,您可以执行正则表达式搜索:"CrumbStore":\"crumb":"(?<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查询参数与您的纪元范围开始日期,例如period1=1510340760 可选的period2查询参数与您的纪元范围结束日期,例如period2=1510663712

【讨论】:

知道如何刮掉面包屑吗? @RupertPupkin 现在你可能会在你的应用程序中硬编码 crumb 和 cookie 值,因为它们有 1 年的生命周期 @RupertPupkin 更新了如何刮碎屑 @ThomasMcLeod 它工作我在我的应用程序中使用它,没有保证他们不会尝试让它更安全,但在未来:( @Edd 我刚刚意识到通过使用 v8 url 还可以以一个不错的 json 格式获取完整的历史记录【参考方案3】:

我设法设计了一个 .NET 类以从 Yahoo Finance 获取有效的令牌(cookie 和 crumb)

关于从新雅虎财经获取历史数据的完整API库,您可以访问Github中的YahooFinanceAPI

这是获取 cookie 和 crumb 的类

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;

        

    

17 年 6 月 1 日更新 感谢@Ed0906 将 crumb 正则表达式模式修改为 Regex("CrumbStore\":\"crumb\":\"(?&lt;crumb&gt;.+?)\""

【讨论】:

查看了您的代码。看起来非常好。明天试试这个。非常感谢您! 非常感谢!它完美地工作。在我们所有人中,可能节省了数百万小时! 今天,我根据您的两个类将过时的 Yahoo Api 替换为新的。结果非常好。非常感谢。不幸的是,没有 Paypal 按钮。所以我无法为你拯救我的所有痛苦捐款。 ;) 请小心那个 reg ex,因为我在实验过程中看到了带有符号的碎屑 @Ed0906 用奇怪的碎屑样本告诉我你的发现【参考方案4】:

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

尼克松说:

大家好 - 财务团队已停止使用此功能,他们不会重新引入该功能。

【讨论】:

【参考方案5】:

对于 Python 爱好者,我已经更新了 tradingWithPython 库中的 yahooFinance.py。

还有一个例子notebook根据Ed0906的技巧,一步步演示如何获取数据。看到它

【讨论】:

这部分时间效果很好,我得到status_code200,但有时它随机失败,我得到status_code401。我刚刚做了一个for 循环并添加了一个tryexcept。谢谢! 你只需要得到一个 cookie-crumb 对,有效期大约一年。 将生成 query1.finance.yahoo.com/v7/finance/download/… cookie: B=66lgrj1cib1au&b=3&s=qq> 的代码放在一起,看起来不错,响应 = request.urlopen(url) 返回 HTTP 错误 400 未知版本任何想法为什么?【参考方案6】:

下载历史数据的 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

【讨论】:

【参考方案7】:

我找到了另一个不需要 cookie,但会生成 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

事实证明,它们似乎支持 'perod1' 和 'period2'(在 unix 时间)参数,可以用来代替 'interval'。

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

下面为我解析 Jason:

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");

【讨论】:

我认为现在他们实际上也需要 cookie。 @AlbertCheng 我不这么认为。我在没有 cookie 的情况下运行,它可以工作。 如果是这样,那就太棒了!【参考方案8】:

我在同一条船上。慢慢到达那里。历史价格页面上的下载链接仍然有效。所以我将导出cookies扩展添加到firefox,登录到yahoo,转储cookies。使用交互式会话中的 crumb 值,我能够检索值。这是有效的测试 perl 脚本的一部分。

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

自动化我的工作需要一段时间。如果雅虎真的打算让人们使用它,希望雅虎能对其进行简化或提供一些指导。

【讨论】:

你能在你的代码中添加几行注释吗?我不清楚task 是什么。谢谢。【参考方案9】:

完整的 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));

【讨论】:

效果很好。谢谢!【参考方案10】:

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
           ...
        
 

现在您可以在 yahoo 网站中搜索面包屑:

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();

【讨论】:

我比其他方法更喜欢它.....使用这种方法可以得到图表中可用的分钟数据吗?【参考方案11】:

Python

我使用此代码获取 cookie(复制自 fix-yahoo-finance):

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, crumb = get_yahoo_crumb_cookie()
params = 
    'symbol': stock.symbol,
    'period1': 0,
    'period2': int(time.time()),
    'interval': '1d',
    'crumb': crumb,

url_price = 'https://query1.finance.yahoo.com/v7/finance/download/symbol'

response = requests.get(url_price, params=params, cookies='B': cookie)

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

【讨论】:

这很好:blog.bradlucas.com/posts/… 谢谢@Lucas03【参考方案12】:

我使用了一个使用 fopen() 的 php 脚本来访问财务数据,这里是我修改的 sn-ps 以使其恢复工作:

为开始日期和结束日期创建时间戳:

$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);

确保在上面的 sn-ps 中为 $ticker$crumb$cookie 设置您自己的值。 关注Ed0906's approach 了解如何检索$crumb$cookie

【讨论】:

请注意在此答案中添加更多内容。我理解它,但我似乎无法执行它。不确定我是否使用了正确的 Cookie? 嗨@Chad,您希望我详细说明什么?检查 Yahoo! 网站中设置的 cookie 时,复制名称为“B”的 cookie 的值。希望这会有所帮助:-) 好吧,这是我的少数未成年人的组合,但对于其他任何人来说,这就是饼干和面包屑的样子。 $cookie = "95eg6lcisb25&amp;b=3&amp;s=oq"; $crumb = "nGLaX9jgD2B"; 获取 cookie 最简单的方法就是在浏览器中插入一个 cookie 插件。感谢@jm。另外我只想说我讨厌雅虎在没有通知的情况下这样做! 用这种方法可以得到图表中可用的分钟数据吗? 我收到HTTP request failed! HTTP/1.0 401 Unauthorized in E:\xampp\htdocs\test.php on line 31 错误消息。他们已经解决了吗?此外,我的 cookie B 值在某种程度上比你的长得多......这个答案虽然有效:***.com/a/44348197/4114325【参考方案13】:

我是这个service的作者

基本信息here

每日价格

您需要熟悉 RESTFUL 服务。

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

历史价格

您必须提供日期范围:

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

如果您不提供开始或结束,它将使用最早或当前日期:

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,请在 Twitter 上给我发送 DM。您将收到一个 API 密钥以添加到 URL。

我们正在为无费率付费订阅设置一个贝宝帐户。

可用代码列表

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

我还致力于提供来自 EDGAR 的基本数据和公司数据。 干杯。

【讨论】:

这些显示的是前一个交易日的数据。不是实时的。 您好,我刚刚添加了此功能,因此您现在可以延迟 5 分钟查看纽约证券交易所和纳斯达克的实时价格,示例如下:nasdaqviz.herokuapp.com/api/v1.1/markets/data/nsdaq/realtime/…【参考方案14】:

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

【讨论】:

【参考方案15】:

对于那些 Excel/VBA 用户,我使用上述建议开发了一种 VBA 方法,以从更新的雅虎网站中提取历史价格。下面列出了关键代码 sn-ps,我还提供了我的测试工作簿。

在尝试从雅虎提取价格数据之前,首先请求获取 Crumb 和 Cookie 值集。

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

请参阅以下Yahoo Historical Price Extract 链接到我的网站以获取示例文件以及我用来从雅虎网站提取历史证券价格的方法的更多详细信息

【讨论】:

【参考方案16】:

javascript

查找cookie;

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

寻找面包屑;

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

为移动设备查找 crumb;

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

【讨论】:

【参考方案17】:

如果您尝试将 yahooFinance api 与 java 连接。只需添加以下依赖项。

<dependency>
    <groupId>com.yahoofinance-api</groupId>
    <artifactId>YahooFinanceAPI</artifactId>
    <version>3.13.0</version>
</dependency>

【讨论】:

【参考方案18】:

我在同一条船上。我设法从雅虎下载了 CSV,其中包含一些我从谷歌、SOF 和一些令人头疼的东西中制作的 vb.net frankencode。

但是,我发现了 Intrinio(查一下),然后注册了,我的免费帐户每天可以给我 500 次历史数据 api 调用,比雅虎拥有更多的数据和更准确的数据。我为 Intrinio API 重写了我的代码,我很高兴。

顺便说一句,我不工作或与 Intrinio 没有任何关系,但他们为我节省了很多时间......

【讨论】:

【参考方案19】:

我发现有一个修复方法效果很好。请看我的帖子:

Yahoo Finance API / URL not working: Python fix for Pandas DataReader 我按照https://pypi.python.org/pypi/fix-yahoo-finance 中的步骤执行以下操作: $ pip install fix_yahoo_finance --upgrade --no-cache-dir (当然还升级了 pandas_datareader)并测试正常:

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 个数据列的顺序是“Adj Close”和“Volume”,因此出于我的目的,我已将这些列重置为原始顺序:

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

【讨论】:

我遇到的问题是,每次我们找到修复程序时,雅虎可能都会停止任何数据访问。我将尝试使用 Google 财务代码将符号写入预设的 Google 电子表格中,以进行价格查找,然后读回结果。看起来谷歌电子表格的限制是 250 只股票,因此必须将所有纳斯达克股票循环 13 次,然后再循环 NYSE 和美国运通股票。有人试过吗?【参考方案20】:

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

您可以从 this 中获取 cookie,但它会包含 Json 格式的历史报价数据。下载页面后,我会从中删除 Json 数据。保存一个 url 请求。

【讨论】:

【参考方案21】:

目前提到的方法(Yahoo、Google 和 Intrinio)的另一种方法是从 Alpha Vantage 免费获取历史数据。他们的网络服务提供日内、每日、调整后的股票价格和 50 多个技术指标。他们甚至通过 Deriscope 直接向 Excel 提供 - 也是免费的。 (我是后者的作者。)

【讨论】:

Alpha Vantage 没有索引或大部分信息已经存在于 Yahoo... 不是真的!试试这个 url alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=^DJI&outputsize=compact&apikey=xxx 你必须用你自己的 Alpha Vantage 密钥替换最后一个 xxx。您将看到 ^DJI 指数的数据。您还应该知道,Yahoo 不提供该指数或任何其他指数的实时价格,而 Alpha Vantage 提供(延迟一分钟)。相应的网址是alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=^DJI&interval=1min&apikey=xxx 但它返回了错误"Error Message": "Invalid API call。我确实在寻找日内世界指数(N225、HSI、IXIC、BOVESPA、DAX 等),而大多数服务根本不提供这些(https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&amp;symbol=^DJI&amp;interval=1min&amp;apikey=xxx)。我尝试将其转义为 %5E^ 我现在在 chrome 上尝试了 url alphavantage.co/…,其中 xxx 代表我的用户密钥。当你尝试它时,你应该用你自己的密钥替换 xxx,你可以从 Alpha Vantage 站点获得它。你这样做了吗?你的密钥有效吗?例如,您可以通过尝试在 MSFT 上获取价格来检查它是否有效。 现在可以使用了!对于 ^IXIC 和 ^DJI 和以前一样。但是其他国家的其他世界股票指数(^N225、^HSI、^DAX、^BOVESPA)没有出现。或者我不知道它们的正确符号?我应该如何寻找符号列表?【参考方案22】:

我结合了上述处理 crumb / cookie 刷新的一些想法,特别是来自@Dennis,并创建了一个可以像这样调用的 vb.net 类:

Dim f = Await YahooFinanceFactory.CreateAsync
Dim items1 = Await f.GetHistoricalDataAsync("SPY", #1/1/2018#)
Dim items2 = Await f.GetHistoricalDataAsync("^FTSE", #1/1/2018#)

类本身在这里:

Imports System.Net
Imports System.Net.Http
Imports System.Text.RegularExpressions

Namespace YahooFinance
    Public Class YahooHistoryPrice

        Public Property [Date] As DateTime

        Public Property Open As Double

        Public Property High As Double

        Public Property Low As Double

        Public Property Close As Double

        Public Property Volume As Double

        Public Property AdjClose As Double
    End Class

    Public Class YahooFinanceFactory
        Public Property Cookie As String
        Public Property Crumb As String
        Public Property CrumbUrl As String = "https://finance.yahoo.com/quote/0?p=0"
        Public Property DownloadUrl As String = "https://query1.finance.yahoo.com/v7/finance/download/0?period1=1&period2=2&interval=1d&events=3&crumb=4"

        Public Property Timeout As Integer = 5
        Public Property NoRefreshRetries As Integer = 10
        Public Property NoDownloadRetries As Integer = 10
        Private Property Regex_crumb As Regex

        Public Shared Async Function CreateAsync(Optional noRefreshRetries As Integer = 10, Optional noDownloadRetries As Integer = 10, Optional timeout As Integer = 5, Optional crumbUrl As String = "https://finance.yahoo.com/quote/0?p=0", Optional downloadUrl As String = "https://query1.finance.yahoo.com/v7/finance/download/0?period1=1&period2=2&interval=1d&events=3&crumb=4") As Task(Of YahooFinanceFactory)
            Return Await (New YahooFinanceFactory With 
                .NoRefreshRetries = noRefreshRetries,
                .NoDownloadRetries = noDownloadRetries,
                .Timeout = timeout,
                .CrumbUrl = crumbUrl,
                .DownloadUrl = downloadUrl
            ).RefreshAsync()
        End Function

        Public Async Function GetHistoricalDataAsync(symbol As String, dateFrom As Date) As Task(Of IEnumerable(Of YahooHistoryPrice))
            Dim count As Integer = 0

            If Not IsValid Then
                Throw New Exception("Invalid YahooFinanceFactory instance")
            End If

            Dim csvData = Await GetRawAsync(symbol, dateFrom, Now).ConfigureAwait(False)

            If csvData IsNot Nothing Then
                Return ParsePrice(csvData)
            End If

            Return Array.Empty(Of YahooHistoryPrice)
        End Function

        Public Async Function GetRawAsync(symbol As String, start As DateTime, [end] As DateTime) As Task(Of String)
            Dim count = 0

            While count < NoDownloadRetries
                Try
                    Dim cookies = New CookieContainer
                    cookies.Add(New Cookie("B", If(Cookie.StartsWith("B="), Cookie.Substring(2), Cookie), "/", ".yahoo.com"))

                    Using handler = New HttpClientHandler With .CookieContainer = cookies
                        Using client = New HttpClient(handler) With .Timeout = TimeSpan.FromSeconds(Timeout)
                            Dim httpResponse = Await client.GetAsync(GetDownloadUrl(symbol, start)).ConfigureAwait(False)
                            Return Await httpResponse.Content.ReadAsStringAsync
                        End Using
                    End Using
                Catch ex As Exception
                    If count >= NoDownloadRetries - 1 Then
                        Throw
                    End If
                End Try

                count += 1
            End While

            Throw New Exception("Retries exhausted")
        End Function

        Private Function ParsePrice(ByVal csvData As String) As IEnumerable(Of YahooHistoryPrice)
            Dim lst = New List(Of YahooHistoryPrice)
            Dim rows = csvData.Split(Convert.ToChar(10))
            For i = 1 To rows.Length - 1
                Dim row = rows(i)
                If String.IsNullOrEmpty(row) Then
                    Continue For
                End If
                Dim cols = row.Split(","c)
                If cols(1) = "null" Then
                    Continue For
                End If
                Dim itm = New YahooHistoryPrice With .Date = DateTime.Parse(cols(0)), .Open = Convert.ToDouble(cols(1)), .High = Convert.ToDouble(cols(2)), .Low = Convert.ToDouble(cols(3)), .Close = Convert.ToDouble(cols(4)), .AdjClose = Convert.ToDouble(cols(5))
                If cols(6) <> "null" Then
                    itm.Volume = Convert.ToDouble(cols(6))
                End If
                lst.Add(itm)
            Next

            Return lst
        End Function

        Public ReadOnly Property IsValid() As Boolean
            Get
                Return Not String.IsNullOrWhiteSpace(Cookie) And Not String.IsNullOrWhiteSpace(Crumb)
            End Get
        End Property

        Public Function GetDownloadUrl(symbol As String, dateFrom As Date, Optional eventType As String = "history") As String
            Return String.Format(DownloadUrl, symbol, Math.Round(DateTimeToUnixTimestamp(dateFrom), 0), Math.Round(DateTimeToUnixTimestamp(Now.AddDays(-1)), 0), eventType, Crumb)
        End Function

        Public Function GetCrumbUrl(symbol As String) As String
            Return String.Format(Me.CrumbUrl, symbol)
        End Function

        Public Function DateTimeToUnixTimestamp(dateTime As DateTime) As Double
            Return (dateTime.ToUniversalTime() - New DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds
        End Function

        Private Async Function RefreshAsync(Optional symbol As String = "SPY") As Task(Of YahooFinanceFactory)
            Dim count = 0

            While count < NoRefreshRetries And Not IsValid
                Try
                    Using client = New HttpClient With .Timeout = TimeSpan.FromSeconds(Timeout)
                        Dim httpResponse = Await client.GetAsync(GetCrumbUrl(symbol)).ConfigureAwait(False)
                        Me.Cookie = httpResponse.Headers.First(Function(f) f.Key = "Set-Cookie").Value.FirstOrDefault?.Split(";"c)(0)
                        Dim html = Await httpResponse.Content.ReadAsStringAsync
                        Me.Crumb = GetCrumb(html)
                        If Crumb IsNot Nothing Then
                            Return Me
                        End If
                    End Using
                Catch ex As Exception
                    If count >= NoRefreshRetries - 1 Then
                        Cookie = ""
                        Crumb = ""
                        Throw
                    End If
                End Try

                count += 1
            End While

            Cookie = ""
            Crumb = ""
            Throw New Exception("Could not refresh YahooFinanceFactory")
        End Function

        Private Function GetCrumb(html As String) As String
            Dim crumb As String = Nothing

            If Regex_crumb Is Nothing Then
                Regex_crumb = New Regex("CrumbStore"":""crumb"":""(?<crumb>.+?)""", RegexOptions.CultureInvariant Or RegexOptions.Compiled, TimeSpan.FromSeconds(5))
            End If

            Dim matches As MatchCollection = Regex_crumb.Matches(html)
            If matches.Count > 0 Then
                crumb = matches(0).Groups("crumb").Value
                crumb = System.Text.RegularExpressions.Regex.Unescape(crumb)
            Else
                Throw New Exception("Regex no match")
            End If

            Return crumb
        End Function
    End Class
End Namespace

【讨论】:

【参考方案23】:

为什么不使用提供完全访问权限的现成版本。没有故障:

tickers='AAPL' 

from pandas_datareader import data as wb

new_data = pd.DataFrame()
for t in tickers :

    new_data[t] = wb.DataReader(t, data_source ='yahoo', start = '2004-1-1')['Adj Close']

a = new_data[t]

【讨论】:

“没有故障”,直到 Yahoo 更改他们的 API 并且库维护者不想再使用它【参考方案24】:

对于 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) 到 响应 = requests.get(url,cookies='B':cookie) response.text 中的数据

数据格式完全不同,但至少现在可以正常工作

【讨论】:

【参考方案25】:

可以从google finance api 获取当前和历史数据。非常适合我。

【讨论】:

谷歌金融的问题是他们会限制数据流,几次调用后,您将无法获得任何数据。

以上是关于雅虎财经网址不起作用的主要内容,如果未能解决你的问题,请参考以下文章

雅虎汇率不起作用

Yahoo Finance API / URL 不起作用:Pandas DataReader 的 Python 修复

自动雅虎邮件登录时,密码编辑框上的发送密钥命令不起作用

旧网址的网址重写不起作用

雅虎财经 API 的替代品? [关闭]

Htaccess 不起作用 - 不错的网址