90 votes

L'URL de Yahoo Finance ne fonctionne pas

J'utilise l'URL suivante pour récupérer les données historiques de Yahoo Finance depuis un certain temps maintenant, mais cela ne fonctionne plus depuis hier.

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

Lorsque vous naviguez sur ce site, il est indiqué :

Je reviens tout de suite...

Merci de votre patience.

Nos ingénieurs travaillent rapidement pour résoudre ce problème.

Cependant, comme ce problème existe toujours depuis hier, je commence à penser qu'ils ont interrompu ce service ?

Ma recherche de SO ne m'a conduit qu'à ce sujet qui était lié à https, mais...

Quelqu'un d'autre rencontre-t-il ce problème ? Comment puis-je résoudre ce problème ? Offrent-ils un accès différent à leurs données historiques ?

4 votes

Il semble que cela soit arrivé sans aucun avertissement. C'est quoi ce bordel.

0 votes

Cela ne fonctionne plus, cela m'est arrivé aussi, mais j'ai trouvé un moyen très simple de contourner le problème en créant des urls et en récupérant les données directement à l'aide de pandas.

122voto

Ryder Brooks Points 650

Yahoo a opté pour un frontal Reactjs, ce qui signifie que si vous analysez les en-têtes de requête du client vers le backend, vous pouvez obtenir le JSON réel qu'ils utilisent pour remplir les magasins côté client.

Hôtes :

Si vous prévoyez d'utiliser un proxy ou des connexions persistantes utilisez query2.finance.yahoo.com . Mais pour les besoins de cet article, l'hôte utilisé pour les URLs d'exemple n'est pas censé impliquer quoi que ce soit sur le chemin avec lequel il est utilisé.


Données fondamentales

(remplacez votre symbole par : AAPL)

  • /v10/finance/quoteSummary/AAPL?modules=

Entrées pour le ?modules= requête :

    [
       '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']

Exemple d'URL : l'interrogation de tous les modules ci-dessus

  • 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

Le site %2C est la représentation hexagonale de , et doit être inséré entre chaque module que vous demandez. détails sur le bit d'encodage hexagonal (si cela vous intéresse)


Contrats d'options

  • /v7/finance/options/AAPL (expiration en cours)
  • /v7/finance/options/AAPL?date=1679011200 (expiration le 17 mars 2023)

Exemple d'URL :

  • https://query2.finance.yahoo.com/v7/finance/options/AAPL (expiration en cours)
  • https://query2.finance.yahoo.com/v7/finance/options/AAPL?date=1679011200 (expiration du Match 17, 2023)

Toute expiration future valide représentée par un horodatage UNIX peut être utilisée dans la fonction ?date= requête. Si vous demandez l'expiration en cours, la réponse JSON contiendra une liste de toutes les expirations valides qui peuvent être utilisées dans l'application ?date= requête. (voici un post expliquant la conversion de dates lisibles par l'homme en timestamp UNIX en Python)


Prix

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

Entrées possibles pour &interval= : 1m, 5m, 15m, 30m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo

m (minute) Les intervalles sont limités à 30 jours avec period1 et period2 s'étendant sur un maximum de 7 jours par/demande. Le dépassement de l'une ou l'autre de ces limites entraînera une erreur et ne fera pas le tour

h (heure) L'intervalle est limité à 730 jours, sans limite de portée. Le dépassement de cette limite entraînera une erreur et une ne fera pas le tour

period1= : Représentation de l'horodatage UNIX de la date que vous souhaitez commencer à.

d (jour) , wk (semaine) , mo (mois) Les intervalles dont la valeur est inférieure à la date de négociation initiale seront arrondis à la date de négociation initiale.

period2= : Représentation de l'horodatage UNIX de la date que vous souhaitez fin à.

Pour tous les intervalles : les valeurs supérieures à la dernière date de transaction seront arrondies à l'horodatage le plus récent disponible.

Ajouter des données pré et post marché

&includePrePost=true

Ajouter les dividendes et les fractionnements

&events=div%7Csplit

%7C est un hexagone pour | . , fonctionnera mais yahoo utilise en interne le pipe

Exemple d'URL :

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

La requête ci-dessus renverra toutes les données de prix pour le ticker AAPL sur un intervalle d'un jour, y compris les données avant et après le marché, ainsi que les dividendes et les fractionnements.

Note : les valeurs utilisées dans l'exemple de prix URL pour period1= & period2= sont pour démontrer le comportement d'arrondi respectif de chaque entrée. `

5 votes

Bonjour @ryder-brooks, merci pour votre excellent article ! Pourriez-vous poster votre lien github ?

2 votes

Comment avez-vous trouvé la liste de "tous" les modules ? Pouvez-vous décrire le processus de recherche de la liste des modules ? Merci !

0 votes

Comment avez-vous découvert les modules et les terminaux ?

50voto

Edd Points 3097

Il semble qu'ils aient commencé à ajouter un cookie obligatoire, mais vous pouvez le récupérer assez facilement, par exemple :

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

Répond avec l'en-tête dans le formulaire :

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

Vous devriez être en mesure de le lire et de l'attacher à votre .csv demande :

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;

Notez le crumb ce qui semble correspondre à votre paramètre de requête cookie d'une manière ou d'une autre. Votre meilleure chance est de scrape ceci à partir de la réponse HTML à votre requête GET initiale. Dans cette réponse, vous pouvez faire une recherche regex pour : "CrumbStore":\{"crumb":"(?<crumb>[^"]+)"\} et extraire le groupe correspondant aux miettes.

Il semble qu'une fois que vous avez crumb bien que vous puissiez l'utiliser avec la même cookie sur n'importe quel symbole/ticker pour l'année prochaine, ce qui signifie que vous ne devriez pas avoir à faire la scrape trop fréquemment.


Pour obtenir des devis actuels, il suffit de charger :

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

Avec :

  • AAPL remplacé par votre ticker boursier
  • l'un des intervalles suivants [1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo]
  • en option period1 paramètre de requête avec la date de début de votre plage d'époque, par exemple period1=1510340760
  • en option period2 paramètre de la requête avec la date de fin de la plage d'époque, par exemple period2=1510663712

0 votes

Une idée sur la façon de gratter cette miette ?

0 votes

@RupertPupkin Pour l'instant, vous pouvez probablement vous en sortir en codant en dur la valeur des miettes et des cookies dans votre application, car ils ont une durée de vie d'un an.

3 votes

@RupertPupkin Mise à jour avec la façon de gratter la miette.

23voto

Dennis Points 417

J'ai réussi à mettre au point une classe .NET pour obtenir des jetons valides (cookie et crumb) de Yahoo Finance.

Pour obtenir la bibliothèque API complète permettant de récupérer les données historiques du nouveau Yahoo Finance, vous pouvez visiter le site suivant YahooFinanceAPI dans Github

Voici la classe pour attraper le cookie et la miette

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;

        }

    }
}

Mis à jour le 1 juin 17
crédits à @Ed0906
modifier le motif regex de la mie en Regex("CrumbStore\":{\"crumb\":\"(?<crumb>.+?)\"}"

0 votes

J'ai jeté un coup d'oeil à votre code. Il semble très bon. Je vais l'essayer demain. Merci beaucoup d'avance !

0 votes

Merci beaucoup ! Cela fonctionne parfaitement. Entre nous tous, probablement des millions d'heures économisées !

0 votes

Aujourd'hui, j'ai remplacé l'Api Yahoo obsolète par la nouvelle basée sur vos deux classes. Cela a très bien fonctionné. Je vous remercie beaucoup. Malheureusement, il n'y avait pas de bouton Paypal. Je n'ai donc pas pu faire de don pour toute la peine que vous m'avez épargnée ;)

14voto

Ximix Points 161

Dans ce forum : https://forums.yahoo.net/t5/Yahoo-Finance-help/Is-Yahoo-Finance-API-broken/td-p/250503/page/3

Nixon a dit :

Bonjour à tous - Cette fonctionnalité a été abandonnée par l'équipe des finances et elle ne sera pas réintroduite.

13voto

whbogado Points 121

L'URL pour le téléchargement des données historiques est maintenant quelque chose comme ceci :

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

Notez que l'URL ci-dessus ne fonctionnera pas pour vous ni pour personne d'autre. Vous obtiendrez quelque chose comme ceci :

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

Il semble que Yahoo utilise maintenant un système de hachage pour empêcher les gens d'accéder aux données comme vous l'avez fait. L'URL varie à chaque session, il est donc très probable que vous ne puissiez plus faire cela avec une URL fixe.

Vous devrez faire un peu de récupération pour obtenir l'URL correct de la page principale, par exemple :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X