File indexing completed on 2024-04-28 16:30:15

0001 #!/usr/bin/env python3
0002 # -*- coding: utf-8 -*-
0003 #***************************************************************************
0004 #* SPDX-FileCopyrightText: 2022 S. MANKOWSKI stephane@mankowski.fr
0005 #* SPDX-FileCopyrightText: 2022 G. DE BURE support@mankowski.fr
0006 #* SPDX-License-Identifier: GPL-3.0-or-later
0007 #***************************************************************************
0008 
0009 """
0010 Created on Thu May 18 22:58:12 2017
0011 @author: c0redumb
0012 """
0013 
0014 # To make print working for Python2/3
0015 from __future__ import print_function
0016 
0017 # Use six to import urllib so it is working for Python2/3
0018 from six.moves import urllib
0019 # If you don't want to use six, please comment out the line above
0020 # and use the line below instead (for Python3 only).
0021 #import urllib.request, urllib.parse, urllib.error
0022 
0023 import time
0024 import sys
0025 
0026 '''
0027 Starting on May 2017, Yahoo financial has terminated its service on
0028 the well used EOD data download without warning. This is confirmed
0029 by Yahoo employee in forum posts.
0030 Yahoo financial EOD data, however, still works on Yahoo financial pages.
0031 These download links uses a "crumb" for authentication with a cookie "B".
0032 This code is provided to obtain such matching cookie and crumb.
0033 '''
0034 
0035 # Build the cookie handler
0036 cookier = urllib.request.HTTPCookieProcessor()
0037 opener = urllib.request.build_opener(cookier)
0038 urllib.request.install_opener(opener)
0039 
0040 # Cookie and corresponding crumb
0041 _cookie = None
0042 _crumb = None
0043 
0044 def _get_cookie_crumb(ticker):
0045     '''
0046     This function perform a query and extract the matching cookie and crumb.
0047     '''
0048     # Perform a Yahoo financial lookup
0049     url = 'https://finance.yahoo.com/quote/' + ticker
0050     hdr = { 'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)',
0051         'content-type': 'text/html; charset=utf-8'}
0052     req = urllib.request.Request(url, headers=hdr)
0053     f = urllib.request.urlopen(req)
0054     alines = f.read()
0055     alines = alines.decode('utf-8')
0056 
0057     # Extract the crumb from the response
0058     global _crumb
0059     cs = alines.find('CrumbStore')
0060     cr = alines.find('crumb', cs + 10)
0061     cl = alines.find(':', cr + 5)
0062     q1 = alines.find('"', cl + 1)
0063     q2 = alines.find('"', q1 + 1)
0064     crumb = alines[q1 + 1:q2]
0065     _crumb = crumb
0066 
0067     # Extract the cookie from cookiejar
0068     global cookier, _cookie
0069     for c in cookier.cookiejar:
0070         if c.domain != '.yahoo.com':
0071             continue
0072         if c.name != 'B':
0073             continue
0074         _cookie = c.value
0075 
0076 def load_yahoo_quote(ticker, begindate, enddate, interval):
0077     '''
0078     This function load the corresponding history from Yahoo.
0079     '''
0080     # Check to make sure that the cookie and crumb has been loaded
0081     global _cookie, _crumb
0082     if _cookie == None or _crumb == None:
0083         _get_cookie_crumb(ticker)
0084         
0085     begindate = begindate.replace('-', '')
0086     enddate = enddate.replace('-', '')
0087 
0088     # Prepare the parameters and the URL
0089     tb = int(time.mktime((int(begindate[0:4]), int(begindate[4:6]), int(begindate[6:8]), 0, 0, 0, 0, 0, 0)))
0090     te = int(time.mktime((int(enddate[0:4]), int(enddate[4:6]), int(enddate[6:8]), 0, 0, 0, 0, 0, 0)))
0091     if te == tb:
0092         tb = tb -1 
0093 
0094     param = dict()
0095     param['period1'] = tb
0096     param['period2'] = te
0097     param['interval'] = interval
0098     param['events'] = 'history'
0099     param['crumb'] = _crumb
0100     params = urllib.parse.urlencode(param)
0101     url = 'https://query1.finance.yahoo.com/v7/finance/download/{}?{}'.format(ticker, params)
0102 
0103     # Perform the query
0104     # There is no need to enter the cookie here, as it is automatically handled by opener
0105     try:
0106         f = urllib.request.urlopen(url)
0107         alines = f.read().decode('utf-8')
0108         return sorted(alines.split('\n'), reverse=True)
0109     except IOError:
0110         return ["Date,Open,High,Low,Close,Adj Close,Volume"]
0111 
0112 
0113 for l in load_yahoo_quote(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]):
0114     print(l)