I have a recursive script that's scraping a JSON file for cars. At each recursive level, it gets a new variable added, and passes that (along with the other values) on to the recursive call, each time getting more and more detailed in the information. I tried to use locals()
to dynamically assign a variable, but it remains None
even after the call (I recall seeing that sometimes locals()
is read only).
I tried using eval()
as well, and it gives me the same issue (I know eval is not ideal). I'd ideally like to avoid using a dictionary, because that would require me to load it with values first, which seems like it has some unnecessary steps, but I'm open to anything at this point.
Example:
scraper(manufacturer='Honda')
would scrape a JSON file of models, set model='Accord'
and then recursively call
scraper(manufacturer='Honda, model='Accord')
which scrapes a file of years, set's year=2014
and recursively calls
scraper(manufacturer='Honda', model='Accord', year='2014')
which is the base case
def scraper(self, manufacturers, model=None, year=None):
if year:
scrapeurl = '%s&manufacturer=%s&model=%s&year=%s' % (url, manufacturer, model, year)
return someFinalFunction()
elif model:
scrapeurl = '%s&manufacturer=%s&model=%s' % (url, manufacturer, model)
elif manufacturer:
scrapeurl = '%s&manufacturer=%s' % (url, manufacturer)
j = getJSONFromUrl(scrapeurl)
key, values = j.popitems()
for value in values:
locals()[key] = value
return self.scraper(manufacturer, model, year, color)
I'd appreciate any input on how to handle this, I know Python always seems to have some clever ways of doing things, and I'm always learning more about it, so thank you in advance! I'm using Python3 in this example too, if that changes anything
It's not entirely clear what you're trying to do, but perhaps this will help:
def scraper(self, **kwargs):
if kwargs.get('year') is not None:
scrapeurl = '{0}&manufacturer={manufacturer}&model={model}&year={year}'
return someFinalFunction() # not sure why this takes no arguments
elif kwargs.get('model') is not None:
scrapeurl = '{0}&manufacturer={manufacturer}&model={model}'
elif kwargs.get('manufacturer') is not None:
scrapeurl = '{0}&manufacturer={manufacturer}'
else:
raise KeyError
j = getJSONFromUrl(scrapeurl.format(url, **kwargs))
key, values = j.popitems()
for value in values:
kwargs[key] = value
return self.scraper(**kwargs)
This uses Python's built-in functionality to treat arbitrary keyword arguments as a dictionary, along with more modern str.format
string formatting, to dynamically handle the arguments you're looking for. The only difference is that you now need to call it:
instance.scraper(manufacturer='...')
rather than just
instance.scraper('...')
An example of the string formatting, mixing positional and keyword arguments:
>>> '{0}&manufacturer={manufacturer}'.format('foo', **{'manufacturer': 'bar'})
'foo&manufacturer=bar'