I used yahoo and then a google package but both had issues, so I modified
my script to pull from finance.google.com. The json appeared to be broken
so I used regex to extract price and date.
On Tuesday, November 7, 2017 at 8:36:25 AM UTC-6, Jim Robinson wrote:
>
> Hi Folks,
>
> Does anyone here have an alternative to the yahoo finance api for pulling
> daily pricedb values?
>
> Looks like folks were abusing the yahoo site and they've shut down the
> service.
>
> I could just plug in the data manually, but having an api I could kick off
> periodically to pull down the dozen or so symbols was much nicer.
>
>
> Jim
>
>
--
---
You received this message because you are subscribed to the Google Groups
"Ledger" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
#!/usr/bin/env python
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import argparse
import re
import sys
from datetime import datetime
from dateutil.relativedelta import relativedelta
import requests
quote_url = 'https://finance.google.com/finance?q={}&output=json'
field_regex_pattern = r'"{}"\s*:\s*"([^"]+)"'
price_field_regex = re.compile(field_regex_pattern.format('nav_prior'))
date_field_regex = re.compile(field_regex_pattern.format('nav_time'))
date_regex_pattern = r'([A-Za-z]+)\s*([0-9]+),'
date_parts_regex = re.compile(date_regex_pattern)
def download(price_file=None):
symbols = [
'blah1', # your stuff
'blah2', # your stuff
]
for symbol in symbols:
response = requests.get(quote_url.format(symbol))
if response.status_code == 200:
try:
the_date, the_price = get_quote_data(response)
except Exception as e:
print('Error loading {}: {}'.format(symbol, e))
continue
else:
print('Error downloading {symbol}. Received code {code}.'.format(
symbol=symbol,
code=response.status_code
))
continue
print('{date:12} {inv:8} ${price}'.format(
date=the_date,
inv=symbol,
price=the_price
))
if price_file:
with open(price_file, 'a') as the_file:
the_file.write('P {date} {inv:10} ${price}\n'.format(
date=the_date,
inv=symbol,
price=the_price
))
def get_quote_data(response):
# google finance json appears to be broken, so will use crude string stuff
data = response.content[6:-2].decode('unicode_escape')
the_price = regex_search(data, price_field_regex, 'price')
the_date = regex_search(data, date_field_regex, 'date')
return get_date(the_date), the_price
def regex_search(data, regex, label):
match = regex.search(data)
if match:
return match.groups()[0]
else:
raise Exception("Couldn't find {}.".format(label))
def get_date(quote_date):
last_month_abbreviated = (
datetime.now() + relativedelta(months=-1)
).strftime('%b')
date_parts_match = date_parts_regex.search(quote_date)
if date_parts_match:
quote_month_abbreviated = date_parts_match.groups()[0]
quote_day = date_parts_match.groups()[1]
else:
raise Exception("Couldn't parse date parts.")
if (quote_month_abbreviated == last_month_abbreviated
and last_month_abbreviated == 'Dec'):
quote_year = (datetime.now() + relativedelta(years=-1)).strftime('%Y')
else:
quote_year = datetime.now().strftime('%Y')
# date seems to come back a day off, e.g. 6/15/17 instead of 6/16/17,
# so we'll add 1
the_date = datetime.strptime(
'{} {} {}'.format(quote_month_abbreviated, quote_day, quote_year),
'%b %d %Y'
) + relativedelta(days=1)
return the_date.strftime('%Y/%m/%d')
class ArgHandler(object):
@staticmethod
def get_args(args):
parser = argparse.ArgumentParser()
parser.add_argument(
'-f', '--file',
type=str,
help='save to this prices db file',
)
return parser.parse_args(args)
def main(argv=None): # pragma: no cover
if argv is None:
argv = sys.argv[1:]
args = ArgHandler.get_args(argv)
download(args.file)
if __name__ == '__main__': # pragma: no cover
sys.exit(main())