Subversion Repositories SmartDukaan

Rev

Rev 20315 | Blame | Compare with Previous | Last modification | View Log | RSS feed

from xml.dom.minidom import parseString
import re
import urllib
import hashlib
import hmac
import base64
from time import strftime, gmtime
from requests import request


class MWS(object):
    URI = "/"
    VERSION = "2009-01-01"
    NS = ''

    def __init__(self, access_key, secret_key, merchant_id,
                 domain='https://mws-eu.amazonservices.com', uri="", version=""):
        self.access_key = access_key
        self.secret_key = secret_key
        self.merchant_id = merchant_id
        self.domain = domain
        self.uri = uri or self.URI
        self.version = version or self.VERSION

    def make_request(self, extra_data, action,method="GET", **kwargs):

        params = {
            'AWSAccessKeyId': self.access_key,
            'SignatureVersion': '2',
            'Timestamp': self.get_timestamp(),
            'Version': self.version,
            'SignatureMethod': 'HmacSHA256',
            'Action': action
        }
        if action=='GetLowestOfferListingsForSKU':
            params['ExcludeMe']='true'
        if action =='GetLowestOfferListingsForASIN':
            params['ItemCondition'] = 'New'
        params.update(extra_data)
        request_description = '&'.join(['%s=%s' % (k, urllib.quote(params[k], safe='-_.~').encode('utf-8')) for k in sorted(params)])
        signature = self.calc_signature(method, request_description)
        url = '%s%s?%s&Signature=%s' % (self.domain, self.uri, request_description, urllib.quote(signature))
        #headers = {'User-Agent': 'AmazonJavascriptScratchpad/1.0 (Language=Python)'}
        #headers.update(kwargs.get('extra_headers', {}))
        response = request(method, url)
        if action=='GetLowestOfferListingsForSKU':
            return self.parse_competitor_pricing_response(response)
        elif action=='GetMyPriceForSKU':
            return self.parse_my_pricing_response(response)
        elif action=='GetProductCategoriesForSKU':
            return self.parse_product_category_for_sku(response)
        elif action=='GetMatchingProductForId':
            return self.parse_product_attributes(response)
        elif action=='GetLowestOfferListingsForASIN':
            return self.parse_lowest_pricing_asins(response)
        elif action == 'GetMatchingProduct':
            return self.parse_get_matching_product(response)
        else:
            raise
    
    def parse_get_matching_product(self, response):
        spString = re.sub('<\?.*\?>','',response.text)
        spString = "<dom>" + spString + "</dom>"
        dom = parseString(spString)
        asinStatuses = dom.getElementsByTagName('GetMatchingProductResult')
        asinMap = {}
        for asinStatus in asinStatuses:
            #print asinStatus.attributes.items()
            status = asinStatus.attributes.items()[0][1]
            asin = asinStatus.attributes.items()[1][1]
            asinMap[asin] = status
        return asinMap
    
    def parse_product_category_for_sku(self,response):
        browseNodes = []
        #node = "" 
        spString = re.sub('<\?.*\?>','',response.text)
        spString = "<dom>" + spString + "</dom>"
        dom = parseString(spString)
        selfTag = dom.getElementsByTagName('Self')
        for element in selfTag:
            temp = []
            browsingNodes = element.getElementsByTagName('ProductCategoryName')
            for browsingNode in browsingNodes:
                temp.append(browsingNode.firstChild.nodeValue)
            browseNodes.append(temp)
        return browseNodes
    
    def parse_product_attributes(self,response):
        spString = re.sub('<\?.*\?>','',response.text)
        spString = "<dom>" + spString + "</dom>"
        dom = parseString(spString)
        sku = dom.getElementsByTagName("GetMatchingProductForIdResult")[0].attributes.items()[2][1]
        dimensions = dom.getElementsByTagName("ns2:PackageDimensions")
        for dimension in dimensions:
            height = dimension.getElementsByTagName("ns2:Height")[0].firstChild.nodeValue #Inch
            length = dimension.getElementsByTagName("ns2:Length")[0].firstChild.nodeValue #Inch
            width = dimension.getElementsByTagName("ns2:Width")[0].firstChild.nodeValue #Inch
            weight = dimension.getElementsByTagName("ns2:Weight")[0].firstChild.nodeValue #Pounds
            return {'sku':sku,'length':length,'width':width,'height':height,'weight':weight}
    
    def parse_lowest_pricing_asins(self,response):
        #GetLowestOfferListingsForASINResult
        spString = re.sub('<\?.*\?>','',response.text)
        spString = "<dom>" + spString + "</dom>"
        dom = parseString(spString)
        asinOffers = dom.getElementsByTagName('GetLowestOfferListingsForASINResult')
        asinMap = {}
        for asinOffer in asinOffers:
            asin = asinOffer.attributes.items()[1][1]
            asinMap[asin] = 0.0
            for offer in asinOffer.getElementsByTagName('LowestOfferListing'):
                price =  offer.getElementsByTagName('Amount')[0].firstChild.nodeValue
                asinMap[asin] = float(price) 
                break
        return asinMap
        
        
    def parse_competitor_pricing_response(self,response):
        spString = re.sub('<\?.*\?>','',response.text)
        spString = "<dom>" + spString + "</dom>"
        dom = parseString(spString)
        skuOffers = dom.getElementsByTagName('GetLowestOfferListingsForSKUResult')
        offerMap = {}
        otherInfo = {}
        for skuOffer in skuOffers:
            status = skuOffer.attributes.items()[0][1]
            sku = skuOffer.attributes.items()[1][1]
            info = []
            for offer in skuOffer.getElementsByTagName('LowestOfferListing'):
                temp = {}
                try:
                    if len(info)==3:
                        break
                    amount = offer.getElementsByTagName('Amount')[0].firstChild.nodeValue
                    temp['sellingPrice'] = float(amount)
                    temp['promoPrice'] = float(amount)
                    temp['fulfillmentChannel'] = offer.getElementsByTagName('FulfillmentChannel')[0].firstChild.nodeValue
                    try:
                        temp['shippingTime'] = (offer.getElementsByTagName('Max')[0].firstChild.nodeValue).replace('days','')
                    except:
                        temp['shippingTime'] = '0-0'
                    try:
                        temp['rating'] = (offer.getElementsByTagName('SellerPositiveFeedbackRating')[0].firstChild.nodeValue)
                        if temp['rating'] == 'Just Launched':
                            temp['rating'] = '100'
                        else:
                            str_rating = temp['rating'].replace('-',' ').replace('%','')
                            a =  str_rating.split()
                            l = []
                            for x in a:
                                if x.isdigit():
                                    l.append(x)
                            temp['rating'] = l[0]
                    except:
                        temp['rating'] = '0'
                except:
                    pass
                temp['notOurSku'] = True
                info.append(temp)
                offerMap[sku]=info
        for skuOffer in skuOffers:
            sku = skuOffer.attributes.items()[1][1]
            temp = {}
            temp['lowestMfnIgnored']=0.0
            temp['isLowestMfnIgnored']=False
            temp['lowestFba']=0.0
            temp['isLowestFba']=False
            temp['lowestMfn']=0.0
            temp['isLowestMfn']=False
            for offer in skuOffer.getElementsByTagName('LowestOfferListing'):
                try:
                    fulfillmentChannel = offer.getElementsByTagName('FulfillmentChannel')[0].firstChild.nodeValue
                    amount = offer.getElementsByTagName('Amount')[0].firstChild.nodeValue
                    try:
                        rating = (offer.getElementsByTagName('SellerPositiveFeedbackRating')[0].firstChild.nodeValue)
                        if rating == 'Just Launched':
                            rating = 100
                        else:
                            str_rating = rating.replace('-',' ').replace('%','')
                            a =  str_rating.split()
                            l = []
                            for x in a:
                                if x.isdigit():
                                    l.append(x)
                            rating = int(l[0])
                    except:
                        rating = 0
                    if fulfillmentChannel=='Merchant' and not temp['isLowestMfnIgnored'] and not temp['isLowestMfn'] and rating < 60:
                        temp['lowestMfnIgnored'] = float(amount)
                        temp['isLowestMfnIgnored']=True
                    elif fulfillmentChannel=='Merchant' and not temp['isLowestMfn'] and rating > 60:
                        temp['lowestMfn'] = float(amount)
                        temp['isLowestMfn']=True
                    elif fulfillmentChannel=='Amazon' and not temp['isLowestFba']:
                        temp['lowestFba'] = float(amount)
                        temp['isLowestFba']=True
                    else:
                        pass
                except:
                    pass
                otherInfo[sku]=temp
        return offerMap, otherInfo
    
    def parse_my_pricing_response(self,response):
        spString = re.sub('<\?.*\?>','',response.text)
        spString = "<dom>" + spString + "</dom>"
        dom = parseString(spString)
        skuOffers = dom.getElementsByTagName('GetMyPriceForSKUResult')
        skuMap = {}
        for skuOffer in skuOffers:
            try:
                status = skuOffer.attributes.items()[0][1]
                sku = skuOffer.attributes.items()[1][1]
                asin = skuOffer.getElementsByTagName('ASIN')[0].firstChild.nodeValue
                skuMap[sku]={}
            except:
                continue
            for offer in skuOffer.getElementsByTagName('Offer'):
                offerSku = offer.getElementsByTagName('SellerSKU')[0].firstChild.nodeValue
                fcChannel =  offer.getElementsByTagName('FulfillmentChannel')[0].firstChild.nodeValue
                if not (offerSku==sku and fcChannel=='AMAZON'):
                    continue
                temp = {}
                try:
                    promoPrice = offer.getElementsByTagName('LandedPrice')[0].getElementsByTagName('Amount')[0].firstChild.nodeValue
                    regularPrice = offer.getElementsByTagName('RegularPrice')[0].getElementsByTagName('Amount')[0].firstChild.nodeValue
                    temp['sellingPrice'] = float(regularPrice)
                    temp['promoPrice'] = float(promoPrice)
                    if promoPrice == regularPrice:
                        temp['promotion'] = False
                    else:
                        temp['promotion'] = True
                    temp['status'] = status
                    temp['asin'] = asin
                    temp['notOurSku'] = False
                    temp['fulfillmentChannel'] ='AMAZON'
                    temp['shippingTime'] =  '0-0'
                    temp['rating'] = '0'
                except:
                    pass
                skuMap[sku]=temp     
        return skuMap    
        
        
    def calc_signature(self, method, request_description):
        sig_data = method + '\n' + self.domain.replace('https://', '').lower() + '\n' + self.uri + '\n' + request_description
        return base64.b64encode(hmac.new(str(self.secret_key), sig_data, hashlib.sha256).digest())

    def get_timestamp(self):
        return strftime("%Y-%m-%dT%H:%M:%SZ", gmtime())


class Products(MWS):

    URI = '/Products/2011-10-01'
    VERSION = '2011-10-01'
    NS = '{https://mws-eu.amazonservices.com/Products/2011-10-01}'
    
    
    def get_my_pricing_for_sku(self, marketplaceid, skus):

        data = dict(SellerId=self.merchant_id, MarketplaceId=marketplaceid)
        num=0
        for sku in skus:
            data['SellerSKUList.SellerSKU.%d' % (num + 1)] = sku
            num+=1
        return self.make_request(data,'GetMyPriceForSKU')
    

    def get_competitive_pricing_for_sku(self, marketplaceid, skus):
        data = dict(SellerId=self.merchant_id, MarketplaceId=marketplaceid)
        num=0
        for sku in skus:
            data['SellerSKUList.SellerSKU.%d' % (num + 1)] = sku
            num+=1
        return self.make_request(data,'GetLowestOfferListingsForSKU')
    
    def get_product_category_for_sku(self, marketplaceid, sku):
        data = dict(SellerId=self.merchant_id, MarketplaceId=marketplaceid)
        data['SellerSKU'] = sku
        return self.make_request(data,'GetProductCategoriesForSKU')
    
    def get_product_attributes_for_sku(self, marketplaceid, skus):
        data = dict(SellerId=self.merchant_id, MarketplaceId=marketplaceid)
        num=0
        for sku in skus:
            data['IdList.Id.%d' % (num + 1)] = sku
            num+=1
        data['IdType'] = 'ASIN'
        return self.make_request(data,'GetMatchingProductForId')
    
    def get_competitive_pricing_for_asin(self, marketplaceid, asins):
        data = dict(SellerId=self.merchant_id, MarketplaceId=marketplaceid)
        num=0
        for asin in asins:
            data['ASINList.ASIN.%d' % (num + 1)] = asin
            num+=1
        return self.make_request(data,'GetLowestOfferListingsForASIN')
    
    def get_matching_product(self, marketplaceid, asins):
        data = dict(SellerId=self.merchant_id, MarketplaceId=marketplaceid)
        num=0
        for asin in asins:
            data['ASINList.ASIN.%d' % (num + 1)] = asin
            num+=1
        return self.make_request(data,'GetMatchingProduct')
    
    
    
def main():
    p = Products("AKIAII3SGRXBJDPCHSGQ", "B92xTbNBTYygbGs98w01nFQUhbec1pNCkCsKVfpg", "AF6E3O0VE0X4D")
    print p.get_matching_product("A21TJRUUN4KGV", ["B016QBT87W","B0168L23VS"])

if __name__=='__main__':
    main()