Yahoo Finance URL ne fonctionne pas
j'ai utilisé L'URL suivante pour récupérer des données historiques de yahoo finance depuis un certain temps maintenant, mais il a cessé de fonctionner à partir d'hier.
https://ichart.finance.yahoo.com/table.csv?s=SPY
lors de la navigation sur ce site, il est dit:
Sera de retour...
merci de votre patience.
nos ingénieurs travaillez rapidement pour résoudre le problème.
cependant, comme ce problème existe toujours depuis hier, je commence à penser qu'ils ont abandonné ce service?
mon SO recherche m'a seulement indiqué à ce sujet , qui était lié à https cependant...
Est ce que quelqu'un d'autre rencontre ce problème? Comment puis-je résoudre ce problème? Offrent-ils un accès différent à leurs Données historiques?
23 réponses
On dirait qu'ils ont commencé à ajouter un nécessaire cookies, mais vous pouvez récupérer assez facilement, par exemple:
GET https://uk.finance.yahoo.com/quote/AAPL/history
répond avec l'en-tête dans la forme:
set-cookie:B=xxxxxxxx&b=3&s=qf; expires=Fri, 18-May-2018 00:00:00 GMT; path=/; domain=.yahoo.com
vous devriez pouvoir lire ceci et le joindre à votre demande .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;
Notez le paramètre de requête crumb
, cela semble correspondre à votre cookie
d'une certaine manière. Votre meilleur pari est de scrape
ceci provient de la réponse HTML à votre demande GET initiale. Dans cette réponse, vous pouvez effectuer une recherche regex pour: "CrumbStore":\{"crumb":"(?<crumb>[^"]+)"\}
et extraire le groupe de correspondance crumb.
il ressemble à une fois que vous avez que crumb
valeur, bien que vous pouvez l'utiliser avec le même cookie
sur n'importe quel symbole/téléscripteur pour l'année suivante, ce qui signifie que vous ne devriez pas avoir à faire le scrape
trop fréquemment.
charge:
https://query1.finance.yahoo.com/v8/finance/chart/AAPL?interval=2m
avec:
- AAPL substitué avec votre stock ticker
- intervalle un de
[1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo]
- optionnel
period1
param de requête avec votre date de début de gamme d'époque par exempleperiod1=1510340760
- optionnel
period2
param de requête avec votre intervalle d'époque date de fin par exempleperiod2=1510663712
j'ai réussi à mettre au point une classe .NET pour obtenir un token valide (cookie et crumb) de Yahoo Finance
pour la bibliothèque API complète dans la recherche de données historiques de New Yahoo Finance, vous pouvez visiter YahooFinanceAPI in Github
Voici la classe pour saisir le biscuit 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;
}
}
}
Mise À Jour Le 1er Juin 17
les crédits à @Ed0906
modifier le motif de crumb regex en Regex("CrumbStore\":{\"crumb\":\"(?<crumb>.+?)\"}"
Yahoo est allé à un front end de Reactjs ce qui signifie que si vous analysez les en-têtes de requête du client au backend vous pouvez obtenir le JSON réel qu'ils utilisent pour peupler les magasins côté client.
Hosts:
-
query1.finance.yahoo.com
HTTP / 1.0 -
query2.finance.yahoo.com
HTTP / 1.1 ( différence entre HTTP/1.0 ET HTTP/1.1 )
si vous prévoyez utiliser une procuration ou les connexions persistantes utilisent query2.finance.yahoo.com
. Mais pour les fins de ce poste l'hôte utilisé pour les exemples d'Url ne veut pas dire quelque chose sur le chemin il est utilisé avec.
Données Fondamentales
-
/v10/finance/quoteSummary/AAPL?modules=
(liste complète des modules ci-dessous)
(remplacer votre symbole par: AAPL)
Intrants pour la requête ?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' ]
exemple D'URL:
-
https://query1.finance.yahoo.com/v10/finance/quoteSummary/AAPL?modules=assetProfile%2CearningsHistory
Interrogation de : assetProfile
et earningsHistory
le %2C
est la représentation hexadécimale de ,
et doit être inséré entre chaque module vous demande. détails sur le bit d'encodage hex (si vous vous en souciez)
contrats D'Options
-
/v7/finance/options/AAPL
(date d'expiration actuelle) -
/v7/finance/options/AAPL?date=1579219200
(expiration le 17 janvier 2020)
exemple D'URL:
-
https://query2.yahoo.finance.com/v7/finance/options/AAPL
(date d'expiration actuelle) -
https://query2.yahoo.finance.com/v7/finance/options/AAPL?date=1579219200
(expiration le 17 janvier 2020)
toute expiration future valide représentée sous forme D'horodatage UNIX peut être utilisée dans la requête ?date=
. Si vous interrogez pour l'expiration courante, la réponse JSON contiendra une liste de toutes les expirations valides qui peuvent être utilisées dans la requête ?date=
. (voici un billet expliquant la conversion de dates lisibles par l'homme en horodatage unix en Python)
Prix
-
/v8/finance/chart/AAPL?symbol=AAPL&period1=0&period2=9999999999&interval=3mo
intervalles:
-
&interval=3mo
3 des mois, remontant jusqu'à la date de négociation initiale. -
&interval=1d
1 jour, remontant jusqu'à la date de négociation initiale. -
&interval=5m
5 minutes, remontant à 80(ish) jours. -
&interval=1m
1 minute, retour 4-5 jours.
Jusqu'à quel point vous pouvez remonter avec chaque intervalle est un peu confus et semble incohérent. Mon hypothèse est que yahoo interne compte dans les jours de commerce et mon approche naïve ne tenait pas compte des vacances. Bien que ce soit une supposition et YMMV.
period1=
: représentation unix timestamp de la date à laquelle vous souhaitez démarrer at. Les valeurs ci-dessous la négociation initiale date sera arrondi à la première date de transaction.
period2=
: représentation unix timestamp de la date que vous souhaitez fin at. Les valeurs supérieures à la dernière date d'échange seront arrondies à l'heure la plus récente disponible.
Note: si vous interrogez avec un period1=
(date de début) qui est trop loin dans le passé pour l'intervalle que vous avez choisi, yahoo retournera les prix dans l'intervalle 3mo
quel que soit l'intervalle que vous avez demandé.
ajouter données avant et après commercialisation
&includePrePost=true
ajouter dividendes & splits
&events=div%2Csplit
exemple D'URL:
-
https://query1.finance.yahoo.com/v8/finance/chart/AAPL?symbol=AAPL&period1=0&period2=9999999999&interval=1d&includePrePost=true&events=div%2Csplit
la demande ci-dessus retournera toutes les données de prix pour le téléscripteur AAPL sur un intervalle d'un jour, y compris les données avant et après la mise en marché ainsi que les dividendes et les Divis ions.
Note: les valeurs utilisées dans l'url d'exemple de prix pour period1=
& period2=
doivent démontrer le comportement d'arrondissement respectif de chaque entrée.
dans ce forum: https://forums.yahoo.net/t5/Yahoo-Finance-help/Is-Yahoo-Finance-API-broken/td-p/250503/page/3
Nixon a dit:
Salut tout le monde - cette fonctionnalité a été abandonnée par L'équipe des Finances et ils ne seront pas réintroduire cette fonctionnalité.
L'URL pour télécharger des données historiques est maintenant quelque chose comme ceci:
notez que L'URL ci-dessus ne fonctionnera pas pour vous ou quelqu'un d'autre. Vous obtiendrez quelque chose comme ceci:
{
"finance": {
"error": {
"code": "Unauthorized",
"description": "Invalid cookie"
}
}
}
il semble que Yahoo utilise maintenant un certain hashing pour empêcher les gens d'avoir accès aux données comme vous l'avez fait. L'URL varie avec chaque session, il est donc très probable que vous ne puissiez plus faire cela avec une URL fixe.
vous aurez besoin de faire un peu de suppression pour obtenir L'URL correcte à partir de la page principale, par exemple:
pour les amateurs de python là-bas, j'ai mis à jour le yahooFinance.py dans tradingWithPython library.
il y a aussi un exemple notebook basé sur les conseils de Ed0906, montrant comment obtenir les données étape par étape. Voir
je suis dans le même bateau. Comment y arriver lentement. Le lien de téléchargement sur la page des prix historiques fonctionne toujours. J'ai ajouté l'extension export cookies à firefox, je me suis connecté à yahoo, j'ai jeté les cookies. J'ai utilisé la valeur crumb de la session interactive et j'ai pu récupérer des valeurs. Voici une partie d'un script perl test qui a fonctionné.
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
ça va prendre du temps d'automatiser ce que je fais. Avec un peu de chance, yahoo simplifiera ou donnera quelques conseils à ce sujet si vraiment l'intention de gens à l'utiliser.
pour les amoureux de java.
vous pouvez accéder à vos cookies à partir d'une connexion URL de cette façon.
// "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
...
}
}
maintenant vous pouvez rechercher la miette dans le site 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();
et enfin, configurer le 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();
Fully working PHP example , basé sur ce post et des sources connexes:
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;
}
Utilisation :
$csv = readYahoo('AAPL', mktime(0, 0, 0, 6, 2, 2017), mktime(0, 0, 0, 6, 3, 2017));
j'avais trouvé un autre site yahoo qui ne nécessite pas de cookies, mais génère jason sortie: https://query1.finance.yahoo.com/v7/finance/chart/YHOO?range=2y&interval=1d&indicators=quote&includeTimestamps=true
il a été souligné d'ici: https://www.stock-data-solutions.com/kb/how-to-load-historical-prices-from-yahoo-finance-to-excel.htm
comme il s'est avéré qu'ils semblent soutenir les paramètres' perod1 'et' period2 '(en temps unix) qui peuvent être utilisés à la place du'interval'.
String quoteSite = "https://query1.finance.yahoo.com/v7/finance/chart/"
+ symbolName + "?"
+ "period1=" + period1
+ "&period2=" + period2
+ "&interval=1d&indicators=quote&includeTimestamps=true";
et les parses Jason suivants pour moi:
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");
je suis l'auteur de ce service
informations de base ici
prix quotidiens
vous devez vous familiariser avec les services de repos.
https://quantprice.herokuapp.com/api/v1.1/scoop/day?tickers=MSFT&date=2017-06-09
prix historiques
vous devez fournir une plage de dates:
https://quantprice.herokuapp.com/api/v1.1/scoop/period?tickers=MSFT&begin=2012-02-19&end=2012-02-20
si vous ne fournissez pas begin ou end, il utilisera la date la plus ancienne ou actuelle:
https://quantprice.herokuapp.com/api/v1.1/scoop/period?tickers=MSFT&begin=2012-02-19
Multiple tickers
il suffit de virgule pour séparer les titres:
https://quantprice.herokuapp.com/api/v1.1/scoop/period?tickers=IBM,MSFT&begin = 2012-02-19
Taux limite
toutes les demandes sont limitées à 10 demandes par heure. Si vous souhaitez vous inscrire pour une API d'accès complet, envoyez-moi DM sur twitter. Vous recevrez une clé API à ajouter à la URL.
nous sommes en train de créer un compte paypal pour un abonnement payant sans frais.
Liste des tickers disponible
https://github.com/robomotic/valueviz/blob/master/scoop_tickers.csv
je travaille aussi à fournir des données fondamentales et des données d'entreprise à partir D'EDGAR. Acclamation.
VBA
voici quelques fonctions VBA qui téléchargent et extraient la paire cookie / crumb et les renvoient dans un Collection
, puis les utilisent pour télécharger le contenu du fichier csv pour un code particulier.
le projet containing doit avoir une référence au 'Microsoft XML, v6.0 ' bibliothèque ajoutée (une autre version pourrait être bien aussi avec quelques modifications mineures au code).
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
j'ai utilisé ce code pour obtenir cookie (copié de 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
puis ce code pour obtenir la réponse:
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})
C'est joli aussi http://blog.bradlucas.com/posts/2017-06-03-yahoo-finance-quote-download-python /
j'ai utilisé un script php en utilisant fopen () pour accéder aux données financières, voici les extraits que j'ai modifiés pour le remettre au travail:
Créer le timestamp de la date de début et date de fin:
$timestampStart = mktime(0,0,0,$startMonth,$startDay,$startYear);
$timestampEnd = mktime(0,0,0,$endMonth,$endDay,$endYear);
Force fopen () pour envoyer le cookie requis avec des valeurs codées dures:
$cookie="YourCookieTakenFromYahoo";
$opts = array(
'http'=>array(
'method'=>"GET",
'header'=>"Accept-language: en\r\n" .
"Cookie: B=".$cookie."\r\n"
)
);
$context = stream_context_create($opts);
utilisez fopen () pour obtenir le fichier 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);
Maintenant, vous pouvez faire toute la magie que vous avez fait avant à l'intérieur de cette boucle while:
while (!feof($handle) ) {
$line_of_text = fgetcsv($handle, 5000);
}
assurez-vous de définir vos propres valeurs pour $ticker
, $crumb
et $cookie
dans les extraits ci-dessus.
Suivez l'approche de Ed0906 sur la façon de récupérer $crumb
et $cookie
.
pour les utilisateurs Excel / VBA j'ai utilisé les suggestions ci-dessus pour développer une méthode VBA pour extraire les prix historiques à partir du site Yahoo mis à jour. Les extraits de code clé sont énumérés ci-dessous et j'ai aussi fourni mon cahier de test.
D'abord une demande pour obtenir les valeurs de miette et de Cookie définies avant d'essayer d'extraire les données de Yahoo pour les prix..
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
voir le suivant extrait de prix historique de Yahoo lien vers mon site web pour un fichier échantillon et plus de détails sur la méthode que j'ai utilisée pour extraire les prix historiques de la sécurité du site Yahoo
j'étais sur le même bateau. J'ai réussi à obtenir le CSV téléchargé de Yahoo avec certains vb.net frankencode Je l'ai fait à partir de morceaux et morceaux de Google, SOF et certains tête-grattage.
cependant, J'ai découvert Intrinio (chercher), je me suis inscrit, et mon compte gratuit me permet de recevoir 500 appels d'api Données historiques par jour, avec beaucoup plus de données et beaucoup plus de précision que Yahoo. J'ai réécrit mon code pour L'API D'Intrinio, et je suis heureux comme une palourde.
BTW, Je ne travaille pas ou ça a quelque chose à voir avec Intrinio, mais ils m'ont sauvé la mise...
il y a un correctif que j'ai trouvé qui fonctionne bien. Veuillez voir mon post:
Yahoo Finance API / URL ne fonctionne pas: Python correctif pour les Pandas DataReader où j'ai suivi les étapes dans https://pypi.python.org/pypi/fix-yahoo-finance : $ pip install fix_yahoo_finance --upgrade --no-cache-dir (et également mis à jour pandas_datareader pour être sûr) et testé 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')
notez également que l'ordre des 2 dernières colonnes de données sont 'Adj Close' et 'Volume' donc pour mon but, j'ai réinitialisé les colonnes à l'ordre original:
cols = ['Date', 'Open', 'High', 'Low', 'Close', 'Volume', 'Adj Close']
data = data.reindex(columns=cols)
en fait, vous n'avez pas besoin de faire 2 requêtes pour obtenir des données Yahoo. J'utilise ce lien https://ca.finance.yahoo.com/quote/AAAP/history?period1=1474000669&period2=1505536669&interval=1d&filter=history&frequency=1d
vous pouvez saisir le cookie de la ceci mais à la place il inclut ces données pour vous citation historique dans le format Json. Après avoir téléchargé la page je scarpe les données Json hors de lui. Enregistre une requête d'url.
Javascript
Trouver cookie;
match = document.cookie.match(new RegExp('B=([^;]+)'));
alert (match[1]);
Trouver miette;
i=document.body.innerHTML.search("CrumbStore")
if (i>=0) alert (document.body.innerHTML.substr(i+22,11))
trouver crumb pour mobile;
i=document.body.innerHTML.search('USER={\"crumb\":');
if (i>=0) alert(document.body.innerHTML.substr(i+15,11));
et il est probablement préférable d'attendre la page (E. g https://finance.yahoo.com/quote/goog ) pour charger en premier, vous pouvez
document.readyState
une approche alternative à celles mentionnées jusqu'à présent (Yahoo, Google et Intrinio) est d'obtenir gratuitement les données historiques D'Alpha Vantage. Leur service Web offre quotidiennement des cours d'actions ajustés et des indicateurs techniques de plus de 50 ans. Ils livrent même directement à excellent - également gratuitement - à travers Deriscope. (Je suis l'auteur de cette dernière.)
pour les utilisateurs de Python 3, remplacer par
de
url = ' https://chartapi.finance.yahoo.com/instrument/1.0/AAAP/chartdata;type=quote; range=10d / csv/ '
et
réponse = demande.urlopen(url) de réponse = demandes.get (url, cookies={'B': cookie}) les données en réponse.texte
le format de données est totalement différent mais au moins son bon fonctionnement pour l'instant
Il est possible d'obtenir des données actuelles et historiques de api google finance . Fonctionne très bien pour moi.
j'ai combiné quelques-unes des idées ci-dessus qui gère le rafraîchissement crumb / cookie, en particulier de @Dennis, et a créé un vb.net classe que l'on peut appeler comme ceci:
Dim f = Await YahooFinanceFactory.CreateAsync
Dim items1 = Await f.GetHistoricalDataAsync("SPY", #1/1/2018#)
Dim items2 = Await f.GetHistoricalDataAsync("^FTSE", #1/1/2018#)
la classe elle-même est ici:
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