Yahoo Finance URL无效

Yahoo Finance URL not working

我已经用下面的网址从雅虎财经上获取历史数据有一段时间了,但从昨天起它就停止工作了。

https://ichart.finance.yahoo.com/table.csv?间谍=间谍

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

Will be right back...

Thank you for your patience.

Our engineers are working quickly to resolve the issue.

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

我的搜索结果只指向了这个主题,尽管它与https相关…

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


它看起来像他们有增一开始所需的饼干,但你不可以访问这个fairly容易,例如:

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

responds与头部的形状:

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

你应该能够读这两个附加的信息和你的.csv请求:

1
2
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查询参数,这似乎correspond你cookie在一些的方式。你最好的赌注,这两个scrape冰从HTML响应你的初始get请求。在你的回答,你可以做一个正则表达式搜索:"CrumbStore":\{"crumb":"(?[^"]+)"\}屑和提取物的匹配组。

它看起来像你有一次crumb价值,虽然你可以使用它,用相同的cookie在任何符号/股票为下一年的意思,你不应该有两个scrape竞相做了。

两个负载电流quotes说:

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

用:

  • Apple取代用股份的股票
  • 一个[1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo]区间
  • 可选参数period1查询与你约会的时代范围开始如period1=1510340760
  • 可选参数period2查询与你约会的时代,比如period2=1510663712范围


雅虎已经进入了一个ReactJS前端,这意味着如果你分析从客户端到后端的请求头,你可以得到它们用来填充客户端存储的实际JSON。

主持人:

  • query1.finance.yahoo.comhttp/1.0
  • query2.finance.yahoo.comhttp/1.1(HTTP/1.0和HTTP/1.1之间的差异)

如果计划使用代理或持久连接,请使用query2.finance.yahoo.com。但在本文中,用于示例URL的主机并不意味着它所使用的路径。

基础数据

  • /v10/finance/quoteSummary/AAPL?modules=(以下模块完整列表)

(将符号替换为:aapl)

?modules=查询的输入:

  • 埃多克斯1〔5〕

示例URL:

  • 埃多克斯1〔6〕

查询:assetProfileearningsHistory

%2C,的十六进制表示,需要在您请求的每个模块之间插入。有关十六进制编码位的详细信息(如果您愿意)

期权合约

  • /v7/finance/options/AAPL(当前到期)
  • /v7/finance/options/AAPL?date=1579219200(2020年1月17日到期)

示例URL:

  • https://query2.yahoo.finance.com/v7/finance/options/AAPL(当前到期)
  • https://query2.yahoo.finance.com/v7/finance/options/AAPL?date=1579219200(2020年1月17日到期)

任何表示为unix时间戳的有效未来到期都可以在?date=查询中使用。如果查询当前到期,json响应将包含可在?date=查询中使用的所有有效到期的列表。(以下是一篇文章,解释了如何将人类可读的日期转换为Python中的Unix时间戳)

价格

  • 埃多克斯1〔17〕

间隔:

  • &interval=3mo3个月,追溯至初始交易日。
  • &interval=1d1天,回到初始交易日。
  • &interval=5m5分钟,可追溯到80(ish)天。
  • &interval=1m1分钟,往回4-5天。

每一个间歇跑多远有点让人困惑,似乎不一致。我的假设是,雅虎内部正在计入交易日,而我天真的做法没有考虑假期。虽然这是一个猜测,YMMV。

period1=:希望开始日期的Unix时间戳表示。低于初始交易日期的值将四舍五入到初始交易日期。

period2=:希望结束日期的Unix时间戳表示。大于最后交易日期的值将向下舍入到最新的可用时间戳。

注意:如果您查询的EDOCX1(起始日期)对于您所选择的时间间隔来说太远,那么无论您要求什么时间间隔,雅虎都会返回3mo时间间隔的价格。

添加市场前和市场后数据

埃多克斯1〔26〕

增加股息和分割

埃多克斯1〔27〕

示例URL:

  • 埃多克斯1〔28〕

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

注:period1=period2=的价格示例url中使用的值用于演示每个输入的各自舍入行为。


在管理工作了一.net两级获得有效的令牌(和饼干屑)从雅虎财经

完整的API对图书馆在新的历史fetching从雅虎财经的数据,你可以访问yahoofinanceapi在GitHub

这里是两个类的饼干屑和抓斗

token.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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学分 修改正则表达式模式的两个Regex("CrumbStore\":{\"crumb\":\"(?.+?)\"}"


在这个论坛:http:/ / / / forums.yahoo.net T5雅虎金融服务/冰雅虎财务API破碎的TD P / / / / 3 250503页

尼克松说:

Hi All - This feature was discontinued by the Finance team and they will not be reintroducing that functionality.


《Python有情人了,有更新的yahoofinance.py在tradingwithpython图书馆。

有个笔记本也以"基于城市ed0906 demonstrating技巧,如何把数据步进。看到它的在线


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

http:/ / / query1.finance.yahoo.com V7 /金融/下载/间谍?1492449771 period1 = = &;Period2 1495041771 &;一维区间= &;历史事件= = &;9gaimfhz.wu屑

注意以上的URL不会工作对你或任何人。你会得到这样的东西:

1
2
3
4
5
6
7
8
{
   "finance": {
       "error": {
           "code":"Unauthorized",
           "description":"Invalid cookie"
        }
    }
}

它表明,雅虎现在是一些预防使用散列的数据访问的人从你这样做。不同的URL与每个会议,那么它很可能,你不能这样做有一个固定的URL了。

你会需要做一些scrapping两把正确的"主页的URL,例如:

finance.yahoo.com http:/ / / / /历史quote间谍吗?P =间谍


完整工作的PHP示例,基于本文和相关来源:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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;
}

用途:

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


在我的船一样。有一个越来越慢。在下载链接在页面的静态工厂历史价格。我加了两口饼干的Firefox扩展,记录在雅虎把饼干。使用价值的屑从交互式会话,我能够检索值。这里的人一个Perl脚本,测试工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

它会把一段两个automate在做什么。hopefully雅虎将简化或提供一些指导信息,如果他们真的intend两个使用它的人。


适用于Java爱好者。

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

1
2
3
4
5
6
7
8
9
10
11
12
 // "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
           ...
        }
 }

现在您可以在雅虎网站中搜索crumb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

1
2
3
4
5
6
7
8
9
10
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();


我发现另一个雅虎网站不需要cookie,但会生成jason输出:https://query1.finance.yahoo.com/v7/finance/chart/yhoo?范围=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"。

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

下面为我解析Jason:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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");


Python

我使用此代码获取cookie(从Fix Yahoo Finance复制):

1
2
3
4
5
6
7
8
9
10
11
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

然后此代码得到响应:

1
2
3
4
5
6
7
8
9
10
11
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/


我是这项服务的作者

此处显示基本信息

每日价格

您需要熟悉RESTful服务。

https://quantprice.herokuapp.com/api/v1.1/scoop/day?Tickers=MSFT&Date=2017年6月9日

历史价格

您必须提供日期范围:

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。您将收到一个要添加到URL的API密钥。

我们正在建立一个PayPal帐户付费订阅无利率。

可用的票据列表

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

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


VBA

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

包含项目应具有对添加的"Microsoft XML,V6.0"库的引用(其他版本可能也可以,但对代码进行了一些较小的更改)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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

在使用一个PHP脚本使用fopen()的两个财务数据的存取,这是我snippets改性让它回去工作。

创建的日期和时间戳比开始日期:

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

空军fopen()所需的两个发送的Cookie和硬编码的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$cookie="YourCookieTakenFromYahoo";

$opts = array(
    'http'=>array(
        'method'=>"GET",
        'header'=>"Accept-language: en

" .
           "Cookie: B=".$cookie."

"
    )
);

$context = stream_context_create($opts);

使用fopen()把两个CSV文件:

1
2
3
4
$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);

现在你可以做你所做的所有的魔术在这之前随循环:

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

确保你自己的价值观两个角度对$ticker$crumb$cookie的snippets以上。 ed0906后续的检索两种方法对如何$crumb$cookie鸭。


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

首先请求获取crumb和cookie值,然后再尝试从雅虎中提取价格数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
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 finance api/url不工作:python fix for pandas datareader,在这里我按照https://pypi.python.org/pypi/fix-yahoo-finance中的步骤安装fix-yahoo-finance-upgrade-no cache dir(并升级pandas-datareader以确保)并测试正常:

1
2
3
4
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')

另外请注意,最后两个数据列的顺序是"adj close"和"volume",因此为了我的目的,我将这些列重置为原始顺序:

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


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

您可以从中获取cookie,但它以JSON格式为您包含了历史引用的数据。下载页面后,我会将JSON数据从中删除。保存URL请求。


javascript

找到饼干;

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

找到面包屑;

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

找到移动面包屑;

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

最好是等待页面(如https://finance.yahoo.com/quote/goog)首先加载,您可以核对一下;

1
document.readyState


到目前为止,另一种方法(雅虎、谷歌和Intrinio)是免费从Alpha Vantage获取历史数据。他们的网络服务提供日内、日内、调整后的股价和50多个技术指标。他们甚至通过Deriscope直接交付到Excel(也是免费的)。(我是后者的作者。)


我在同一艘船上。我设法从雅虎下载了一些vb.net frankencode的csv文件,这些文件是我用google、sof和一些头皮屑制作的。

然而,我发现了Intrinio(查找它),注册了,我的免费帐户每天能收到500个历史数据API调用,比雅虎有更多的数据和更准确的数据。我重新编写了intrinio api的代码,我高兴得像个蛤蜊。

顺便说一句,我不工作,也和里奇诺没有任何关系,但是他们节省了我的时间…


如果你试图连接雅虎软件API和Java。只需添加以下依赖项。

1
2
3
4
5
<dependency>
    <groupId>com.yahoofinance-api</groupId>
    YahooFinanceAPI</artifactId>
    <version>3.13.0</version>
</dependency>

可以从Google Finance API获取当前和历史数据。对我很好。


对于python 3,用户更改为

url='https://query1.finance.yahoo.com/v7/finance/download/aaap?期间1=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/'

响应=请求.urlopen(url)到response=requests.get(url,cookies='b':cookie)响应中的数据.text

数据格式完全不同,但至少目前工作正常


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

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

类本身在这里:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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