An Example Using boto Amazon MWS Package

逃离我推掉我的手 2022-08-20 10:17 16阅读 0赞

Overview

This article is a follow up of the Guide to boto Amazon MWS Python Package.Here we give a complete example of submitting a product feed.

This implementation uses boto 2.33 to call Amazon MWS apis. To create a product feed XML, we use the Jinja2 template engine because it has rich features and is widely used by Python developers as Web page or Email templates.

XML Template of Product Feed

Amazon recommends XML, not a flat file, as the preferred data format to send MWS request. According to a group discussion message from a boto MWS developer (Andy Davidoff), boto’s MWS module does not support generating XML from a Python object for two reasons:

First, redistribution of the XSD files is (supposedly) not permitted. Second, there are many defects in these files.

He suggested using an XML template engine and recommended Genshi. Because many Python web developers are already familiar with Jinja2, we use it as our XML template engine.
Using Jianja2 template engine is straight forward because its syntax is similar to Python code. To make the example simple, the below Jinja2 template is used to change titles of one or more products.

Please remove the backslashes in the following code. Without it, I couldn’t show Jinja2 code using GitHub markdown

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="amzn-envelope.xsd">
  3. <Header>
  4. <DocumentVersion>1.01</DocumentVersion>
  5. <MerchantIdentifier></MerchantIdentifier>
  6. </Header>
  7. <MessageType>Product</MessageType>
  8. <PurgeAndReplace>false</PurgeAndReplace>
  9. \{\% for message in FeedMessages \%\}
  10. <Message>
  11. <MessageID>\{\{ loop.index \}\}</MessageID>
  12. <OperationType>PartialUpdate</OperationType>
  13. <Product>
  14. <SKU>\{\{ message.SKU \}\}</SKU>
  15. <DescriptionData>
  16. <Title>\{\{ message.Title \}\}</Title>
  17. </DescriptionData>
  18. </Product>
  19. </Message>
  20. \{\% endfor \%\}
  21. </AmazonEnvelope>

The Amazon MWS XML schema is defined in the Selling on Amazon Guide to XML pdf file and links embedded in the file. There are some subtle things that cause Amazon to reject the a submitted XML feed. For example:

  • There is nothing before the the XML declaration.
  • There is a space after the “utf-8” in the XML declaration

boto MWS API Call

The boto MWS package doesn’t have good document and even good code comments. We had to read the code to figure out the calling conventions. The use is not hard once we know where to look in the source code.

The API to submit a product feed are defined in boto.mws.connection module. An MWSConnection usually needs three keyword arguments: Merchant, awsaccesskeyid, and awssecretaccesskey. A connection object is created using the following code:

  1. MarketPlaceID = 'Your_Market_Place_ID'
  2. MerchantID = 'Your_Merchant_ID'
  3. AccessKeyID = 'Your_AccessKey_ID'
  4. SecretKey = 'Your_SecreteKey_ID'
  5. conn = connection.MWSConnection(
  6. aws_access_key_id=AccessKeyID,
  7. aws_secret_access_key=SecretKey,
  8. Merchant=MerchantID)

To change a product tile, we need to make three calls: the submit_feed call to submit the feed, the get_feed_submission_list call to find out the call processing status, the get_feed_submission_result call to find out the call processing result. Each call has different requirements. For example, thesubmit_feed has the following decorators:

  1. @requires(['FeedType'])
  2. @boolean_arguments('PurgeAndReplace')
  3. @http_body('FeedContent')
  4. @structured_lists('MarketplaceIdList.Id')
  5. @api_action('Feeds', 15, 120)

The above decorators specify the following call conventions:

  • It requires a ‘FeedType’ keyword argument
  • It has a boolean ‘PurgeAndReplace’ keyword argument
  • The HTTP request body is passed as the ‘FeedContent’ keyword argument
  • It is in ‘Feed’ section with a quota of 15 and restoration time of 120 seconds.

It seems there is no need to pass any request or header arguments to make a call. All needed is to provide the required keyword arguments. The following is the code to call submit_feed:

  1. feed = conn.submit_feed(
  2. FeedType='_POST_PRODUCT_DATA_',
  3. PurgeAndReplace=False,
  4. MarketplaceIdList=[MarketPlaceID],
  5. content_type='text/xml',
  6. FeedContent=feed_content
  7. )

Call Response

Though boto doesn’t generate request XML content, it parses an XML response into a Python object. A response XML message usually has two parts. For thesubmit_feed call, they are: and . The generated Python object has attributes that have one-to-one mapping to the XML response message. The attribute names can be found in Amazon MWS API document. For example, the Amazon SubmitFeed document describes the XML structure for the boto submit_feedmethod response. All attributes can be easily accessed as Python object attribute. All attribute values are of ‘UTF-8’ string type.

Complete Source Code

There are three files in this example. There are arranged in the following structure:

  1. boto_test\
  2. __init__.py
  3. connnection_test.py
  4. templates\
  5. product_feed_template.xml

The init.py is an empty file used to define a Python package. ‘productfeedtemplate.xml’ is the template described above. The following is the source code of ‘connection_test.py’.

  1. # -*- coding: utf-8 -*-
  2. from boto.mws import connection
  3. import time
  4. from jinja2 import Environment, PackageLoader
  5. # Amazon US MWS ID
  6. MarketPlaceID = 'ATVPDKIKX0DER'
  7. MerchantID = 'MID'
  8. AccessKeyID = 'AKID'
  9. SecretKey = 'SID'
  10. env = Environment(loader=PackageLoader('boto_test', 'templates'),
  11. trim_blocks=True,
  12. lstrip_blocks=True)
  13. template = env.get_template('product_feed_template.xml')
  14. class Message(object):
  15. def __init__(self, sku, title):
  16. self.SKU = sku
  17. self.Title = title
  18. feed_messages = [
  19. Message('SDK1', 'Title1'),
  20. Message('SDK2', 'Title2'),
  21. ]
  22. namespace = dict(MerchantId=MerchantID, FeedMessages=feed_messages)
  23. feed_content = template.render(namespace).encode('utf-8')
  24. conn = connection.MWSConnection(
  25. aws_access_key_id=AccessKeyID,
  26. aws_secret_access_key=SecretKey,
  27. Merchant=MerchantID)
  28. feed = conn.submit_feed(
  29. FeedType='_POST_PRODUCT_DATA_',
  30. PurgeAndReplace=False,
  31. MarketplaceIdList=[MarketPlaceID],
  32. content_type='text/xml',
  33. FeedContent=feed_content
  34. )
  35. feed_info = feed.SubmitFeedResult.FeedSubmissionInfo
  36. print 'Submitted product feed: ' + str(feed_info)
  37. while True:
  38. submission_list = conn.get_feed_submission_list(
  39. FeedSubmissionIdList=[feed_info.FeedSubmissionId]
  40. )
  41. info = submission_list.GetFeedSubmissionListResult.FeedSubmissionInfo[0]
  42. id = info.FeedSubmissionId
  43. status = info.FeedProcessingStatus
  44. print 'Submission Id: {}. Current status: {}'.format(id, status)
  45. if (status in ('_SUBMITTED_', '_IN_PROGRESS_', '_UNCONFIRMED_')):
  46. print 'Sleeping and check again....'
  47. time.sleep(60)
  48. elif (status == '_DONE_'):
  49. feedResult = conn.get_feed_submission_result(FeedSubmissionId=id)
  50. print feedResult
  51. break
  52. else:
  53. print "Submission processing error. Quit."
  54. break

转载自:http://www.mindissoftware.com/2014/10/25/boto-amazon-wms-example/

发表评论

表情:
评论列表 (有 0 条评论,16人围观)

还没有评论,来说两句吧...

相关阅读