Ejemplo n.º 1
0
    def test_get_items_UnrecognizedClient(self):
        host = "webservices.amazon.com"
        region = "us-east-1"
        default_api = DefaultApi(access_key="",
                                 secret_key="",
                                 host=host,
                                 region=region)

        get_items_request = GetItemsRequest(
            partner_tag="",
            partner_type=PartnerType.ASSOCIATES,
            marketplace="www.amazon.com",
            item_ids=[],
            resources=[],
        )
        try:
            response = default_api.get_items(get_items_request)
        except ApiException as exception:
            self.assertEquals(exception.status, 401, "Status Check")
            self.assertEquals(
                (json.loads(exception.body)["Errors"])[0]["Code"],
                UNRECOGNIZED_CLIENT,
                "Error Code Check",
            )
            self.assertEquals(
                (json.loads(exception.body)["Errors"])[0]["Message"],
                "The Access Key ID or security token included in the request is invalid.",
                "Message Check",
            )
Ejemplo n.º 2
0
    def test_get_items_IncompleteSignature(self):
        host = "webservices.amazon.com"
        region = "us-east-1"
        default_api = DefaultApi(
            access_key=DUMMY_ACCESS_KEY,
            secret_key=DUMMY_SECRET_KEY,
            host=host,
            region=region,
        )

        get_items_request = GetItemsRequest(
            partner_tag="",
            partner_type=PartnerType.ASSOCIATES,
            marketplace="www.amazon.com",
            item_ids=[],
            resources=[],
        )
        try:
            response = default_api.get_items(get_items_request)
        except ApiException as exception:
            self.assertEquals(exception.status, 400, "Status Check")
            self.assertEquals(
                (json.loads(exception.body)["Errors"])[0]["Code"],
                INCOMPLETE_SIGNATURE,
                "Error Code Check",
            )
            self.assertEquals(
                (json.loads(exception.body)["Errors"])[0]["Message"],
                "The request signature did not include all of the required components. If you are using an AWS SDK, requests are signed for you automatically; otherwise, go to https://webservices.amazon.com/paapi5/documentation/sending-request.html#signing.",
                "Message Check",
            )
Ejemplo n.º 3
0
    def test_get_items_aync_UnrecognizedClient(self):
        host = "webservices.amazon.com"
        region = "us-east-1"
        connetion_pool_max_size = 12
        configuration = Configuration()
        configuration.__init__(connetion_pool_max_size)
        api_client = ApiClient(
            access_key="",
            secret_key="",
            host=host,
            region=region,
            configuration=configuration,
        )
        default_api = DefaultApi(
            access_key="",
            secret_key="",
            host=host,
            region=region,
            api_client=api_client,
        )

        get_items_request = GetItemsRequest(
            partner_tag="",
            partner_type=PartnerType.ASSOCIATES,
            marketplace="www.amazon.com",
            item_ids=[],
            resources=[],
        )
        try:
            thread = default_api.get_items(get_items_request, async_req=True)
            api_client.__del__()
            response = thread.get()
        except ApiException as exception:
            self.assertEquals(exception.status, 401, "Status Check")
            self.assertEquals(
                (json.loads(exception.body)["Errors"])[0]["Code"],
                UNRECOGNIZED_CLIENT,
                "Error Code Check",
            )
            self.assertEquals(
                (json.loads(exception.body)["Errors"])[0]["Message"],
                "The Access Key ID or security token included in the request is invalid.",
                "Message Check",
            )
Ejemplo n.º 4
0
class AmazonAPI:
    """Amazon Product Advertising API 5.0 wrapper for Python"""
    RESOURCES = {
        'all': [
            getattr(GetItemsResource, v) for v in
            # Hack: pulls all resource consts from GetItemsResource
            vars(GetItemsResource).keys() if v.isupper()
        ],
        'import': [
            GetItemsResource.IMAGES_PRIMARY_LARGE,
            GetItemsResource.ITEMINFO_BYLINEINFO,
            GetItemsResource.ITEMINFO_CONTENTINFO,
            GetItemsResource.ITEMINFO_MANUFACTUREINFO,
            GetItemsResource.ITEMINFO_PRODUCTINFO,
            GetItemsResource.ITEMINFO_TITLE,
            GetItemsResource.ITEMINFO_CLASSIFICATIONS,
            GetItemsResource.OFFERS_LISTINGS_PRICE,
        ],
        'prices': [GetItemsResource.OFFERS_LISTINGS_PRICE]
    }

    def __init__(self,
                 key,
                 secret,
                 tag,
                 host='webservices.amazon.com',
                 region='us-east-1',
                 throttling=0.9):
        """
        Creates an instance containing your API credentials.

        :param key (string): affiliate key
        :param secret (string): affiliate secret
        :param tag (string): affiliate string
        :param host (string): which server to query
        :param region (string): which regional host to query
        :param throttling (float): Reduce this value to wait longer
          between API calls.
        :return: Amazon metadata for one product
        :rtype: dict
        """
        self.tag = tag
        self.throttling = throttling
        self.last_query_time = time.time()

        self.api = DefaultApi(access_key=key,
                              secret_key=secret,
                              host=host,
                              region=region)

    def get_product(self, asin, serialize=False, **kwargs):
        products = self.get_products([asin], **kwargs)
        if products:
            return next(
                self.serialize(p) if serialize else p for p in products)

    def get_products(self,
                     asins,
                     serialize=False,
                     marketplace='www.amazon.com',
                     resources=None,
                     **kwargs):
        """
        :param asins (string): One or more ItemIds like ASIN that
        uniquely identify an item or product URL. (Max 10) Seperated
        by comma or as a list.
        """
        # Wait before doing the request
        wait_time = 1 / self.throttling - (time.time() - self.last_query_time)
        if wait_time > 0:
            time.sleep(wait_time)
        self.last_query_time = time.time()

        item_ids = asins if type(asins) is list else [asins]
        _resources = self.RESOURCES[resources or 'import']
        try:
            request = GetItemsRequest(partner_tag=self.tag,
                                      partner_type=PartnerType.ASSOCIATES,
                                      marketplace=marketplace,
                                      item_ids=item_ids,
                                      resources=_resources,
                                      **kwargs)
        except ApiException:
            logger.error("Amazon fetch failed for: %s" % ', '.join(item_ids),
                         exc_info=True)
            return None
        response = self.api.get_items(request)
        products = [p for p in response.items_result.items
                    if p] if response.items_result else []
        return (products
                if not serialize else [self.serialize(p) for p in products])

    @staticmethod
    def serialize(product):
        """Takes a full Amazon product Advertising API returned AmazonProduct
        with multiple ResponseGroups, and extracts the data we are
        interested in.

        :param AmazonAPI product:
        :return: Amazon metadata for one product
        :rtype: dict

        {
          'price': '$54.06',
          'price_amt': 5406,
          'physical_format': 'hardcover',
          'authors': [{'name': 'Guterson, David'}],
          'publish_date': 'Jan 21, 2020',
          #'dimensions': {
          #  'width': [1.7, 'Inches'],
          #  'length': [8.5, 'Inches'],
          #  'weight': [5.4, 'Pounds'],
          #  'height': [10.875, 'Inches']
          # },
          'publishers': ['Victory Belt Publishing'],
          'source_records': ['amazon:1628603976'],
          'title': 'Boundless: Upgrade Your Brain, Optimize Your Body & Defy Aging',
          'url': 'https://www.amazon.com/dp/1628603976/?tag=internetarchi-20',
          'number_of_pages': 640,
          'cover': 'https://m.media-amazon.com/images/I/51IT9MV3KqL._AC_.jpg',
          'languages': ['English']
          'edition_num': '1'
        }

        """
        if not product:
            return {}  # no match?

        item_info = getattr(product, 'item_info')
        images = getattr(product, 'images')
        edition_info = item_info and getattr(item_info, 'content_info')
        attribution = item_info and getattr(item_info, 'by_line_info')
        price = (getattr(product, 'offers') and product.offers.listings
                 and product.offers.listings[0].price)
        brand = (attribution and getattr(attribution, 'brand')
                 and getattr(attribution.brand, 'display_value'))
        manufacturer = (item_info and getattr(item_info, 'by_line_info')
                        and getattr(item_info.by_line_info, 'manufacturer')
                        and item_info.by_line_info.manufacturer.display_value)
        product_group = (item_info and getattr(
            item_info,
            'classifications',
        ) and getattr(item_info.classifications, 'product_group') and
                         item_info.classifications.product_group.display_value)
        try:
            publish_date = edition_info and isoparser.parse(
                edition_info.publication_date.display_value).strftime(
                    '%b %d, %Y')
        except Exception:
            logger.exception("serialize({})".format(product))
            publish_date = None

        book = {
            'url':
            "https://www.amazon.com/dp/%s/?tag=%s" %
            (product.asin, h.affiliate_id('amazon')),
            'source_records': ['amazon:%s' % product.asin],
            'isbn_10': [product.asin],
            'isbn_13': [isbn_10_to_isbn_13(product.asin)],
            'price':
            price and price.display_amount,
            'price_amt':
            price and price.amount and int(100 * price.amount),
            'title': (item_info and item_info.title
                      and getattr(item_info.title, 'display_value')),
            'cover': (images and images.primary and images.primary.large
                      and images.primary.large.url),
            'authors':
            attribution and [{
                'name': contrib.name
            } for contrib in attribution.contributors],
            'publishers':
            list(set(p for p in (brand, manufacturer) if p)),
            'number_of_pages': (edition_info and edition_info.pages_count
                                and edition_info.pages_count.display_value),
            'edition_num': (edition_info and edition_info.edition
                            and edition_info.edition.display_value),
            'publish_date':
            publish_date,
            'product_group':
            product_group,
            'physical_format': (item_info and item_info.classifications
                                and getattr(item_info.classifications.binding,
                                            'display_value', '').lower()),
        }
        return book
Ejemplo n.º 5
0
class AmazonAPI:
    """Creates an instance containing your API credentials.

    Args:
        key (str): Your API key.
        secret (str): Your API secret.
        tag (str): The tag you want to use for the URL.
        country (str): Country code. Use one of the following:
            AU, BR, CA, FR, DE, IN, IT, JP, MX, ES, TR, AE, UK, US.
        throttling (float, optional): Reduce this value to wait longer
            between API calls.
    """
    def __init__(self,
                 key: str,
                 secret: str,
                 tag: str,
                 country: str,
                 throttling=0.8):
        self.key = key
        self.secret = secret
        self.tag = tag
        if 1 >= throttling > 0:
            self.throttling = throttling
        elif throttling <= 0:
            raise AmazonException('ValueError',
                                  'Throttling should be greater than 0')
        elif throttling > 1:
            raise AmazonException('ValueError',
                                  'Throttling should be 1 or less')
        self.country = country
        try:
            self.host = 'webservices.amazon.' + DOMAINS[country]
            self.region = REGIONS[country]
            self.marketplace = 'www.amazon.' + DOMAINS[country]
        except KeyError:
            raise AmazonException('KeyError', 'Invalid country code')
        self.last_query_time = time.time()
        self.api = DefaultApi(access_key=self.key,
                              secret_key=self.secret,
                              host=self.host,
                              region=self.region)

    def get_products(self,
                     product_ids: [str, list],
                     condition='Any',
                     merchant='All',
                     async_req=False):
        """Find product information for multiple products on Amazon.

        Args:
            product_ids (str|list): One or more item IDs like ASIN or product URL.
                Use a string separated by comma or as a list.
            condition (str, optional): Specify the product condition.
                Allowed values: Any, Collectible, New, Refurbished, Used.
                Defaults to Any.
            merchant (str, optional): Filters search results to return items
                having at least one offer sold by target merchant. Allowed values:
                All, Amazon. Defaults to All.
            async_req (bool, optional): Specify if a thread should be created to
                run the request. Defaults to False.

        Returns:
            list of instances: A list containing 1 instance for each product
                or None if no results.
        """

        # Clean up input data and remove 10 items limit from Amazon API
        if isinstance(product_ids, str):
            product_ids = [x.strip() for x in product_ids.split(',')]
        elif not isinstance(product_ids, list):
            raise AmazonException(
                'TypeError', 'Arg product_ids should be a list or string')
        asin_full_list = list(set([get_asin(x) for x in product_ids]))
        asin_full_list = list(chunks(asin_full_list, 10))

        results = []
        for asin_list in asin_full_list:
            try:
                request = GetItemsRequest(partner_tag=self.tag,
                                          partner_type=PartnerType.ASSOCIATES,
                                          marketplace=self.marketplace,
                                          merchant=merchant,
                                          condition=CONDITION[condition],
                                          item_ids=asin_list,
                                          resources=PRODUCT_RESOURCES)
            except KeyError:
                raise AmazonException('KeyError', 'Invalid condition value')
            except Exception as e:
                raise AmazonException('GetItemsError', e)

            for x in range(3):
                try:
                    # Wait before doing the request
                    wait_time = 1 / self.throttling - (time.time() -
                                                       self.last_query_time)
                    if wait_time > 0:
                        time.sleep(wait_time)
                    self.last_query_time = time.time()

                    # Send the request and create results
                    if async_req:
                        thread = self.api.get_items(request, async_req=True)
                        response = thread.get()
                    else:
                        response = self.api.get_items(request)
                    break
                except ApiException as e:
                    if x == 2:
                        raise AmazonException('ApiException', e)
            try:
                if response.items_result is not None:
                    if len(response.items_result.items) > 0:
                        for item in response.items_result.items:
                            results.append(parse_product(item))
            except Exception as e:
                raise AmazonException('ResponseError', e)

        if results:
            return results
        else:
            return None

    def get_product(self,
                    product_id: str,
                    condition='Any',
                    merchant='All',
                    async_req=False):
        """Find product information for a specific product on Amazon.

        Args:
            product_id (str): One item ID like ASIN or product URL.
            condition (str, optional): Specify the product condition.
                Allowed values: Any, Collectible, New, Refurbished, Used.
                Defaults to Any.
            merchant (str, optional): Filters search results to return items
                having at least one offer sold by target merchant. Allowed values:
                All, Amazon. Defaults to All.
            async_req (bool, optional): Specify if a thread should be created to
                run the request. Defaults to False.

        Returns:
            instance: An instance containing all the available information
                for the product or None if no results.
        """
        if isinstance(product_id, list):
            raise AmazonException('TypeError',
                                  'Arg product_id should be string')
        if isinstance(product_id, str):
            check_product_id = product_id.split(',')
            if len(check_product_id) > 1:
                raise AmazonException(
                    'ValueError', 'Only 1 product ID is allowed, use '
                    'get_products for multiple requests')
        return self.get_products(product_id,
                                 condition=condition,
                                 merchant=merchant,
                                 async_req=async_req)[0]

    def search_products(self,
                        item_count=10,
                        item_page=1,
                        items_per_page=10,
                        keywords=None,
                        actor=None,
                        artist=None,
                        author=None,
                        brand=None,
                        title=None,
                        availability='Available',
                        browse_node=None,
                        condition='Any',
                        delivery=None,
                        max_price=None,
                        min_price=None,
                        min_rating=None,
                        min_discount=None,
                        merchant='All',
                        search_index='All',
                        sort_by=None,
                        async_req=False):
        """Search products on Amazon using different parameters. At least one of the
        following parameters should be used: keywords, actor, artist, author, brand,
        title.

        Args:
            item_count (int, optional): The total number of products to get. Should be between
                1 and 100. Defaults to 10.
            item_page (int, optional): The page where the results start from. Should be between
                1 and 10. Defaults to 1.
            items_per_page (int, optional): Products on each page. Should be between
                1 and 10. Defaults to 10.
            keywords (str, optional): A word or phrase that describes an item.
            actor (str, optional): Actor name associated with the item.
            artist (str, optional): Artist name associated with the item.
            author (str, optional): Author name associated with the item.
            brand (str, optional): Brand name associated with the item.
            title (str, optional): Title associated with the item.
            availability (str, optional): Filters available items on Amazon. Allowed values:
            Available, IncludeOutOfStock. Defaults to Available.
            browse_node (str, optional): A unique ID assigned by Amazon that
                identifies a product category or subcategory.
            condition (str, optional): The condition parameter filters offers by
                condition type. Allowed values: Any, Collectible, New, Refurbished, Used.
                Defaults to Any.
            delivery (list, optional): The delivery flag filters items which
                satisfy a certain delivery program promoted by the specific
                Amazon Marketplace. Allowed values: AmazonGlobal, FreeShipping,
                FulfilledByAmazon, Prime.
            max_price (int, optional): Filters search results to items with at
                least one offer price below the specified value.
            min_price (int, optional): Filters search results to items with at
                least one offer price above the specified value.
            min_rating (int, optional): Filters search results to items with
                customer review ratings above specified value.
            min_discount (int, optional): Filters search results to items with
                at least one offer having saving percentage above the specified
                value.
            merchant (str, optional): Filters search results to return items
                having at least one offer sold by target merchant. Allowed values:
                All, Amazon. Defaults to All.
            search_index (str, optional): Indicates the product category to
                search. Defaults to All.
            sort_by (str, optional): The way in which items in the response
                are sorted. Allowed values: AvgCustomerReviews, Featured,
                NewestArrivals, Price:HighToLow, Price:LowToHigh, Relevance.
            async_req (bool, optional): Specify if a thread should be created to
                run the request. Defaults to False.

        Returns:
            list of instances: A list containing 1 instance for each product
                or None if no results.
        """
        if items_per_page > 10 or items_per_page < 1:
            raise AmazonException(
                'ValueError', 'Arg items_per_page should be between 1 and 10')
        if item_count > 100 or item_count < 1:
            raise AmazonException(
                'ValueError', 'Arg item_count should be between 1 and 100')
        if item_page > 10 or item_page < 1:
            raise AmazonException('ValueError',
                                  'Arg item_page should be between 1 and 10')
        if not keywords and not actor and not artist and not author and not brand and not title:
            raise AmazonException(
                'ValueError', 'At least one of the following args must be '
                'provided: keywords, actor, artist, author, brand,'
                'title')
        results = []
        while len(results) < item_count:
            try:
                request = SearchItemsRequest(
                    partner_tag=self.tag,
                    partner_type=PartnerType.ASSOCIATES,
                    actor=actor,
                    artist=artist,
                    author=author,
                    availability=availability,
                    brand=brand,
                    browse_node_id=browse_node,
                    condition=CONDITION[condition],
                    delivery_flags=delivery,
                    item_count=items_per_page,
                    item_page=item_page,
                    keywords=keywords,
                    max_price=max_price,
                    merchant=merchant,
                    min_price=min_price,
                    min_reviews_rating=min_rating,
                    min_saving_percent=min_discount,
                    offer_count=1,
                    resources=SEARCH_RESOURCES,
                    search_index=search_index,
                    sort_by=sort_by,
                    title=title)
            except KeyError:
                raise AmazonException('KeyError', 'Invalid condition value')
            except Exception as e:
                raise AmazonException('SearchItemsError', e)

            for x in range(3):
                try:
                    # Wait before doing the request
                    wait_time = 1 / self.throttling - (time.time() -
                                                       self.last_query_time)
                    if wait_time > 0:
                        time.sleep(wait_time)
                    self.last_query_time = time.time()

                    # Send the request and create results
                    if async_req:
                        thread = self.api.search_items(request, async_req=True)
                        response = thread.get()
                    else:
                        response = self.api.search_items(request)
                    break
                except ApiException as e:
                    if x == 2:
                        raise AmazonException('ApiException', e)
            try:
                if response.search_result is not None:
                    for item in response.search_result.items:
                        results.append(parse_product(item))
                        if len(results) >= item_count:
                            break
                else:
                    break
                if response.errors is not None:
                    raise AmazonException(response.errors[0].code,
                                          response.errors[0].message)
            except Exception as e:
                raise AmazonException('ResponseError', e)
            item_page += 1
            if item_page > 10:
                break

        if results:
            return results
        else:
            return None

    def get_variations(self,
                       asin,
                       item_count=10,
                       item_page=1,
                       items_per_page=10,
                       condition='Any',
                       merchant='All',
                       async_req=False):
        """Returns a set of items that are the same product, but differ according to a
        consistent theme, for example size and color.

        Args:
            asin (str): One item ID like ASIN or product URL.
            item_count (int, optional): The total number of products to get. Should be between
                1 and 100. Defaults to 10.
            item_page (int, optional): The page where the results start from. Should be between
                1 and 10. Defaults to 1.
            items_per_page (int, optional): Products on each page. Should be between
                1 and 10. Defaults to 10.
            condition (str, optional): The condition parameter filters offers by
                condition type. Allowed values: Any, Collectible, New, Refurbished, Used.
                Defaults to Any.
            merchant (str, optional): Filters search results to return items
                having at least one offer sold by target merchant. Allowed values:
                All, Amazon. Defaults to All.
            async_req (bool, optional): Specify if a thread should be created to
                run the request. Defaults to False.

        Returns:
            list of instances: A list containing 1 instance for each product
                or None if no results.
        """
        if items_per_page > 10 or items_per_page < 1:
            raise AmazonException(
                'ValueError', 'Arg items_per_page should be between 1 and 10')
        if item_count > 100 or item_count < 1:
            raise AmazonException(
                'ValueError', 'Arg item_count should be between 1 and 100')
        if item_page > 10 or item_page < 1:
            raise AmazonException('ValueError',
                                  'Arg item_page should be between 1 and 10')

        results = []
        while len(results) < item_count:
            try:
                request = GetVariationsRequest(
                    partner_tag=self.tag,
                    partner_type=PartnerType.ASSOCIATES,
                    marketplace=self.marketplace,
                    asin=get_asin(asin),
                    condition=CONDITION[condition],
                    merchant=merchant,
                    offer_count=1,
                    variation_count=items_per_page,
                    variation_page=item_page,
                    resources=VARIATION_RESOURCES)
            except KeyError:
                raise AmazonException('KeyError', 'Invalid condition value')
            except Exception as e:
                raise AmazonException('GetVariationsError', e)

            for x in range(3):
                try:
                    # Wait before doing the request
                    wait_time = 1 / self.throttling - (time.time() -
                                                       self.last_query_time)
                    if wait_time > 0:
                        time.sleep(wait_time)
                    self.last_query_time = time.time()

                    # Send the request and create results
                    if async_req:
                        thread = self.api.get_variations(request,
                                                         async_req=True)
                        response = thread.get()
                    else:
                        response = self.api.get_variations(request)
                    break
                except ApiException as e:
                    if x == 2:
                        raise AmazonException('ApiException', e)
            try:
                if response.variations_result is not None:
                    for item in response.variations_result.items:
                        results.append(parse_product(item))
                        if len(results) >= item_count:
                            break
                else:
                    break
                if response.errors is not None:
                    raise AmazonException(response.errors[0].code,
                                          response.errors[0].message)
            except Exception as e:
                raise AmazonException('ResponseError', e)
            item_page += 1
            if item_page > 10:
                break

        if results:
            return results
        else:
            return None
Ejemplo n.º 6
0
class MBAProducts(object):
    '''Class to access Amazon Product API
    '''
    def __init__(self, path_to_credentials_csv, partner_tag, marketplace="de"):
        self.cred_df = pd.read_csv(path_to_credentials_csv)
        self.access_key = self.cred_df["Access Key"].iloc[0]
        self.secret_key = self.cred_df["Secret Key"].iloc[0]
        self.partner_tag = partner_tag
        self.marketplace = marketplace

        if self.marketplace == "de":
            self.host = "webservices.amazon.de"
            self.region = "eu-west-1"
        elif self.marketplace == "com":
            self.host = "webservices.amazon.com"
            self.region = "us-east-1"
        else:
            raise NotImplementedError(
                f"Marketplace {self.marketplace} not definded")

        self.api = DefaultApi(access_key=self.access_key,
                              secret_key=self.secret_key,
                              host=self.host,
                              region=self.region)

        # self.product_resources_to_get = [RESOURCE_TITLE, RESOURCE_BRAND, RESOURCE_BRAND_URL, RESOURCE_PRICE, RESOURCE_PRICE_CURRENCY,
        #  RESOURCE_BSR, RESOURCE_BSR_CATEGORY, RESOURCE_FIT_TYPES, RESOURCE_COLOR_NAMES, RESOURCE_LISTINGS, RESOURCE_PRODUCT_TYPE,
        #  RESOURCE_DESCRIPTION, RESOURCE_UPLOAD_DATE, RESOURCE_REVIEW_SCORE, RESOURCE_REVIEW_COUNT, RESOURCE_IMAGE_URLS,
        #  RESOURCE_AFFILIATE_URL, RESOURCE_ASIN, RESOURCE_BSR_NODES, RESOURCE_BSR_NODES_CATEGORIES]

        self.product_resources_to_get = [
            RESOURCE_TITLE, RESOURCE_BRAND, RESOURCE_PRICE,
            RESOURCE_PRICE_CURRENCY, RESOURCE_BSR, RESOURCE_BSR_CATEGORY,
            RESOURCE_LISTINGS, RESOURCE_IMAGE_URLS, RESOURCE_AFFILIATE_URL,
            RESOURCE_ASIN, RESOURCE_BSR_NODES, RESOURCE_BSR_NODES_CATEGORIES
        ]

        self.set_items_resources()

    def set_items_resources(self):
        """ Choose resources you want from GetItemsResource enum """
        """ For more details, refer: https://webservices.amazon.com/paapi5/documentation/get-items.html#resources-parameter """

        # set all item resources for PAAPI
        self.items_resources = []
        if RESOURCE_TITLE in self.product_resources_to_get:
            self.items_resources.append(GetItemsResource.ITEMINFO_TITLE)
        if any(resource in self.product_resources_to_get
               for resource in [RESOURCE_PRICE_CURRENCY, RESOURCE_PRICE]):
            self.items_resources.append(GetItemsResource.OFFERS_LISTINGS_PRICE)
        if any(resource in self.product_resources_to_get
               for resource in [RESOURCE_REVIEW_COUNT, RESOURCE_REVIEW_SCORE]):
            self.items_resources.append(GetItemsResource.CUSTOMERREVIEWS_COUNT)
            self.items_resources.append(
                GetItemsResource.ITEMINFO_CONTENTRATING)
        if any(resource in self.product_resources_to_get
               for resource in [RESOURCE_BSR, RESOURCE_BSR_CATEGORY]):
            self.items_resources.append(
                GetItemsResource.BROWSENODEINFO_BROWSENODES_SALESRANK)
            self.items_resources.append(
                GetItemsResource.BROWSENODEINFO_WEBSITESALESRANK)
        if RESOURCE_IMAGE_URLS in self.product_resources_to_get:
            self.items_resources.append(GetItemsResource.IMAGES_PRIMARY_LARGE)
            self.items_resources.append(GetItemsResource.IMAGES_PRIMARY_MEDIUM)
            self.items_resources.append(GetItemsResource.IMAGES_PRIMARY_SMALL)
        if RESOURCE_LISTINGS in self.product_resources_to_get:
            self.items_resources.append(GetItemsResource.ITEMINFO_FEATURES)
        if RESOURCE_UPLOAD_DATE in self.product_resources_to_get:
            self.items_resources.append(GetItemsResource.ITEMINFO_CONTENTINFO)
        if any(resource in self.product_resources_to_get
               for resource in [RESOURCE_BRAND, RESOURCE_BRAND_URL]):
            self.items_resources.append(GetItemsResource.ITEMINFO_BYLINEINFO)

        self.items_resources.append(GetItemsResource.ITEMINFO_PRODUCTINFO)
        #self.items_resources.append(GetItemsResource.ITEMINFO_MANUFACTUREINFO)

    def get_items_resources(self):
        return self.items_resources

    def extract_resource(self, resource_name, res_dict):
        try:
            if resource_name == RESOURCE_BRAND:
                return res_dict.item_info.by_line_info.brand.display_value
            if resource_name == RESOURCE_ASIN:
                return res_dict.asin
            elif resource_name == RESOURCE_BSR:
                return res_dict.browse_node_info.website_sales_rank.sales_rank
            elif resource_name == RESOURCE_BSR_CATEGORY:
                return res_dict.browse_node_info.website_sales_rank.context_free_name
            elif resource_name == RESOURCE_BSR_NODES:
                return [
                    v.sales_rank
                    for v in res_dict.browse_node_info.browse_nodes
                ]
            elif resource_name == RESOURCE_BSR_NODES_CATEGORIES:
                return [
                    v.context_free_name
                    for v in res_dict.browse_node_info.browse_nodes
                ]
            # elif resource_name == RESOURCE_COLOR_NAMES:
            #     pass
            # elif resource_name == RESOURCE_DESCRIPTION:
            #     pass
            # elif resource_name == RESOURCE_FIT_TYPES:
            #     pass
            elif resource_name == RESOURCE_IMAGE_URLS:
                return res_dict.images.primary.large.url
            elif resource_name == RESOURCE_LISTINGS:
                return res_dict.item_info.features.display_values
            elif resource_name == RESOURCE_PRICE:
                return res_dict.offers.listings[0].price.amount
            elif resource_name == RESOURCE_PRICE_CURRENCY:
                return res_dict.offers.listings[0].price.currency
            # elif resource_name == RESOURCE_REVIEW_COUNT:
            #     pass
            # elif resource_name == RESOURCE_REVIEW_SCORE:
            #     pass
            elif resource_name == RESOURCE_UPLOAD_DATE:
                return res_dict.item_info.content_info.publication_date.display_value
            elif resource_name == RESOURCE_TITLE:
                return res_dict.item_info.title.display_value
            #elif resource_name == RESOURCE_PRODUCT_TYPE:
            #return res_dict.browse_node_info.browse_nodes.large.url
            elif resource_name == RESOURCE_AFFILIATE_URL:
                return res_dict.detail_page_url
            else:
                print(
                    f"Resource {resource_name} is not defined to extract data from response"
                )
                return None
        except Exception as e:
            #print(f"Something went wrong while trying to get data of resource {resource_name}", str(e))
            return None

    def response2MWData(self, response_dict):
        mw_data = []
        for asin, res_dict in response_dict.items():
            mw_data_item = {}
            for resource_name in self.product_resources_to_get:
                mw_data_item.update({
                    resource_name:
                    self.extract_resource(resource_name, res_dict)
                })
            mw_data.append(mw_data_item)
        return mw_data

    def get_mw_data(self, asin_list):
        mw_data = []
        try:
            get_items_request = GetItemsRequest(
                partner_tag=self.partner_tag,
                partner_type=PartnerType.ASSOCIATES,
                marketplace=f"www.amazon.{self.marketplace}",
                condition=Condition.NEW,
                item_ids=asin_list,
                resources=self.get_items_resources(),
            )
        except ValueError as exception:
            print("Error in forming GetItemsRequest: ", exception)
            return mw_data

        try:
            """ Sending request """
            response = self.api.get_items(get_items_request)
            #print("API called Successfully")
            if response.errors is not None:
                try:
                    #print("Found errors/ ASINS have takedows")
                    for error in response.errors:
                        asin = error.message.split(
                            "ItemId")[1:2][0].strip().split(" ")[0]
                        mw_data_takedown = {
                            RESOURCE_ASIN: asin,
                            RESOURCE_BSR: 404,
                            RESOURCE_BSR_CATEGORY: "404",
                            RESOURCE_BSR_NODES: [404],
                            RESOURCE_BSR_NODES_CATEGORIES: ["404"],
                            RESOURCE_PRICE: 404.0,
                            RESOURCE_PRICE_CURRENCY: "404"
                        }
                        mw_data.append(mw_data_takedown)
                except Exception as e:
                    print("Could not append mw_data with takedown asins",
                          str(e))
            """ Parse response """
            if response.items_result is not None:
                response_dict = parse_response(response.items_result.items)
                mw_data.extend(self.response2MWData(response_dict))
                return mw_data
            else:
                print("Could not get item result of api response")
                return mw_data

        except ApiException as exception:
            print("Error calling PA-API 5.0!")
            print("Status code:", exception.status)
            print("Errors :", exception.body)
            print("Request ID:", exception.headers["x-amzn-RequestId"])
            return mw_data
        except Exception as exception:
            print("Exception :", exception)
            return mw_data
Ejemplo n.º 7
0
class AmazonAPI:
    """
    Creates an instance containing your API credentials.

    params:
        *access_key (string)*
            Your API key
        *secret_key (string)*
            Your API secret
        *partner_tag (string)*
            The tag you want to use for the URL
        *country (string)*
            Country code
        *throttling (float, optional)*
            Reduce this value to wait longer between API calls
        *CacheReader (function)*
            Write a function to read the stored responses from previous api calls
        *CacheWriter (function)*
            Write a function to save the responses returned by amazon api calls
    
    
    """
    def __init__(self, access_key, secret_key, partner_tag, country='US', throttling=0.9, CacheReader=None, CacheWriter=None):
        """
            init AmazonApi. It is necessary to specify *access_key, secret_key, partner_tag, country* parameters
            By default the throttling parameter is set to 0.9. Increse or descrease this number to manage the time among different calls
            
            params:
                *access_key (string)*
                    amazon key of AWS account
                *secret_key (string)*
                    amazon secret of AWS account
                *partner_tag*
                    tag of the service Amazon Product Advertising account
                *country (string)*
                    possible values are defined in `amazon.constant.REGIONS`
                *throttling (float)*
                    value in the range (0,1] to wait among calls
                *CacheReader (function)*
                    function to read from cache 
                *CacheWriter (function)*
                    function to write results into the cache 

        """
        self.access_key = access_key
        self.secret_key = secret_key
        self.partner_tag = partner_tag
        self.throttling = throttling
        self.country = country
        self.host = 'webservices.amazon.' + DOMAINS[country]
        self.region = REGIONS[country]
        self.marketplace = 'www.amazon.' + DOMAINS[country]
        self.last_query_time = time.time()
        self.CacheReader = CacheReader
        self.CacheWriter = CacheWriter

        self.default_api = DefaultApi(
            access_key=self.access_key, secret_key=self.secret_key, host=self.host, region=self.region
        )
        

    def _cache_url(self, query):
        """
            return a url used to identify the call and retrieve it from the cache if CacheReader and CacheWriter are set.
        """
        return self.host + "?" + _quote_query(query)



    
    def search_items(self, actor=None, artist=None,author=None, availability=None, brand=None, browse_node_id=None, condition=None, currency_of_preference=None, delivery_flags=None, item_count=10,item_page=1, keywords=None, languages_of_preference=None, max_price=None, merchant="All", min_price=None,  min_reviews_rating=None, min_saving_percent=None, offer_count=1, search_index="All", sort_by= None,  title=None,  http_info=False, async_req=False, search_items_resource=SEARCH_RESOURCES):
        """ 
        Search products based on keywords
        Choose resources you want from SEARCH_RESOURCES enum 
        For more details, refer: https://webservices.amazon.com/paapi5/documentation/search-items.html#resources-parameter 

        args:
            *actor (string)*
                actor to search products
            *artist (string)*
                artist to search products
            *author (string)*
                author to search products
            *availability (string)*
                availability to search products. Admitted values: "Available", "IncludeOutOfStock"
            *brand* (string, optional)*
                filter the products based on the brand
            *browse_node_id (string)*
                search products into a specific browse node
            *condition* (enum, optional)*
                filter the products based on the condition
            *currency_of_preference (string)*
                Currency of preference in which the prices information should be returned in response. By default the prices are returned in the default currency of the marketplace. Expected currency code format is the ISO 4217 currency code (i.e. USD, EUR etc.)
            *delivery_flags (list of string)*
                The delivery flag filters items which satisfy a certain delivery program promoted by the specific Amazon Marketplace. For example, Prime DeliveryFlag will return items having at least one offer which is Prime Eligible.
            *item_count (integer)*
                number of products returned. Values in the range [1,10]. Default 10
            *item_page (integer)*
                can be used to fetch the specific set/page of items to be returned from the available Search Results. The number of items returned in a page is determined by the item_count parameter. For e.g. if the third set of 5 items (i.e. items numbered 11 to 15) are desired for a search request, you may specify
            *keywords (string)*
                keywords to search products
            *languages_of_preference (list of string)*
                Languages in order of preference in which the item information should be returned in response. By default the item information is returned in the default language of the marketplace.
            *max_price (positive integers)*
                Filters search results to items with at least one offer price below the specified value. Prices appear in lowest currency denomination. For example, in US marketplace, 3241 is $31.41.
            *merchant (string)*
                Filters search results to return items having at least one offer sold by target merchant. By default the value "All" is passed. 
            *min_price (positive integers)*
                Filters search results to items with at least one offer price above the specified value. Prices appear in lowest currency denomination. For example, in US marketplace, 3241 is $32.41.
            *min_reviews_rating (positive integers less than 5)*
                Filters search results to items with customer review ratings above specified value.
            *min_saving_percent (integers less than 100)*
                Filters search results to items with at least one offer having saving percentage above the specified value
            *offer_count (integer)*
                The number of offers desired for each item in the search results. Default: 1
            *search_index (string)*
                search products based on an index. Default value "All"
            *sort_by (string, optional)*
                sort hte results based on the specification defined at https://webservices.amazon.com/paapi5/documentation/search-items.html#sortby-parameter
            *title (string)*
                Title associated with the item. Title searches are subset of Keywords searches. Use a Keywords search if a Title search does not return desired items.
            *http_info (boolean)*
                specify if http header should be returned
            *async_req (boolean)*
                specify if a thread should be created to run the request
            *search_items_resource (list)*
                For more details, refer: https://webservices.amazon.com/paapi5/documentation/search-items.html#resources-parameter. By deafult all possible resources are requested
        return
            Dict with 
                *data* 
                    contains the AmazonProduct list
                *http_info*
                    contains the http header information if requested. By default None
        """

        try:
            if item_count > 10 or item_count < 1:
                item_count = 10
            cache_url = self._cache_url(
                {'partner_tag':self.partner_tag,
                'partner_type':PartnerType.ASSOCIATES,
                'keywords':keywords,
                'search_index':search_index,
                'item_count':item_count,
                'condition':condition,
                'browse_node_id': browse_node_id,
                'brand': brand,
                'sort_by': sort_by,
                'actor': actor,
                'artist': artist,
                'author': author,
                'availability': availability,
                'currency_of_preference': currency_of_preference,
                'delivery_flags': delivery_flags,
                'item_page': item_page,
                'languages_of_preference': languages_of_preference,
                'max_price': max_price,
                'merchant': merchant,
                'min_price': min_price,
                'min_reviews_rating': min_reviews_rating,
                'min_saving_percent': min_saving_percent,
                'offer_count': offer_count,
                'title': title
                }
            )
            
            if self.CacheReader:
                cached_response_text = self.CacheReader(cache_url)
                if cached_response_text is not None:
                    return {'data': pickle.loads(cached_response_text['data']), 'http_info': pickle.loads(cached_response_text['http_info'])}

            search_items_request = SearchItemsRequest(
                partner_tag=self.partner_tag,
                partner_type=PartnerType.ASSOCIATES,
                actor=actor,
                artist=artist,
                author=author,
                availability=availability,
                brand=brand,
                browse_node_id=browse_node_id,
                condition=condition,
                currency_of_preference=currency_of_preference,
                delivery_flags=delivery_flags,
                item_count=item_count,
                item_page=item_page,
                keywords=keywords,
                languages_of_preference=languages_of_preference,
                max_price=max_price,
                merchant=merchant,
                min_price=min_price,
                min_reviews_rating=min_reviews_rating,
                min_saving_percent=min_saving_percent,
                offer_count=offer_count,
                resources=search_items_resource,
                search_index=search_index,
                sort_by=sort_by,
                title=title
            )
            
            
        except ValueError as exception:
            #print("Error in forming SearchItemsRequest: ", exception)
            raise AmazonException("ValueError", exception)
        except AmazonException as exception:
            #print("Error in forming SearchItemsRequest: ", exception)
            raise AmazonException(exception.status, exception.reason)

        try:
            """ Sending request """
            wait_time = 1 / self.throttling - (time.time() - self.last_query_time)
            if wait_time > 0:
                time.sleep(wait_time)
            self.last_query_time = time.time()
            resp_http = None
            if http_info:
                response_with_http_info = self.default_api.search_items_with_http_info(search_items_request)
                """ Parse response """
                if response_with_http_info is not None:
                    response = response_with_http_info[0]
                    resp_http = response_with_http_info[2]
                    if response.search_result is not None:
                        resp = [ AmazonProduct(item) for item in response.search_result.items]
                        if self.CacheWriter:
                            self.CacheWriter(cache_url, pickle.dumps(resp), pickle.dumps(resp_http))
                        return {'data': resp, 'http_info': resp_http}
                    if response.errors is not None:
                        #print("\nPrinting Errors:\nPrinting First Error Object from list of Errors")
                        #print("Error code", response.errors[0].code)
                        #print("Error message", response.errors[0].message)
                        raise AmazonException(response.errors[0].code, response.errors[0].message)

            else:
                if async_req:
                    thread = self.default_api.search_items(search_items_request, async_req=True)
                    response = thread.get()
                else:
                    response = self.default_api.search_items(search_items_request)
                """ Parse response """
                if response.search_result is not None:
                    resp = [ AmazonProduct(item) for item in response.search_result.items]
                    if self.CacheWriter:
                        self.CacheWriter(cache_url, pickle.dumps(resp), pickle.dumps(resp_http))
                    return {'data': resp, 'http_info': resp_http}
                if response.errors is not None:
                    #print("\nPrinting Errors:\nPrinting First Error Object from list of Errors")
                    #print("Error code", response.errors[0].code)
                    #print("Error message", response.errors[0].message)
                    if response.errors[0].code == "NoResults":
                        resp = []
                        if self.CacheWriter:
                            self.CacheWriter(cache_url, pickle.dumps(resp), pickle.dumps(resp_http))  
                    raise AmazonException(response.errors[0].code, response.errors[0].message)

        except ApiException as exception:
            #print("Error calling PA-API 5.0!")
            #print("Status code:", exception.status)
            #print("Errors :", exception.body)
            #print("Request ID:", exception.headers["x-amzn-RequestId"])
            raise AmazonException("ApiException", exception.body)

        except TypeError as exception:
            #print("TypeError :", exception)
            raise AmazonException("TypeError", exception)

        except ValueError as exception:
            #print("ValueError :", exception)
            raise AmazonException(ValueError, exception)

        except AmazonException as exception:
            raise AmazonException(exception.status, exception.reason)
        
        except Exception as exception:
            raise AmazonException("General", exception)


    
    def search_items_pool(self, actor=None, artist=None,author=None, availability=None, brand=None, browse_node_id=None, condition=None, currency_of_preference=None, delivery_flags=None, item_count=10,item_page=1, keywords=None, languages_of_preference=None, max_price=None, merchant="All", min_price=None,  min_reviews_rating=None, min_saving_percent=None, offer_count=1, search_index="All", sort_by= None,  title=None, search_items_resource=SEARCH_RESOURCES ,connetion_pool_max_size=12):
        """ 
        Search products based on keywords. You can specify max connection pool size here. We recommend a value equal to cpu_count * 5.
        Choose resources you want from SEARCH_RESOURCES enum.
        For more details, refer: https://webservices.amazon.com/paapi5/documentation/search-items.html#resources-parameter 

        args:
            *actor (string)*
                actor to search products
            *artist (string)*
                artist to search products
            *author (string)*
                author to search products
            *availability (string)*
                availability to search products. Admitted values: "Available", "IncludeOutOfStock"
            *brand* (string, optional)*
                filter the products based on the brand
            *browse_node_id (string)*
                search products into a specific browse node
            *condition* (enum, optional)*
                filter the products based on the condition
            *currency_of_preference (string)*
                Currency of preference in which the prices information should be returned in response. By default the prices are returned in the default currency of the marketplace. Expected currency code format is the ISO 4217 currency code (i.e. USD, EUR etc.)
            *delivery_flags (list of string)*
                The delivery flag filters items which satisfy a certain delivery program promoted by the specific Amazon Marketplace. For example, Prime DeliveryFlag will return items having at least one offer which is Prime Eligible.
            *item_count (integer)*
                number of products returned. Values in the range [1,10]. Default 10
            *item_page (integer)*
                can be used to fetch the specific set/page of items to be returned from the available Search Results. The number of items returned in a page is determined by the item_count parameter. For e.g. if the third set of 5 items (i.e. items numbered 11 to 15) are desired for a search request, you may specify
            *keywords (string)*
                keywords to search products
            *languages_of_preference (list of string)*
                Languages in order of preference in which the item information should be returned in response. By default the item information is returned in the default language of the marketplace.
            *max_price (positive integers)*
                Filters search results to items with at least one offer price below the specified value. Prices appear in lowest currency denomination. For example, in US marketplace, 3241 is $31.41.
            *merchant (string)*
                Filters search results to return items having at least one offer sold by target merchant. By default the value "All" is passed. 
            *min_price (positive integers)*
                Filters search results to items with at least one offer price above the specified value. Prices appear in lowest currency denomination. For example, in US marketplace, 3241 is $32.41.
            *min_reviews_rating (positive integers less than 5)*
                Filters search results to items with customer review ratings above specified value.
            *min_saving_percent (integers less than 100)*
                Filters search results to items with at least one offer having saving percentage above the specified value
            *offer_count (integer)*
                The number of offers desired for each item in the search results. Default: 1
            *search_index (string)*
                search products based on an index. Default value "All"
            *sort_by (string, optional)*
                sort hte results based on the specification defined at https://webservices.amazon.com/paapi5/documentation/search-items.html#sortby-parameter
            *title (string)*
                Title associated with the item. Title searches are subset of Keywords searches. Use a Keywords search if a Title search does not return desired items.
            *search_items_resource (list)*
                For more details, refer: https://webservices.amazon.com/paapi5/documentation/search-items.html#resources-parameter. By deafult all possible resources are requested
            *connetion_pool_max_size (integer)*
                sice of connection pool. Default 12
        return
            Dict with 
                *data* 
                    contains the AmazonProduct list
                *http_info*
                    contains the http header information if requested. By default None
        """
        
        configuration = Configuration()
        configuration.__init__(connetion_pool_max_size)

        """ API Client Declaration """
        api_client = ApiClient(
            access_key=self.access_key,
            secret_key=self.secret_key,
            host=self.host,
            region=self.region,
            configuration=configuration,
        )

        """ API declaration """
        default_api = DefaultApi(api_client=api_client)

        """ Forming request """
        try:
            if item_count > 10 or item_count < 1:
                item_count = 10

            cache_url = self._cache_url(
                {'partner_tag':self.partner_tag,
                'partner_type':PartnerType.ASSOCIATES,
                'keywords':keywords,
                'search_index':search_index,
                'item_count':item_count,
                'condition':condition,
                'browse_node_id': browse_node_id,
                'brand': brand,
                'sort_by': sort_by,
                'actor': actor,
                'artist': artist,
                'author': author,
                'availability': availability,
                'currency_of_preference': currency_of_preference,
                'delivery_flags': delivery_flags,
                'item_page': item_page,
                'languages_of_preference': languages_of_preference,
                'max_price': max_price,
                'merchant': merchant,
                'min_price': min_price,
                'min_reviews_rating': min_reviews_rating,
                'min_saving_percent': min_saving_percent,
                'offer_count': offer_count,
                'title': title
                }
            )
            
            if self.CacheReader:
                cached_response_text = self.CacheReader(cache_url)
                if cached_response_text is not None:
                    return {'data': pickle.loads(cached_response_text['data']), 'http_info': pickle.loads(cached_response_text['http_info'])}

            search_items_request = SearchItemsRequest(
                partner_tag=self.partner_tag,
                partner_type=PartnerType.ASSOCIATES,
                actor=actor,
                artist=artist,
                author=author,
                availability=availability,
                brand=brand,
                browse_node_id=browse_node_id,
                condition=condition,
                currency_of_preference=currency_of_preference,
                delivery_flags=delivery_flags,
                item_count=item_count,
                item_page=item_page,
                keywords=keywords,
                languages_of_preference=languages_of_preference,
                max_price=max_price,
                merchant=merchant,
                min_price=min_price,
                min_reviews_rating=min_reviews_rating,
                min_saving_percent=min_saving_percent,
                offer_count=offer_count,
                resources=search_items_resource,
                search_index=search_index,
                sort_by=sort_by,
                title=title
            )
            

        except ValueError as exception:
            #print("Error in forming SearchItemsRequest: ", exception)
            raise AmazonException("ValueError", exception)

        try:
            """ Sending request """
            wait_time = 1 / self.throttling - (time.time() - self.last_query_time)
            if wait_time > 0:
                time.sleep(wait_time)
            self.last_query_time = time.time()
            resp_http = None
            response = default_api.search_items(search_items_request)

            """ Parse response """
            if response.search_result is not None:
                resp = [ AmazonProduct(item) for item in response.search_result.items]
                if self.CacheWriter:
                    self.CacheWriter(cache_url, pickle.dumps(resp), pickle.dumps(resp_http))
                return {'data': resp, 'http_info': resp_http}
            if response.errors is not None:
                #print("\nPrinting Errors:\nPrinting First Error Object from list of Errors")
                #print("Error code", response.errors[0].code)
                #print("Error message", response.errors[0].message)
                raise AmazonException(response.errors[0].code, response.errors[0].message)

        except ApiException as exception:
            #print("Error calling PA-API 5.0!")
            #print("Status code:", exception.status)
            #print("Errors :", exception.body)
            #print("Request ID:", exception.headers["x-amzn-RequestId"])
            raise AmazonException("ApiException", exception.body)

        except TypeError as exception:
            #print("TypeError :", exception)
            raise AmazonException("TypeError", exception)

        except ValueError as exception:
            #print("ValueError :", exception)
            raise AmazonException(ValueError, exception)

        except AmazonException as exception:
            raise AmazonException(exception.status, exception.reason)
        
        except Exception as exception:
            raise AmazonException("General", exception)
            raise Exception(exception)

    """ Choose resources you want from GetVariationsResource enum """
    """ For more details, refer: https://webservices.amazon.com/paapi5/documentation/get-variations.html#resources-parameter """
    def get_variations(self, asin, condition=None, currency_of_preference=None, languages_of_preference=None, merchant="All", offer_count=1, variation_count=10, variation_page=1, async_req=False, http_info=False, get_variations_resources=VARIATION_RESOURCES):
        """ 
        Get product variation using the asin of orginal product.
        Choose resources you want from VARIATION_RESOURCES enum.
        For more details, refer: https://webservices.amazon.com/paapi5/documentation/get-variations.html#request-parameters

        args:
            *asin (string)*
                asin of the product for which we want the variations
            *condition* (enum, optional)*
                filter the products based on the condition
            *currency_of_preference (string)*
                specify the currency of returned results
            *languages_of_preference (list of string)*
                specify the language of returned results
            *merchant (string)*
                Filters search results to return items having at least one offer sold by target merchant. By default the value "All" is passed. 
            *offer_count (integer)*
                The number of offers desired for each item in the search results. Default: 1
            *variation_count (integer)*
                Number of variations to be returned per page. Default: 10
            *variation_page (integer)*
                Page number of variations returned by get_variations. Default: 1 
            *http_info (boolean)*
                specify if http header should be returned
            *async_req (boolean)*
                specify if a thread should be created to run the request
            *get_variations_resources (list)*
                For more details, refer: https://webservices.amazon.com/paapi5/documentation/get-variations.html#request-parameters. By deafult all possible resources are requested
            
        return
            Dict with 
                *data* 
                    contains the AmazonProduct list
                *http_info*
                    contains the http header information if requested. By default None
        """
        try:
            cache_url = self._cache_url(
                {'partner_tag':self.partner_tag,
                'partner_type':PartnerType.ASSOCIATES,
                'asin':asin,
                'condition': condition,
                'currency_of_preference': currency_of_preference,
                'languages_of_preference':languages_of_preference,
                'merchant':merchant,
                'offer_count': offer_count,
                'variation_count': variation_count,
                'variation_page': variation_page
                }
            )
            
            if self.CacheReader:
                cached_response_text = self.CacheReader(cache_url)
                if cached_response_text is not None:
                    return {'data': pickle.loads(cached_response_text['data']), 'http_info': pickle.loads(cached_response_text['http_info'])}

            get_variations_request = GetVariationsRequest(
                partner_tag=self.partner_tag,
                partner_type=PartnerType.ASSOCIATES,
                marketplace=self.marketplace,
                asin=asin,
                condition=condition,
                currency_of_preference=currency_of_preference,
                languages_of_preference=languages_of_preference,
                merchant=merchant,
                offer_count=offer_count,
                variation_count=variation_count,
                variation_page=variation_page,
                resources=get_variations_resources
            )
            
        except ValueError as exception:
            #print("Error in forming GetVariationsRequest: ", exception)
            raise AmazonException("ValueError", exception)

        try:
            wait_time = 1 / self.throttling - (time.time() - self.last_query_time)
            if wait_time > 0:
                time.sleep(wait_time)
            self.last_query_time = time.time()
            resp_http = None
            """ Sending request """
            if http_info:
                response_with_http_info = self.default_api.get_variations_with_http_info(get_variations_request)

                """ Parse response """
                if response_with_http_info is not None:
                    response = response_with_http_info[0]
                    resp_http = response_with_http_info[2]
                    if response.variations_result is not None:
                        resp = [ AmazonProduct(item) for item in response.variations_result.items]
                        if self.CacheWriter:
                            self.CacheWriter(cache_url, pickle.dumps(resp), pickle.dumps(resp_http))
                        return {'data': resp, 'http_info': resp_http}

                    if response.errors is not None:
                        #print("\nPrinting Errors:\nPrinting First Error Object from list of Errors")
                        #print("Error code", response.errors[0].code)
                        #print("Error message", response.errors[0].message)
                        raise AmazonException(response.errors[0].code, response.errors[0].message)
            else:
                if async_req:
                    thread = self.default_api.get_variations(get_variations_request, async_req=True)
                    response = thread.get()
                else:
                    response = self.default_api.get_variations(get_variations_request)

                """ Parse response """
                if response.variations_result is not None:
                    resp = [ AmazonProduct(item) for item in response.variations_result.items]
                    if self.CacheWriter:
                        self.CacheWriter(cache_url, pickle.dumps(resp), pickle.dumps(resp_http))
                    return {'data': resp, 'http_info': resp_http}

                if response.errors is not None:
                    #print("\nPrinting Errors:\nPrinting First Error Object from list of Errors")
                    #print("Error code", response.errors[0].code)
                    #print("Error message", response.errors[0].message)
                    raise AmazonException(response.errors[0].code, response.errors[0].message)

        except ApiException as exception:
            #print("Error calling PA-API 5.0!")
            #print("Status code:", exception.status)
            #print("Errors :", exception.body)
            #print("Request ID:", exception.headers["x-amzn-RequestId"])
            raise AmazonException("ApiException", exception.body)

        except TypeError as exception:
            #print("TypeError :", exception)
            raise AmazonException("TypeError", exception)

        except ValueError as exception:
            #print("ValueError :", exception)
            raise AmazonException(ValueError, exception)

        except AmazonException as exception:
            raise AmazonException(exception.status, exception.reason)
        
        except Exception as exception:
            raise AmazonException("General", exception)


    """ Choose resources you want from GetItemsResource enum """
    """ For more details, refer: https://webservices.amazon.com/paapi5/documentation/get-items.html#resources-parameter """
    def get_items(self, item_ids=[], condition=None, currency_of_preference=None, item_id_type="ASIN",languages_of_preference=None, merchant="All", offer_count=1, http_info=False, async_req=False, get_items_resource=ITEM_RESOURCES):
        """ 
        Get items' information.
        Choose resources you want from ITEM_RESOURCES enum 
        For more details, refer: https://webservices.amazon.com/paapi5/documentation/get-items.html#ItemLookup-rp

        args:
            *item_ids (list of string)*
                list of asin of the products of interest
            *condition* (enum, optional)*
                filter the products based on the condition
            *currency_of_preference (string)*
                specify the currency of returned results
            *item_id_type (string)*
                Type of item identifier used to look up an item. Default: ASIN
            *languages_of_preference (list of string)*
                Languages in order of preference in which the item information should be returned in response. By default the item information is returned in the default language of the marketplace
            *merchant (string)*
                Filters search results to return items having at least one offer sold by target merchant. By default the value "All" is passed. 
            *offer_count (integer)*
                The number of offers desired for each item in the search results. Default: 1
            *http_info (boolean)*
                specify if http header should be returned
            *async_req (boolean)*
                specify if a thread should be created to run the request
            *get_items_resource (list)*
                For more details, refer: https://webservices.amazon.com/paapi5/documentation/get-items.html#ItemLookup-rp. By deafult all possible resources are requested
            
        return
            Dict with 
                *data* 
                    Dict of ASIN to AmazonProduct object
                *http_info*
                    contains the http header information if requested. By default None
        """
        
        if len(item_ids) == 0:
            raise Exception('No item ids specified')
        
        """ Forming request """
        try:
            cache_url = self._cache_url(
                {'partner_tag':self.partner_tag,
                'partner_type':PartnerType.ASSOCIATES,
                'item_ids':item_ids,    
                'condition':condition,
                'currency_of_preference': currency_of_preference,
                'item_id_type': item_id_type,
                'languages_of_preference': languages_of_preference,
                'merchant': merchant,
                'offer_count': offer_count
                }
            )
            
            if self.CacheReader:
                cached_response_text = self.CacheReader(cache_url)
                if cached_response_text is not None:
                    return {'data': parse_response_item( pickle.loads(cached_response_text['data']) ), 'http_info': pickle.loads(cached_response_text['http_info'])}

            get_items_request = GetItemsRequest(
                partner_tag=self.partner_tag,
                partner_type=PartnerType.ASSOCIATES,
                marketplace=self.marketplace,
                item_ids=item_ids,
                condition=condition,
                currency_of_preference=currency_of_preference,
                item_id_type=item_id_type,
                languages_of_preference=languages_of_preference,
                merchant=merchant,
                offer_count=offer_count,
                resources=get_items_resource
            )
            

        except ValueError as exception:
            #print("Error in forming GetItemsRequest: ", exception)
            raise AmazonException("ValueError", exception)

        try:
            wait_time = 1 / self.throttling - (time.time() - self.last_query_time)
            if wait_time > 0:
                time.sleep(wait_time)
            self.last_query_time = time.time()
            resp_http = None

            if http_info:
                response_with_http_info = self.default_api.get_items_with_http_info(
                    get_items_request
                )

                """ Parse response """
                if response_with_http_info is not None:
                    response = response_with_http_info[0]
                    resp_http = response_with_http_info[2]
                    if response.items_result is not None:
                        resp = [ AmazonProduct(item) for item in response.items_result.items]
                        if self.CacheWriter:
                            self.CacheWriter(cache_url, pickle.dumps(resp), pickle.dumps(resp_http))
                        return {'data': parse_response_item(resp), 'http_info': resp_http}
                        
                    if response.errors is not None:
                        #print("\nPrinting Errors:\nPrinting First Error Object from list of Errors")
                        #print("Error code", response.errors[0].code)
                        #print("Error message", response.errors[0].message)
                        raise AmazonException(response.errors[0].code, response.errors[0].message)

            else:
                """ Sending request """
                if async_req:
                    thread = self.default_api.get_items(get_items_request, async_req=True)
                    response = thread.get()
                else:
                    response = self.default_api.get_items(get_items_request)

                """ Parse response """
                if response.items_result is not None:
                    resp = [ AmazonProduct(item) for item in response.items_result.items]
                    if self.CacheWriter:
                        self.CacheWriter(cache_url, pickle.dumps(resp), pickle.dumps(resp_http))
                    return {'data': parse_response_item(resp), 'http_info': resp_http}

                if response.errors is not None:
                    #print("\nPrinting Errors:\nPrinting First Error Object from list of Errors")
                    #print("Error code", response.errors[0].code)
                    #print("Error message", response.errors[0].message)
                    raise AmazonException(response.errors[0].code, response.errors[0].message)


        except ApiException as exception:
            #print("Error calling PA-API 5.0!")
            #print("Status code:", exception.status)
            #print("Errors :", exception.body)
            #print("Request ID:", exception.headers["x-amzn-RequestId"])
            raise AmazonException("ApiException", exception.body)

        except TypeError as exception:
            #print("TypeError :", exception)
            raise AmazonException("TypeError", exception)

        except ValueError as exception:
            #print("ValueError :", exception)
            raise AmazonException(ValueError, exception)

        except AmazonException as exception:
            raise AmazonException(exception.status, exception.reason)
        
        except Exception as exception:
            raise AmazonException("General", exception)



    """ Choose resources you want from GetBrowseNodesResource enum """
    """ For more details, refer: https://webservices.amazon.com/paapi5/documentation/getbrowsenodes.html#resources-parameter """
    def get_browse_nodes(self, browse_node_ids=[], languages_of_preference = None, http_info=False, async_req=False, get_browse_node_resources=BROWSE_RESOURCES):
        """" 
        Get browse nodes' information.
        Choose resources you want from BROWSE_RESOURCES enum 
        For more details, refer: https://webservices.amazon.com/paapi5/documentation/getbrowsenodes.html#request-parameters

        args:
            *browse_node_ids (list of string)*
                list of browse node ids
            *languages_of_preference (list of string)*
                specify the language of returned results
            *http_info (boolean)*
                specify if http header should be returned
            *async_req (boolean)*
                specify if a thread should be created to run the request
            
            *get_browse_node_resources (list)*
                For more details, refer: https://webservices.amazon.com/paapi5/documentation/getbrowsenodes.html#request-parameters. By deafult all possible resources are requested
            
        return
            Dict with 
                *data* 
                    Dict of BrowseNodeID to AmazonBrowseNode object
                *http_info*
                    contains the http header information if requested. By default None
        """
        
        if isinstance(browse_node_ids, list) == False or len (browse_node_ids) == 0:
            raise Exception('Browse node ids are not in the right format')
        
        """ Forming request """
        try:
            cache_url = self._cache_url(
                {'partner_tag':self.partner_tag,
                'partner_type':PartnerType.ASSOCIATES,
                'browse_node_ids':browse_node_ids,
                'languages_of_preference':languages_of_preference }
                )
            
            if self.CacheReader:
                cached_response_text = self.CacheReader(cache_url)
                if cached_response_text is not None:
                    return {'data': parse_response_browse_node (pickle.loads(cached_response_text['data']) ), 'http_info': pickle.loads(cached_response_text['http_info'])}

            get_browse_node_request = GetBrowseNodesRequest(
                partner_tag=self.partner_tag,
                partner_type=PartnerType.ASSOCIATES,
                marketplace=self.marketplace,
                languages_of_preference=languages_of_preference,
                browse_node_ids=browse_node_ids,
                resources=get_browse_node_resources,
            )
            
        except ValueError as exception:
            #print("Error in forming GetBrowseNodesRequest: ", exception)
            raise AmazonException("ValueError", exception)

        try:
            wait_time = 1 / self.throttling - (time.time() - self.last_query_time)
            if wait_time > 0:
                time.sleep(wait_time)
            self.last_query_time = time.time()
            resp_http = None

            if http_info:
                response_with_http_info = self.default_api.get_browse_nodes_with_http_info(get_browse_node_request)

                """ Parse response """
                if response_with_http_info is not None:
                    response = response_with_http_info[0]
                    resp_http = response_with_http_info[2]
                    if response.browse_nodes_result is not None:
                        resp = [ AmazonBrowseNode(node) for node in response.browse_nodes_result.browse_nodes]
                        if self.CacheWriter:
                            self.CacheWriter(cache_url, pickle.dumps(resp), pickle.dumps(resp_http))
                        return {'data': parse_response_browse_node(resp), 'http_info': resp_http}
                        
                    if response.errors is not None:
                        #print("\nPrinting Errors:\nPrinting First Error Object from list of Errors")
                        #print("Error code", response.errors[0].code)
                        #print("Error message", response.errors[0].message)
                        raise AmazonException(response.errors[0].code, response.errors[0].message)

            else:
                """ Sending request """
                if async_req:
                    thread = self.default_api.get_browse_nodes(get_browse_node_request, async_req=True)
                    response = thread.get()
                else:
                    response = self.default_api.get_browse_nodes(get_browse_node_request)

                """ Parse response """
                if response.browse_nodes_result is not None:
                    resp = [ AmazonBrowseNode(item) for item in response.browse_nodes_result.browse_nodes]
                    if self.CacheWriter:
                        self.CacheWriter(cache_url, pickle.dumps(resp), pickle.dumps(resp_http))
                    return {'data': parse_response_browse_node(resp), 'http_info': resp_http}
                    
                if response.errors is not None:
                    #print("\nPrinting Errors:\nPrinting First Error Object from list of Errors")
                    #print("Error code", response.errors[0].code)
                    #print("Error message", response.errors[0].message)
                    raise AmazonException(response.errors[0].code, response.errors[0].message)

        except ApiException as exception:
            #print("Error calling PA-API 5.0!")
            #print("Status code:", exception.status)
            #print("Errors :", exception.body)
            #print("Request ID:", exception.headers["x-amzn-RequestId"])
            raise AmazonException("ApiException", exception.body)

        except TypeError as exception:
            #print("TypeError :", exception)
            raise AmazonException("TypeError", exception)

        except ValueError as exception:
            #print("ValueError :", exception)
            raise AmazonException(ValueError, exception)

        except AmazonException as exception:
            raise AmazonException(exception.status, exception.reason)
        
        except Exception as exception:
            raise AmazonException("General", exception)
Ejemplo n.º 8
0
    def get_products(self, product_ids: [str, list], condition=Condition.ANY):
        """Find product information for a specific product on Amazon.

        Args:
            product_ids (string): One or more item ids like ASIN or product URL.
            Could be a string separated by comma or as a list.
            condition (class, optional): Specify the product condition. Defaults to ANY.

        Returns:
            list of instances: A list containing 1 instance for each product.
        """
        api = DefaultApi(access_key=self.key,
                         secret_key=self.secret,
                         host=self.host,
                         region=self.region)

        # Clean up input data into a list stripping any extra white space
        asin_or_url_list = [x.strip() for x in product_ids.split(",")
                            ] if isinstance(product_ids, str) else product_ids

        # Extract ASIN if supplied input is product URL and remove any duplicate ASIN
        asin_full_list = list(set([get_asin(x) for x in asin_or_url_list]))

        # Creates lists of 10 items each
        asin_full_list = list(_chunks(asin_full_list, 10))

        product_resources = [
            GetItemsResource.BROWSENODEINFO_BROWSENODES,
            GetItemsResource.BROWSENODEINFO_BROWSENODES_ANCESTOR,
            GetItemsResource.BROWSENODEINFO_BROWSENODES_SALESRANK,
            GetItemsResource.BROWSENODEINFO_WEBSITESALESRANK,
            GetItemsResource.IMAGES_PRIMARY_SMALL,
            GetItemsResource.IMAGES_PRIMARY_MEDIUM,
            GetItemsResource.IMAGES_PRIMARY_LARGE,
            GetItemsResource.IMAGES_VARIANTS_SMALL,
            GetItemsResource.IMAGES_VARIANTS_MEDIUM,
            GetItemsResource.IMAGES_VARIANTS_LARGE,
            GetItemsResource.ITEMINFO_BYLINEINFO,
            GetItemsResource.ITEMINFO_CONTENTINFO,
            GetItemsResource.ITEMINFO_CONTENTRATING,
            GetItemsResource.ITEMINFO_CLASSIFICATIONS,
            GetItemsResource.ITEMINFO_EXTERNALIDS,
            GetItemsResource.ITEMINFO_FEATURES,
            GetItemsResource.ITEMINFO_MANUFACTUREINFO,
            GetItemsResource.ITEMINFO_PRODUCTINFO,
            GetItemsResource.ITEMINFO_TECHNICALINFO,
            GetItemsResource.ITEMINFO_TITLE,
            GetItemsResource.ITEMINFO_TRADEININFO,
            GetItemsResource.OFFERS_LISTINGS_AVAILABILITY_MAXORDERQUANTITY,
            GetItemsResource.OFFERS_LISTINGS_AVAILABILITY_MESSAGE,
            GetItemsResource.OFFERS_LISTINGS_AVAILABILITY_MINORDERQUANTITY,
            GetItemsResource.OFFERS_LISTINGS_AVAILABILITY_TYPE,
            GetItemsResource.OFFERS_LISTINGS_CONDITION,
            GetItemsResource.OFFERS_LISTINGS_CONDITION_SUBCONDITION,
            GetItemsResource.OFFERS_LISTINGS_DELIVERYINFO_ISAMAZONFULFILLED,
            GetItemsResource.
            OFFERS_LISTINGS_DELIVERYINFO_ISFREESHIPPINGELIGIBLE,
            GetItemsResource.OFFERS_LISTINGS_DELIVERYINFO_ISPRIMEELIGIBLE,
            GetItemsResource.OFFERS_LISTINGS_DELIVERYINFO_SHIPPINGCHARGES,
            GetItemsResource.OFFERS_LISTINGS_ISBUYBOXWINNER,
            GetItemsResource.OFFERS_LISTINGS_LOYALTYPOINTS_POINTS,
            GetItemsResource.OFFERS_LISTINGS_MERCHANTINFO,
            GetItemsResource.OFFERS_LISTINGS_PRICE, GetItemsResource.
            OFFERS_LISTINGS_PROGRAMELIGIBILITY_ISPRIMEEXCLUSIVE,
            GetItemsResource.OFFERS_LISTINGS_PROGRAMELIGIBILITY_ISPRIMEPANTRY,
            GetItemsResource.OFFERS_LISTINGS_PROMOTIONS,
            GetItemsResource.OFFERS_LISTINGS_SAVINGBASIS,
            GetItemsResource.OFFERS_SUMMARIES_HIGHESTPRICE,
            GetItemsResource.OFFERS_SUMMARIES_LOWESTPRICE,
            GetItemsResource.OFFERS_SUMMARIES_OFFERCOUNT,
            GetItemsResource.PARENTASIN, GetItemsResource.
            RENTALOFFERS_LISTINGS_AVAILABILITY_MAXORDERQUANTITY,
            GetItemsResource.RENTALOFFERS_LISTINGS_AVAILABILITY_MESSAGE,
            GetItemsResource.
            RENTALOFFERS_LISTINGS_AVAILABILITY_MINORDERQUANTITY,
            GetItemsResource.RENTALOFFERS_LISTINGS_AVAILABILITY_TYPE,
            GetItemsResource.RENTALOFFERS_LISTINGS_BASEPRICE,
            GetItemsResource.RENTALOFFERS_LISTINGS_CONDITION,
            GetItemsResource.RENTALOFFERS_LISTINGS_CONDITION_SUBCONDITION,
            GetItemsResource.
            RENTALOFFERS_LISTINGS_DELIVERYINFO_ISAMAZONFULFILLED,
            GetItemsResource.
            RENTALOFFERS_LISTINGS_DELIVERYINFO_ISFREESHIPPINGELIGIBLE,
            GetItemsResource.
            RENTALOFFERS_LISTINGS_DELIVERYINFO_ISPRIMEELIGIBLE,
            GetItemsResource.
            RENTALOFFERS_LISTINGS_DELIVERYINFO_SHIPPINGCHARGES,
            GetItemsResource.RENTALOFFERS_LISTINGS_MERCHANTINFO
        ]

        results = []
        for asin_list in asin_full_list:
            try:
                request = GetItemsRequest(partner_tag=self.tag,
                                          partner_type=PartnerType.ASSOCIATES,
                                          marketplace=self.marketplace,
                                          condition=condition,
                                          item_ids=asin_list,
                                          resources=product_resources)
            except Exception as exception:
                raise exception

            try:
                # Wait before doing the request
                wait_time = 1 / self.throttling - (time.time() -
                                                   self.last_query_time)
                if wait_time > 0:
                    time.sleep(wait_time)
                self.last_query_time = time.time()

                response = api.get_items(request)
                if response.items_result is not None:
                    if len(response.items_result.items) > 0:
                        for item in response.items_result.items:
                            product = parse_product(item)
                            results.append(product)
            except Exception as exception:
                raise exception

        if results:
            return results
        else:
            return None
Ejemplo n.º 9
0
    def get_product(self, product_id, condition=Condition.ANY):
        """Find product information for a specific product on Amazon.

        Args:
            product_id (string): Product ASIN or URL. You can send multiple products separated
                by commas.
            condition (class, optional): Specify the product condition. Defaults to NEW.

        Returns:
            class instance: An instance of the class Product containing all the available
                information when only 1 product is returned.
            list of class instances: A list containing 1 instance of the class Product for
                each returned product.
        """
        api = DefaultApi(access_key=self.key,
                         secret_key=self.secret,
                         host=self.host,
                         region=self.region)

        product_id = product_id.split(',')
        asin_list = []
        for x in product_id:
            asin_list.append(get_asin(x.strip()))

        product_resources = [
            GetItemsResource.BROWSENODEINFO_BROWSENODES,
            GetItemsResource.BROWSENODEINFO_BROWSENODES_ANCESTOR,
            GetItemsResource.BROWSENODEINFO_BROWSENODES_SALESRANK,
            GetItemsResource.BROWSENODEINFO_WEBSITESALESRANK,
            GetItemsResource.IMAGES_PRIMARY_SMALL,
            GetItemsResource.IMAGES_PRIMARY_MEDIUM,
            GetItemsResource.IMAGES_PRIMARY_LARGE,
            GetItemsResource.IMAGES_VARIANTS_SMALL,
            GetItemsResource.IMAGES_VARIANTS_MEDIUM,
            GetItemsResource.IMAGES_VARIANTS_LARGE,
            GetItemsResource.ITEMINFO_BYLINEINFO,
            GetItemsResource.ITEMINFO_CONTENTINFO,
            GetItemsResource.ITEMINFO_CONTENTRATING,
            GetItemsResource.ITEMINFO_CLASSIFICATIONS,
            GetItemsResource.ITEMINFO_EXTERNALIDS,
            GetItemsResource.ITEMINFO_FEATURES,
            GetItemsResource.ITEMINFO_MANUFACTUREINFO,
            GetItemsResource.ITEMINFO_PRODUCTINFO,
            GetItemsResource.ITEMINFO_TECHNICALINFO,
            GetItemsResource.ITEMINFO_TITLE,
            GetItemsResource.ITEMINFO_TRADEININFO,
            GetItemsResource.OFFERS_LISTINGS_AVAILABILITY_MAXORDERQUANTITY,
            GetItemsResource.OFFERS_LISTINGS_AVAILABILITY_MESSAGE,
            GetItemsResource.OFFERS_LISTINGS_AVAILABILITY_MINORDERQUANTITY,
            GetItemsResource.OFFERS_LISTINGS_AVAILABILITY_TYPE,
            GetItemsResource.OFFERS_LISTINGS_CONDITION,
            GetItemsResource.OFFERS_LISTINGS_CONDITION_SUBCONDITION,
            GetItemsResource.OFFERS_LISTINGS_DELIVERYINFO_ISAMAZONFULFILLED,
            GetItemsResource.
            OFFERS_LISTINGS_DELIVERYINFO_ISFREESHIPPINGELIGIBLE,
            GetItemsResource.OFFERS_LISTINGS_DELIVERYINFO_ISPRIMEELIGIBLE,
            GetItemsResource.OFFERS_LISTINGS_DELIVERYINFO_SHIPPINGCHARGES,
            GetItemsResource.OFFERS_LISTINGS_ISBUYBOXWINNER,
            GetItemsResource.OFFERS_LISTINGS_LOYALTYPOINTS_POINTS,
            GetItemsResource.OFFERS_LISTINGS_MERCHANTINFO,
            GetItemsResource.OFFERS_LISTINGS_PRICE, GetItemsResource.
            OFFERS_LISTINGS_PROGRAMELIGIBILITY_ISPRIMEEXCLUSIVE,
            GetItemsResource.OFFERS_LISTINGS_PROGRAMELIGIBILITY_ISPRIMEPANTRY,
            GetItemsResource.OFFERS_LISTINGS_PROMOTIONS,
            GetItemsResource.OFFERS_LISTINGS_SAVINGBASIS,
            GetItemsResource.OFFERS_SUMMARIES_HIGHESTPRICE,
            GetItemsResource.OFFERS_SUMMARIES_LOWESTPRICE,
            GetItemsResource.OFFERS_SUMMARIES_OFFERCOUNT,
            GetItemsResource.PARENTASIN, GetItemsResource.
            RENTALOFFERS_LISTINGS_AVAILABILITY_MAXORDERQUANTITY,
            GetItemsResource.RENTALOFFERS_LISTINGS_AVAILABILITY_MESSAGE,
            GetItemsResource.
            RENTALOFFERS_LISTINGS_AVAILABILITY_MINORDERQUANTITY,
            GetItemsResource.RENTALOFFERS_LISTINGS_AVAILABILITY_TYPE,
            GetItemsResource.RENTALOFFERS_LISTINGS_BASEPRICE,
            GetItemsResource.RENTALOFFERS_LISTINGS_CONDITION,
            GetItemsResource.RENTALOFFERS_LISTINGS_CONDITION_SUBCONDITION,
            GetItemsResource.
            RENTALOFFERS_LISTINGS_DELIVERYINFO_ISAMAZONFULFILLED,
            GetItemsResource.
            RENTALOFFERS_LISTINGS_DELIVERYINFO_ISFREESHIPPINGELIGIBLE,
            GetItemsResource.
            RENTALOFFERS_LISTINGS_DELIVERYINFO_ISPRIMEELIGIBLE,
            GetItemsResource.
            RENTALOFFERS_LISTINGS_DELIVERYINFO_SHIPPINGCHARGES,
            GetItemsResource.RENTALOFFERS_LISTINGS_MERCHANTINFO
        ]

        try:
            request = GetItemsRequest(partner_tag=self.tag,
                                      partner_type=PartnerType.ASSOCIATES,
                                      marketplace=self.marketplace,
                                      condition=condition,
                                      item_ids=asin_list,
                                      resources=product_resources)
        except Exception as exception:
            raise exception

        try:
            # Wait before doing the request
            wait_time = 1 / self.throttling - (time.time() -
                                               self.last_query_time)
            if wait_time > 0:
                time.sleep(wait_time)
            self.last_query_time = time.time()

            response = api.get_items(request)
            if response.items_result is not None:
                if len(response.items_result.items) > 0:
                    results = []
                    for item in response.items_result.items:
                        product = parse_product(item)
                        results.append(product)
                    if len(results) == 0:
                        return None
                    elif len(results) == 1:
                        return results[0]
                    else:
                        return results
                else:
                    return None

        except Exception as exception:
            raise exception
Ejemplo n.º 10
0
class AmazonAPI:
    """Amazon Product Advertising API 5.0 wrapper for Python
    Creates an instance containing your API credentials.

    Args:
        key (string): Your API key.
        secret (string): Your API secret.
        tag (string): The tag you want to use for the URL.
        country (string): Country code.
        throttling (float, optional): Reduce this value to wait longer
          between API calls.
    """
    # Hack: pulls all resource types from GetItemsResource
    RESOURCES = [
        getattr(GetItemsResource, v) for v in vars(GetItemsResource).keys()
        if v.isupper()
    ]

    def __init__(self,
                 key,
                 secret,
                 tag,
                 host='webservices.amazon.com',
                 region='us-east-1',
                 throttling=0.9):
        self.tag = tag
        self.host = host
        self.region = region
        self.throttling = throttling
        self.last_query_time = time.time()

        self.api = DefaultApi(access_key=key,
                              secret_key=secret,
                              host=host,
                              region=self.region)

    def get_product(self, asin, serialize=False, **kwargs):
        products = self.get_products([asin], **kwargs)
        if products:
            return next(
                self.serialize(p) if serialize else p for p in products)

    def get_products(self,
                     asins,
                     serialize=False,
                     marketplace='www.amazon.com',
                     resources=None,
                     **kwargs):
        """
        :param asins (string): One or more ItemIds like ASIN that
        uniquely identify an item or product URL. (Max 10) Seperated
        by comma or as a list.
        """
        item_ids = asins if type(asins) is list else [asins]

        # Wait before doing the request
        wait_time = 1 / self.throttling - (time.time() - self.last_query_time)
        if wait_time > 0:
            time.sleep(wait_time)
        self.last_query_time = time.time()

        try:
            request = GetItemsRequest(partner_tag=self.tag,
                                      partner_type=PartnerType.ASSOCIATES,
                                      marketplace=marketplace,
                                      item_ids=item_ids,
                                      resources=resources or self.RESOURCES,
                                      **kwargs)
            response = self.api.get_items(request)
            products = response.items_result.items
            return (products if not serialize else
                    [self.serialize(p) for p in products])
        except Exception as exception:
            raise exception

    @staticmethod
    def serialize(product):
        """Takes a full Amazon product Advertising API returned AmazonProduct
        with multiple ResponseGroups, and extracts the data we are
        interested in.

        :param AmazonAPI product:
        :return: Amazon metadata for one product
        :rtype: dict

        {
          'price': '$54.06',
          'price_amt': 5406,
          'physical_format': 'Hardcover',
          'authors': [{'role': 'Author', 'name': 'Guterson, David'}],
          'publish_date': 'Jan 21, 2020',
          #'dimensions': {
          #  'width': [1.7, 'Inches'],
          #  'length': [8.5, 'Inches'],
          #  'weight': [5.4, 'Pounds'],
          #  'height': [10.875, 'Inches']
          # },
          'publishers': ['Victory Belt Publishing'],
          'source_records': ['amazon:1628603976'],
          'title': 'Boundless: Upgrade Your Brain, Optimize Your Body & Defy Aging',
          'url': 'https://www.amazon.com/dp/1628603976/?tag=internetarchi-20',
          'number_of_pages': 640,
          'cover': 'https://m.media-amazon.com/images/I/51IT9MV3KqL._AC_.jpg',
          'languages': ['English']
          'edition_num': '1'
        }

        """
        if not product:
            return {}  # no match?

        item_info = product.item_info
        edition_info = item_info.content_info
        attribution = item_info.by_line_info
        price = product.offers.listings and product.offers.listings[0].price
        dims = item_info.product_info and item_info.product_info.item_dimensions

        try:
            publish_date = isoparser.parse(
                edition_info.publication_date.display_value).strftime(
                    '%b %d, %Y')
        except Exception:
            publish_date = None

        book = {
            'url':
            "https://www.amazon.com/dp/%s/?tag=%s" %
            (product.asin, h.affiliate_id('amazon')),
            'source_records': ['amazon:%s' % product.asin],
            'isbn_10': [product.asin],
            'isbn_13': [isbn_10_to_isbn_13(product.asin)],
            'price':
            price and price.display_amount,
            'price_amt':
            price and price.amount and int(100 * price.amount),
            'title':
            item_info.title and item_info.title.display_value,
            'cover': (product.images and product.images.primary
                      and product.images.primary.large
                      and product.images.primary.large.url),
            'authors': [{
                'name': contrib.name,
                'role': contrib.role
            } for contrib in attribution.contributors],
            'publishers':
            attribution.brand and [attribution.brand.display_value],
            'number_of_pages': (edition_info.pages_count
                                and edition_info.pages_count.display_value),
            'edition_num': (edition_info.edition
                            and edition_info.edition.display_value),
            'publish_date':
            publish_date,
            'languages': (edition_info.languages and list(
                set(lang.display_value
                    for lang in edition_info.languages.display_values))),
            'physical_format':
            (item_info.classifications
             and getattr(item_info.classifications.binding, 'display_value')),
            'dimensions':
            dims and {
                d: [getattr(dims, d).display_value,
                    getattr(dims, d).unit]
                for d in dims.to_dict() if getattr(dims, d)
            }
        }
        return book
Ejemplo n.º 11
0
def get_items():
    """ Following are your credentials """
    """ Please add your access key here """
    access_key = "<YOUR ACCESS KEY>"
    """ Please add your secret key here """
    secret_key = "<YOUR SECRET KEY>"
    """ Please add your partner tag (store/tracking id) here """
    partner_tag = "<YOUR PARTNER TAG>"
    """ PAAPI host and region to which you want to send request """
    """ For more details refer: https://webservices.amazon.com/paapi5/documentation/common-request-parameters.html#host-and-region"""
    host = "webservices.amazon.com"
    region = "us-east-1"
    """ API declaration """
    default_api = DefaultApi(access_key=access_key,
                             secret_key=secret_key,
                             host=host,
                             region=region)
    """ Request initialization"""
    """ Choose item id(s) """
    item_ids = ["059035342X", "B00X4WHP5E", "B00ZV9RDKK"]
    """ Choose resources you want from GetItemsResource enum """
    """ For more details, refer: https://webservices.amazon.com/paapi5/documentation/get-items.html#resources-parameter """
    get_items_resource = [
        GetItemsResource.ITEMINFO_TITLE,
        GetItemsResource.OFFERS_LISTINGS_PRICE,
    ]
    """ Forming request """

    try:
        get_items_request = GetItemsRequest(
            partner_tag=partner_tag,
            partner_type=PartnerType.ASSOCIATES,
            marketplace="www.amazon.com",
            condition=Condition.NEW,
            item_ids=item_ids,
            resources=get_items_resource,
        )
    except ValueError as exception:
        print("Error in forming GetItemsRequest: ", exception)
        return

    try:
        """ Sending request """
        response = default_api.get_items(get_items_request)

        print("API called Successfully")
        print("Complete Response:", response)
        """ Parse response """
        if response.items_result is not None:
            print("Printing all item information in ItemsResult:")
            response_list = parse_response(response.items_result.items)
            for item_id in item_ids:
                print("Printing information about the item_id: ", item_id)
                if item_id in response_list:
                    item = response_list[item_id]
                    if item is not None:
                        if item.asin is not None:
                            print("ASIN: ", item.asin)
                        if item.detail_page_url is not None:
                            print("DetailPageURL: ", item.detail_page_url)
                        if (item.item_info is not None
                                and item.item_info.title is not None
                                and item.item_info.title.display_value
                                is not None):
                            print("Title: ",
                                  item.item_info.title.display_value)
                        if (item.offers is not None
                                and item.offers.listings is not None
                                and item.offers.listings[0].price is not None
                                and
                                item.offers.listings[0].price.display_amount
                                is not None):
                            print(
                                "Buying Price: ",
                                item.offers.listings[0].price.display_amount,
                            )
                else:
                    print("Item not found, check errors")

        if response.errors is not None:
            print(
                "\nPrinting Errors:\nPrinting First Error Object from list of Errors"
            )
            print("Error code", response.errors[0].code)
            print("Error message", response.errors[0].message)

    except ApiException as exception:
        print("Error calling PA-API 5.0!")
        print("Status code:", exception.status)
        print("Errors :", exception.body)
        print("Request ID:", exception.headers["x-amzn-RequestId"])

    except TypeError as exception:
        print("TypeError :", exception)

    except ValueError as exception:
        print("ValueError :", exception)

    except Exception as exception:
        print("Exception :", exception)