URL do Yahoo Finance não está funcionando

Eu tenho usado o seguinte URL para buscar dados históricos do yahoo finance por algum tempo agora, mas ele parou de funcionar a partir de ontem.

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

Ao navegar para este site, ele diz:

Estará de volta …

Obrigado pela sua paciência.

Nossos engenheiros estão trabalhando rapidamente para resolver o problema.

No entanto, uma vez que esta questão ainda existe desde ontem, estou começando a pensar que eles descontinuaram este serviço?

Minha pesquisa SO apenas me indicou esse tópico , que estava relacionado a https …

Alguém mais está enfrentando esse problema? Como posso resolver esse problema? Eles oferecem um access diferente aos dados históricos?

    Parece que eles começaram a adicionar um cookie obrigatório, mas você pode recuperá-lo facilmente, por exemplo:

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

    Responde com o header no formulário:

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

    Você deve conseguir ler isso e anexá-lo à sua solicitação .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; 

    Observe o parâmetro de consulta do crumb , isso parece corresponder ao seu cookie de alguma forma. Sua melhor aposta é scrape isso da resposta HTML à sua solicitação GET inicial. Dentro dessa resposta, você pode fazer uma pesquisa regex para: "CrumbStore":\{"crumb":"(?[^"]+)"\} e extrair o grupo correspondente.

    Parece que uma vez que você tem esse valor de crumb você pode usá-lo com o mesmo cookie em qualquer símbolo / ticker para o próximo ano, o que significa que você não deveria ter que fazer o scrape muita freqüência.


    Para obter cotações atuais, basta carregar:

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

    Com:

    • AAPL substituído com seu ticker de ações
    • intervalo um de [1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo]
    • period1 consulta period1 opcional com sua data de início de intervalo de época, por exemplo, period1=1510340760
    • period2 consulta period2 opcional com a data de término da faixa de epoch, por exemplo, period2=1510663712

    Eu consegui elaborar uma class .NET para obter token válido (cookie e migalha) do Yahoo Finance

    Para obter uma biblioteca de API completa na busca de dados históricos do novo Yahoo Finance, você pode visitar o YahooFinanceAPI no Github

    Aqui é a class para pegar o biscoito e migalhas

    Token.cs

     using System; using System.Diagnostics; using System.Net; using System.IO; using System.Text.RegularExpressions; namespace YahooFinanceAPI { ///  /// Class for fetching token (cookie and crumb) from Yahoo Finance /// Copyright Dennis Lee /// 19 May 2017 /// ///  public class Token { public static string Cookie { get; set; } public static string Crumb { get; set; } private static Regex regex_crumb; ///  /// Refresh cookie and crumb value Yahoo Fianance ///  /// Stock ticker symbol ///  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; } ///  /// Get crumb value from HTML ///  /// HTML code ///  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\":\"(?.+?)\"}", 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; } } } 

    Atualizado 1 jun 17
    créditos para @ Ed0906
    modifique o padrão regex migalha para Regex("CrumbStore\":{\"crumb\":\"(?.+?)\"}"

    O Yahoo foi para um front-end do Reactjs, o que significa que, se você analisar os headers de solicitação do cliente para o backend, poderá obter o JSON real que eles usam para preencher as lojas do lado do cliente.

    Hosts:

    • query1.finance.yahoo.com HTTP / 1.0
    • query2.finance.yahoo.com HTTP / 1.1 ( diferença entre HTTP / 1.0 e HTTP / 1.1 )

    Se você planeja usar um proxy ou conexões persistentes, use query2.finance.yahoo.com . Mas, para os propósitos deste post, o host usado para as URLs de exemplo não deve implicar em nada sobre o caminho que está sendo usado.


    Dados Fundamentais

    • /v10/finance/quoteSummary/AAPL?modules= (lista completa dos módulos abaixo)

    (substitua seu símbolo por: AAPL)

    Entradas para a consulta ?modules= :

    • modules = [ 'assetProfile', '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 de exemplo:

    • https://query1.finance.yahoo.com/v10/finance/quoteSummary/AAPL?modules=assetProfile%2CearningsHistory

    Consultando para : assetProfile e earningsHistory

    O %2C é a representação Hex e precisa ser inserido entre cada módulo solicitado. detalhes sobre o bit de codificação hexadecimal (se você se importa)


    Contratos de opções

    • /v7/finance/options/AAPL (expiração atual)
    • /v7/finance/options/AAPL?date=1579219200 (17 de janeiro de 2020)

    URL de exemplo:

    • https://query2.yahoo.finance.com/v7/finance/options/AAPL (expiração atual)
    • https://query2.yahoo.finance.com/v7/finance/options/AAPL?date=1579219200 (17 de janeiro de 2020)

    Qualquer expiração futura válida representada como um registro de data e hora do UNIX pode ser usada na consulta ?date= . Se você consultar a expiração atual, a resposta JSON conterá uma lista de todas as expirações válidas que podem ser usadas na consulta ?date= . (aqui está um post explicando a conversão de datas legíveis para o timestamp unix em Python)


    Preço

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

    Intervalos:

    • &interval=3mo 3 meses, voltando até a data inicial de negociação.
    • &interval=1d 1 dia, voltando até a data inicial de negociação.
    • &interval=5m 5 minuetos, retornando 80 (ish) dias.
    • &interval=1m 1 minueto, voltando de 4 a 5 dias.

    Quão longe você pode ir com cada intervalo é um pouco confuso e parece inconsistente. Minha suposição é que internamente o yahoo está contando em dias de negociação e minha abordagem ingênua não era responsável por feriados. Embora isso seja um palpite e YMMV.

    period1= : representação unix timestamp da data que você deseja iniciar . Os valores abaixo da data de negociação inicial serão arredondados para a data de negociação inicial.

    period2= : representação unix timestamp da data em que você deseja terminar . Valores maiores que a data da última negociação serão arredondados para baixo até o registro de data e hora mais recente disponível.

    Nota: Se você consultar com um period1= (data de início) muito distante no passado para o intervalo escolhido, o yahoo retornará preços no intervalo 3mo , independentemente do intervalo solicitado.

    Adicionar dados pré e pós-mercado

    &includePrePost=true

    Adicionar dividendos e divisões

    &events=div%2Csplit

    URL de exemplo:

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

    A solicitação acima retornará todos os dados de preço do ticker AAPL em um intervalo de 1 dia, incluindo dados de pré e pós-mercado, bem como dividendos e divisões.

    Nota: os valores usados ​​no URL do exemplo de preço para period1= & period2= são para demonstrar o respectivo comportamento de arredondamento de cada input.

    Neste fórum: https://forums.yahoo.net/t5/Yahoo-Finance-help/Is-Yahoo-Finance-API-broken/td-p/250503/page/3

    Nixon disse:

    Oi pessoal – Este recurso foi descontinuado pela equipe de Finanças e eles não estarão reintroduzindo essa funcionalidade.

    O URL para baixar dados históricos agora é algo assim:

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

    Observe que o URL acima não funcionará para você ou para qualquer outra pessoa. Você terá algo assim:

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

    Parece que o Yahoo agora está usando algum hash para impedir que as pessoas acessem os dados como você fez. O URL varia de acordo com cada session, por isso é muito provável que você não possa mais fazer isso com um URL fixo.

    Você precisará fazer alguns ajustes para obter o URL correto da página principal, por exemplo:

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

    Para os amantes de python, atualizei o yahooFinance.py na biblioteca tradingWithPython.

    Há também um exemplo de caderno baseado nas dicas do Ed0906, demonstrando como obter os dados passo a passo. Veja isso

    Eu estou no mesmo barco. Chegando lá devagar. O link de download na página de preços históricos ainda funciona. Então eu adicionei a extensão de cookies de exportação para o firefox, logado no yahoo, joguei fora os cookies. Usado o valor de migalhas da session interativa e consegui recuperar valores. Aqui está parte de um script perl de teste que funcionou.

     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 

    Vai demorar um pouco para automatizar o que faço. Espero que o Yahoo simplifique ou dê alguma orientação sobre isso se eles realmente quiserem que as pessoas o usem.

    Para os amantes de java.

    Você pode acessar seus cookies de uma URLConnection dessa maneira.

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

    Agora você pode procurar a migalha no site do 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(); 

    e finalmente, configurando o cookie

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

    Exemplo de PHP totalmente funcional, com base nesta postagem e nas fonts relacionadas:

     function readYahoo($symbol, $tsStart, $tsEnd) { preg_match('"CrumbStore\":{\"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; } 

    Uso :

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

    Eu encontrei outro site do Yahoo que não exige cookies, mas gera uma saída de jason: https://query1.finance.yahoo.com/v7/finance/chart/YHOO?range=2y&interval=1d&indicators=quote&includeTimestamps=true

    foi apontado daqui para fora: https://www.stock-data-solutions.com/kb/how-to-load-historical-prices-from-yahoo-finance-to-excel.htm

    Como se viu, eles parecem suportar parâmetros ‘perod1’ e ‘period2’ (em tempo unix) que poderiam ser usados ​​em vez do ‘intervalo’.

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

    E o seguinte analisa Jason para mim:

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

    Eu sou o autor deste serviço

    Informação básica aqui

    Preços diários

    Você precisa estar familiarizado com os serviços da RESTFUL.

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

    Preços históricos

    Você precisa fornecer um período:

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

    Se você não fornecer início ou fim, ele usará a data mais antiga ou atual:

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

    Vários tickers

    Você pode apenas separar os tickers:

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

    Taxa limite

    Todas as solicitações são limitadas a 10 solicitações por hora. Se você quer se registrar para uma API de access completo, me envie DM no twitter. Você receberá uma chave de API para adicionar ao URL.

    Estamos configurando uma conta paypal para assinatura paga sem taxas.

    Lista de tickers disponíveis

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

    Estou trabalhando também para fornecer dados fundamentais e dados da empresa da EDGAR. Felicidades.

    VBA

    Aqui estão algumas funções do VBA que baixam e extraem o par cookie / migalha e as retornam em uma Collection , e então as usam para baixar o conteúdo do arquivo csv para um código específico.

    O projeto contendo deve ter uma referência à biblioteca ‘Microsoft XML, v6.0’ adicionada (outra versão pode estar bem também com algumas pequenas alterações no código).

     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 

    Python

    Eu usei este código para obter cookies (copiados do 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[^"]+)"\}') 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 

    então este código para obter resposta:

     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}) 

    Isso parece bom assim http://blog.bradlucas.com/posts/2017-06-03-yahoo-finance-quote-download-python/

    Eu usei um script php usando fopen () para acessar os dados financeiros, aqui estão os trechos que eu modifiquei para voltar ao trabalho:

    Criando os carimbos de data e hora para a data de início e a data de término:

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

    Force fopen () para enviar o cookie necessário com valores codificados:

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

    Use fopen () para obter o arquivo 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); 

    Agora você pode fazer toda a magia que você fez antes neste loop while:

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

    Certifique-se de definir seus próprios valores para $ticker , $crumb e $cookie nos snippets acima. Siga a abordagem do Ed0906 sobre como recuperar $crumb e $cookie .

    Para os usuários do Excel / VBA, usei as sugestões acima para desenvolver um método VBA para extrair os preços históricos do site atualizado do Yahoo. Os snippets de código de chave estão listados abaixo e também forneci minha pasta de trabalho de teste.

    Primeiro, uma solicitação para definir os valores de Crumb e Cookie antes de tentar extrair os dados do Yahoo para os preços.

     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 

    Veja o seguinte extrato do Yahoo Historical Price Extract no meu site para obter um arquivo de amostra e mais detalhes sobre o método que usei para extrair os preços históricos de segurança do site do Yahoo.

    Eu estava no mesmo barco. Eu consegui obter o CSV baixado do Yahoo com alguns códigos vb.net que eu fiz a partir de pedaços do Google, SOF e alguns arranhões na cabeça.

    No entanto, eu descobri o Intrinio (procure), me inscrevi, e minha conta gratuita me dá 500 chamadas históricas de dados por dia, com muito mais dados e muito mais precisos do que o Yahoo. Eu reescrevi meu código para a API Intrinio e estou feliz como um clam.

    BTW, eu não trabalho ou tenho nada a ver com Intrinio, mas eles salvaram minha bunda grande tempo …

    Existe uma correção que encontrei para funcionar bem. Por favor, veja meu post:

    Yahoo Finance API / URL não está funcionando: Correção em Python para o Pandas DataReader, onde segui as etapas em https://pypi.python.org/pypi/fix-yahoo-finance para: $ pip install fix_yahoo_finance –upgrade –no-cache -dir (e também atualizado pandas_datareader para ter certeza) e testado ok:

     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') 

    Observe também que a ordem das duas últimas colunas de dados são ‘Adj Close’ e ‘Volume’, então, para o meu propósito, redefini as colunas para o pedido original:

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

    Você realmente não precisa fazer 2 solicitações para obter dados do Yahoo. Eu uso este link https://ca.finance.yahoo.com/quote/AAAP/history?period1=1474000669&period2=1505536669&interval=1d&filter=history&frequency=1d

    Você poderia pegar o cookie do presente, mas em vez disso, inclui esses dados para você cotação histórica no formato Json. Depois que eu baixar a página eu scarpe os dados Json fora dele. Salva uma solicitação de URL.

    Javascript

    Encontre cookies;

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

    Encontre migalhas;

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

    Encontre migalhas para celular;

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

    e provavelmente é melhor esperar que a página (por exemplo, https://finance.yahoo.com/quote/goog ) seja carregada primeiro, você pode verificar com;

     document.readyState 

    Uma abordagem alternativa às mencionadas até agora (Yahoo, Google e Intrinio) é obter gratuitamente os dados históricos do Alpha Vantage. Seu serviço na web oferece preços de ações diários, diários e ajustados e mais de 50 indicadores técnicos. Eles até entregam diretamente no Excel – também de graça – através do Deriscope. (Eu sou o autor do último.)

    Para usuários do Python 3, mude para

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

    a partir de

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

    e

    response = request.urlopen (url) para response = requests.get (url, cookies = {‘B’: cookie}) dados em response.text

    o formato de dados é totalmente diferente, mas pelo menos está funcionando bem por enquanto

    É possível obter dados atuais e históricos da API do google finance . Funciona muito bem para mim.

    Combinei algumas das idéias acima que lida com a atualização migalha / cookie, especificamente do @Dennis, e criei uma class vb.net que pode ser chamada assim:

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

    A class em si está aqui:

     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"":""(?.+?)""}", 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