I have the following file (associate.py)
import bottlenose
from bs4 import BeautifulSoup
from urllib2 import HTTPError
;; My real keys are here in reality, I just replaced them
;; with the following because they are private.
credentials = {'access-key' : 'MY_ACCESS_KEY_GOES_HERE',
'secret-key' : 'MY_SECRET_KEY_GOES_HERE',
'associate-tag' : 'MY_ASSOCIATE_TAG'}
def error_handler(err):
ex = err['exception']
if isinstance(ex, HTTPError) and ex.code == 503:
time.sleep(random.expovariate(0.1))
return True
api = bottlenose.Amazon(credentials['access-key'],
credentials['secret-key'],
credentials['associate-tag'],
Parser=BeautifulSoup,
ErrorHandler=error_handler,
MaxQPS=0.9)
def get_item(asin):
return api.ItemLookup(ItemId=asin,
ResponseGroup="Large,Images,ItemAttributes")
Here is the result of my Ipython session using the above:
In [1]: import associate
In [2]: associate.get_item("B003K1IJWC")
---------------------------------------------------------------------------
HTTPError Traceback (most recent call last)
<ipython-input-2-31ffe6a959e1> in <module>()
----> 1 associate.get_item("B003K1IJWC")
/home/stephen/work/pantry/associate.pyc in get_item(asin)
22 def get_item(asin):
23 return api.ItemLookup(ItemId=asin,
---> 24 ResponseGroup="Large,Images,ItemAttributes")
/home/stephen/work/pantry/bottlenose/api.pyc in __call__(self, **kwargs)
240 # make the actual API call
241 response = self._call_api(api_url,
--> 242 {'api_url': api_url, 'cache_url': cache_url})
243
244 # decompress the response if need be
/home/stephen/work/pantry/bottlenose/api.pyc in _call_api(self, api_url, err_env)
201 else:
202 # the simple way
--> 203 return urllib2.urlopen(api_request, timeout=self.Timeout)
204 except:
205 if not self.ErrorHandler:
/usr/lib/python2.7/urllib2.pyc in urlopen(url, data, timeout)
125 if _opener is None:
126 _opener = build_opener()
--> 127 return _opener.open(url, data, timeout)
128
129 def install_opener(opener):
/usr/lib/python2.7/urllib2.pyc in open(self, fullurl, data, timeout)
408 for processor in self.process_response.get(protocol, []):
409 meth = getattr(processor, meth_name)
--> 410 response = meth(req, response)
411
412 return response
/usr/lib/python2.7/urllib2.pyc in http_response(self, request, response)
521 if not (200 <= code < 300):
522 response = self.parent.error(
--> 523 'http', request, response, code, msg, hdrs)
524
525 return response
/usr/lib/python2.7/urllib2.pyc in error(self, proto, *args)
446 if http_err:
447 args = (dict, 'default', 'http_error_default') + orig_args
--> 448 return self._call_chain(*args)
449
450 # XXX probably also want an abstract factory that knows when it makes
/usr/lib/python2.7/urllib2.pyc in _call_chain(self, chain, kind, meth_name, *args)
380 func = getattr(handler, meth_name)
381
--> 382 result = func(*args)
383 if result is not None:
384 return result
/usr/lib/python2.7/urllib2.pyc in http_error_default(self, req, fp, code, msg, hdrs)
529 class HTTPDefaultErrorHandler(BaseHandler):
530 def http_error_default(self, req, fp, code, msg, hdrs):
--> 531 raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
532
533 class HTTPRedirectHandler(BaseHandler):
HTTPError: HTTP Error 400: Bad Request
The odd thing is that the above request associate.get_item("B003K1IJWC")
works just fine on my laptop, but fails as seen on my desktop.
My laptop is Crouton Ubuntu 12.04 with python 2.7.5, my Desktop is Ubuntu 14.04 with Python 2.7.6 . I am at quite a loss to explain why this works on one and not the other. If you have any guesses as to why the previous code does not work on the desktop, I would appreciate it. Is it a crypto problem with the signed request? I am just stumped and don't know how to proceed. Thank you.
After firing up wireshark and looking at the response, Amazon politely informs me that "Timezone Expired".
Ok, that was a bit embarrassing. See, my desktop is dual booting windows 8 (for games) and Ubuntu. I have been having a lot of trouble with the clock skewing all over the place when I boot from one os to another. So, genius, I decided to just set my timezone to Reykjavik, Iceland (UTC offset +0), disable internet time synching, and manually set my time to the local time (on both windows and ubuntu). That fixed my time skewing problems.
Amazon does not like this. It says that the timestamp has expired on the request I make. So, I re-enabled internet syncing and set my time zone to Los Angeles, USA. Everything works.