sp_api_client.py 72 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335
  1. import clickhouse_connect
  2. import time
  3. import warnings
  4. warnings.filterwarnings('ignore')
  5. import numpy as np
  6. from pymysql import Timestamp
  7. from sp_api.util import throttle_retry, load_all_pages
  8. from sp_api.api import Orders,ListingsItems,Inventories,Reports,CatalogItems
  9. from sp_api.base import Marketplaces,ReportType,ProcessingStatus
  10. import pandas as pd
  11. import gzip
  12. from io import BytesIO,StringIO
  13. from datetime import datetime, timedelta,timezone
  14. import pytz
  15. import time
  16. from dateutil.parser import parse
  17. import pymysql
  18. from typing import List, Literal
  19. from random import shuffle
  20. from retry import retry
  21. import requests
  22. from urllib import request
  23. import json
  24. try:
  25. from ..settings import MYSQL_AUTH_CONF, MYSQL_DATA_CONF
  26. except:
  27. from sync_amz_data.sync_amz_data.settings import MYSQL_AUTH_CONF, MYSQL_DATA_CONF
  28. class SpApiRequest:
  29. def __init__(self, credentials,marketplace):
  30. self.credentials = credentials
  31. self.marketplace = marketplace
  32. @classmethod
  33. @retry(tries=3, delay=5, backoff=2, )
  34. def Token_auth(cls): # AUTH - mysql_connect_auth
  35. conn = pymysql.connect(**MYSQL_AUTH_CONF)
  36. return conn
  37. @classmethod
  38. @retry(tries=3, delay=5, backoff=2, )
  39. def Data_auth(cls): # DATA - mysql_connect_auth_lst
  40. conn = pymysql.connect(**MYSQL_DATA_CONF)
  41. return conn
  42. @classmethod
  43. @retry(tries=3, delay=5, backoff=2, )
  44. def LocalHost_Auth(cls): # local database-
  45. conn = pymysql.connect(user="huangyifan",
  46. password="123456",
  47. host="127.0.0.1",
  48. database="amz_sp_api",
  49. port=3306)
  50. return conn
  51. @staticmethod
  52. @retry(tries=3, delay=5, backoff=2, )
  53. def auth_info(): # get Auth-data from all of shops - 此连接获取refreshtoken供账户授权使用
  54. auth_conn = SpApiRequest.Token_auth()
  55. cursor = auth_conn.cursor()
  56. cursor.execute("select * from amazon_sp_report.amazon_sp_auth_info;")
  57. columns_name = [i[0] for i in cursor.description]
  58. rel = cursor.fetchall()
  59. df = pd.DataFrame(rel, columns=columns_name)
  60. return df
  61. @classmethod
  62. @retry(tries=3, delay=5, backoff=2, )
  63. def get_refreshtoken(cls): # accroding to differnt shop get diffrent refreshtoken - 获取授权后拿到refreshtoken
  64. df = cls.auth_info()
  65. refreshtoken_list = (df['refresh_token'].to_numpy().tolist())
  66. return refreshtoken_list
  67. @classmethod
  68. def get_catelog(cls,account_name,country=Marketplaces.US,asin=None): # active - 可以使用但未进行使用
  69. if country in [Marketplaces.US, Marketplaces.BR, Marketplaces.CA,Marketplaces.MX]:
  70. region = 'NA'
  71. elif country in [Marketplaces.DE,Marketplaces.AE, Marketplaces.BE, Marketplaces.PL,
  72. Marketplaces.EG,Marketplaces.ES, Marketplaces.GB, Marketplaces.IN, Marketplaces.IT,
  73. Marketplaces.NL, Marketplaces.SA, Marketplaces.SE, Marketplaces.TR,Marketplaces.UK,Marketplaces.FR,
  74. ]:
  75. region = 'EU'
  76. else:
  77. region = str(country)[-2:]
  78. df = cls.auth_info()
  79. try:
  80. refresh_token = df.query("account_name==@account_name and region==@region")['refresh_token'].values[0]
  81. except:
  82. print("请输入正确的account name与Marketplace")
  83. return '获取失败'
  84. cred = {
  85. 'refresh_token': refresh_token,
  86. 'lwa_app_id': 'amzn1.application-oa2-client.1f9d3d4747e14b22b4b598e54e6b922e', # 卖家中心里面开发者资料LWA凭证
  87. 'lwa_client_secret': 'amzn1.oa2-cs.v1.3af0f5649f5b8e151cd5bd25c10f2bf3113172485cd6ffc52ccc6a5e8512b490',
  88. 'aws_access_key': 'AKIARBAGHTGOZC7544GN',
  89. 'aws_secret_key': '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',
  90. 'role_arn': 'arn:aws:iam::070880041373:role/Amazon_SP_API_ROLE'
  91. }
  92. # cate_item = CatalogItems(credentials=cred, marketplace=country)
  93. # images_info = cate_item.get_catalog_item(asin=asin,**{"includedData":['images']})
  94. # print(images_info)
  95. # images = images_info.images[0].get('images')[0]['link']
  96. # title_info = cate_item.get_catalog_item(asin=asin)
  97. # print(title_info)
  98. # title = title_info.payload['summaries'][0]['itemName']
  99. cate_item = CatalogItems(credentials=cred, marketplace=country,version='2022-04-01')
  100. test_bundle = cate_item.get_catalog_item(asin=asin,**{"includedData":['salesRanks']})
  101. print(test_bundle)
  102. # return {'images':images,'title':title}
  103. @retry(tries=3, delay=5, backoff=2,)
  104. def create_report(self,**kwargs): # Main-CreateReport-Function - 创建报告请求
  105. reportType = kwargs['reportType']
  106. reportOptions =kwargs.get("reportOptions")
  107. dataStartTime = datetime.now().strftime("%Y-%m-%dT%H:%M:%S") if kwargs.get("dataStartTime") is None else kwargs.get("dataStartTime")+"T00:00:00"
  108. dataEndTime = datetime.now().strftime("%Y-%m-%dT%H:%M:%S") if kwargs.get("dataEndTime") is None else kwargs.get("dataEndTime")+"T23:59:59"
  109. report = Reports(credentials=self.credentials, marketplace=self.marketplace)
  110. rel = report.create_report(
  111. reportType=reportType,marketplaceIds=[kwargs['marketpalceids'] if kwargs.get('marketpalceids') is not None else self.marketplace.marketplace_id],
  112. reportOptions=reportOptions,dataStartTime=dataStartTime,dataEndTime=dataEndTime
  113. )
  114. reportId = rel.payload.get("reportId")
  115. # print(reportId)
  116. return reportId
  117. # @retry(tries=2, delay=3, backoff=2,)
  118. def decompression(self,reportId): # After-CreateReportFunc-simpleDeal - 根据获取到的报告id进行解压获取
  119. report = Reports(credentials=self.credentials, marketplace=self.marketplace)
  120. while True:
  121. reportId_info = report.get_report(reportId=reportId)
  122. # print(reportId_info.payload)
  123. print("please wait...")
  124. if reportId_info.payload.get("processingStatus")==ProcessingStatus.DONE:
  125. reportDocumentId = reportId_info.payload.get("reportDocumentId")
  126. rp_table = report.get_report_document(reportDocumentId=reportDocumentId,download=False)
  127. print(rp_table)
  128. if rp_table.payload.get('compressionAlgorithm') is not None and self.marketplace.marketplace_id not in ['A1VC38T7YXB528']:#
  129. df = pd.read_table(filepath_or_buffer=rp_table.payload['url'],compression={"method":'gzip'},encoding='iso-8859-1')
  130. return df
  131. elif rp_table.payload.get('compressionAlgorithm') is not None and self.marketplace.marketplace_id in ['A1VC38T7YXB528']:
  132. df = pd.read_table(filepath_or_buffer=rp_table.payload['url'], compression={"method": 'gzip'},
  133. encoding='Shift-JIS')
  134. # df.columns =
  135. return df
  136. elif rp_table.payload.get('compressionAlgorithm') is None and self.marketplace.marketplace_id not in ['A1VC38T7YXB528']:
  137. df = pd.read_table(rp_table.payload.get("url"),encoding='iso-8859-1')
  138. return df
  139. elif rp_table.payload.get('compressionAlgorithm') is None and self.marketplace.marketplace_id in ['A1VC38T7YXB528']:
  140. df = pd.read_table(rp_table.payload.get("url"),encoding='Shift-JIS')
  141. return df
  142. elif reportId_info.payload.get("processingStatus") in [ProcessingStatus.CANCELLED,ProcessingStatus.FATAL]:
  143. print(reportId_info)
  144. reportDocumentId = reportId_info.payload.get("reportDocumentId")
  145. rp_table = report.get_report_document(reportDocumentId=reportDocumentId, download=True)
  146. print("取消或失败",rp_table)
  147. return pd.DataFrame()
  148. time.sleep(15)
  149. print("please wait...")
  150. def decompression2(self,reportId): # After-CreateReportFunc-simpleDeal - 根据获取到的报告id进行解压获取
  151. report = Reports(credentials=self.credentials, marketplace=self.marketplace)
  152. while True:
  153. reportId_info = report.get_report(reportId=reportId)
  154. # print(reportId_info.payload)
  155. print("please wait...")
  156. if reportId_info.payload.get("processingStatus")==ProcessingStatus.DONE:
  157. reportDocumentId = reportId_info.payload.get("reportDocumentId")
  158. rp_table = report.get_report_document(reportDocumentId=reportDocumentId,download=False)
  159. print(rp_table)
  160. if rp_table.payload.get('compressionAlgorithm') is not None and self.marketplace.marketplace_id not in ['A1VC38T7YXB528']:#
  161. # df = pd.read_json(path_or_buf=rp_table.payload['url'],compression={"method":'gzip'},encoding='iso-8859-1')
  162. response = request.urlopen(rp_table.payload['url'])
  163. response.encoding='iso-8859-1'
  164. df = json.loads(response.read().decode())
  165. # pd.json_normalize()
  166. return df
  167. elif rp_table.payload.get('compressionAlgorithm') is not None and self.marketplace.marketplace_id in ['A1VC38T7YXB528']:
  168. df = pd.read_json(path_or_buf=rp_table.payload['url'], compression={"method": 'gzip'},
  169. encoding='Shift-JIS')
  170. # df.columns =
  171. return df
  172. elif rp_table.payload.get('compressionAlgorithm') is None and self.marketplace.marketplace_id not in ['A1VC38T7YXB528']:
  173. df = pd.read_json(path_or_buf=rp_table.payload.get("url"),encoding='iso-8859-1')
  174. return df
  175. elif rp_table.payload.get('compressionAlgorithm') is None and self.marketplace.marketplace_id in ['A1VC38T7YXB528']:
  176. df = pd.read_json(path_or_buf=rp_table.payload.get("url"),encoding='Shift-JIS')
  177. return df
  178. elif reportId_info.payload.get("processingStatus") in [ProcessingStatus.CANCELLED,ProcessingStatus.FATAL]:
  179. print(reportId_info)
  180. reportDocumentId = reportId_info.payload.get("reportDocumentId")
  181. rp_table = report.get_report_document(reportDocumentId=reportDocumentId, download=True)
  182. print("取消或失败",rp_table)
  183. return pd.DataFrame()
  184. time.sleep(15)
  185. print("please wait...")
  186. # def GET_MERCHANT_LISTINGS_ALL_DATA(self,limit=None): # Not be used
  187. # start = time.time()
  188. # para = {"reportType":ReportType.GET_MERCHANT_LISTINGS_ALL_DATA}
  189. # reportid = self.create_report(**para)
  190. # decom_df = self.decompression(reportid)
  191. # print("连接数据库")
  192. # conn = self.LocalHost_Auth()
  193. # print("连接成功")
  194. # cursor = conn.cursor()
  195. # timezone = "UTC" #pytz.timezone(self.timezone)
  196. # bondary_date = (datetime.now()).strftime("%Y-%m-%d") #+ timedelta(days=-28)
  197. # cursor.execute(f"""select * from amz_sp_api.productInfo where (mainImageUrl is not null and mainImageUrl not in ('', ' ')) and
  198. # (`seller-sku` not in ('',' ') and `seller-sku` is not null) and
  199. # `updateTime`>='{bondary_date}'""") #`seller-sku`,`updateTime`,`mainImageUrl`
  200. # col = [i[0] for i in cursor.description]
  201. # query_rel = cursor.fetchall()
  202. #
  203. # if len(query_rel)!=0:
  204. # print(query_rel[0])
  205. # df = pd.DataFrame(query_rel,columns=col)
  206. # listingid = df['listing-id'].to_numpy().tolist()
  207. # decom_df = decom_df.query("`listing-id` not in @listingid")
  208. # print("数据条数: ",len(decom_df))
  209. # # print(f"delete * from amz_sp_api.productInfo where `listing-id` not in {tuple(listingid)}")
  210. #
  211. # # conn.commit()
  212. #
  213. # if len(decom_df)==0:
  214. # return "Done"
  215. #
  216. # if limit != None:
  217. # decom_df = decom_df.iloc[:limit,:]
  218. # print("getting mainImageInfo...")
  219. # rowcount = 0
  220. # while rowcount < len(decom_df):
  221. # df_insert = decom_df.copy()
  222. # df_insert = df_insert.iloc[rowcount:rowcount + 200, :]
  223. #
  224. # df_insert = self.data_deal(df_insert)
  225. # list_df = df_insert.to_numpy().tolist()
  226. #
  227. # # print(list(conn.query("select * from amz_sp_api.orderReport")))
  228. # sql = f"""
  229. # insert into amz_sp_api.productInfo
  230. # values (%s,%s,%s,%s,%s,%s,%s, %s,%s,%s,%s,%s,%s,%s, %s,%s,%s,%s,%s,%s,%s, %s,%s,%s,%s,%s,%s,%s,%s)
  231. # """ #ok
  232. # # print(sql)
  233. # conn = self.LocalHost_Auth()
  234. # cursor = conn.cursor()
  235. # try:
  236. # conn.begin()
  237. # cursor.executemany(sql, list_df)
  238. # conn.commit()
  239. # print("插入中...")
  240. # insert_listingid = df_insert['listing-id'].to_numpy().tolist()
  241. # cursor.execute(f"delete from amz_sp_api.productInfo where `listing-id` not in {tuple(insert_listingid)} and `updateTime`<'{bondary_date}'")
  242. # conn.commit()
  243. # rowcount += 200
  244. # except Exception as e:
  245. # conn.rollback()
  246. # print(e)
  247. # try:
  248. # conn = self.LocalHost_Auth()
  249. # cursor = conn.cursor()
  250. # conn.begin()
  251. # cursor.executemany(sql, list_df)
  252. # conn.commit()
  253. # insert_listingid = df_insert['listing-id'].to_numpy().tolist()
  254. # cursor.execute(f"delete from amz_sp_api.productInfo where `listing-id` not in {tuple(insert_listingid)} and `updateTime`<'{bondary_date}'")
  255. # conn.commit()
  256. # except Exception as e:
  257. # conn.rollback()
  258. # print(e)
  259. # break
  260. # # break
  261. # conn.close()
  262. # print("全部完成")
  263. # end =time.time()
  264. # print("duration:",end-start)
  265. # return decom_df
  266. # def data_deal(self, decom_df, seller_id): # desprecated
  267. # decom_df['mainImageUrl'] = decom_df['seller-sku'].map(lambda x: self.get_mainImage_url(x))
  268. # url_columns = [i for i in decom_df.columns if "url" in i.lower()]
  269. # if len(url_columns) > 0:
  270. # decom_df[url_columns] = decom_df[url_columns].astype("string")
  271. # asin_columns = [i for i in decom_df.columns if 'asin' in i.lower()]
  272. # if len(asin_columns) > 0:
  273. # decom_df[asin_columns] = decom_df[asin_columns].astype("string")
  274. # if 'pending-quantity' in decom_df.columns:
  275. # decom_df['pending-quantity'] = decom_df['pending-quantity'].map(
  276. # lambda x: 0 if pd.isna(x) or np.isinf(x) else x).astype("int32")
  277. # deletecolumns = [i for i in decom_df.columns if 'zshop' in i.lower()]
  278. # decom_df.drop(columns=deletecolumns, inplace=True)
  279. # if 'quantity' in decom_df.columns:
  280. # decom_df['quantity'] = decom_df['quantity'].map(lambda x: 0 if pd.isna(x) or np.isinf(x) else x).astype(
  281. # "int32")
  282. # decom_df['opendate_date'] = decom_df['open-date'].map(lambda x: self.datetime_deal(x))
  283. # if 'add-delete' in decom_df.columns:
  284. # decom_df['add-delete'] = decom_df['add-delete'].astype('string', errors='ignore')
  285. # if 'will-ship-internationally' in decom_df.columns:
  286. # decom_df['will-ship-internationally'] = decom_df['will-ship-internationally'].astype('string',
  287. # errors='ignore')
  288. # if 'expedited-shipping' in decom_df.columns:
  289. # decom_df['expedited-shipping'] = decom_df['expedited-shipping'].astype('string', errors='ignore')
  290. # decom_df['updateTime'] = datetime.now()
  291. # decom_df['timezone'] = "UTC"
  292. # decom_df['seller_id'] = seller_id
  293. # #
  294. # decom_df['item-description'] = decom_df['item-description'].str.slice(0, 500)
  295. # decom_df[decom_df.select_dtypes(float).columns] = decom_df[decom_df.select_dtypes(float).columns].fillna(0.0)
  296. # decom_df[decom_df.select_dtypes(int).columns] = decom_df[decom_df.select_dtypes(int).columns].fillna(0)
  297. # decom_df[decom_df.select_dtypes(datetime).columns] = decom_df[decom_df.select_dtypes(datetime).columns].astype(
  298. # 'string')
  299. # decom_df.fillna('', inplace=True)
  300. # # print(decom_df.info())
  301. # return decom_df
  302. def fba_inventorySQL(self,conn,seller_id):
  303. cursor = conn.cursor()
  304. # 执行语句
  305. cursor.execute(f""" select asin,sku,seller_id,marketplace_id,country_code,quantity,fulfillment_channel
  306. from
  307. (select asin,sku,seller_id,marketplace_id,country_code,quantity,fulfillment_channel,
  308. ROW_NUMBER() over(partition by asin,sku,seller_id,marketplace_id,country_code order by update_datetime desc) as row_
  309. from asj_ads.seller_listings) as t
  310. where row_=1 and seller_id='{seller_id}' and marketplace_id='{self.marketplace.marketplace_id}'
  311. and fulfillment_channel='FBA'
  312. """)#,quantity
  313. query_ = cursor.fetchall()
  314. col_name = [i[0] for i in cursor.description]
  315. df_datatable = pd.DataFrame(query_, columns=col_name)
  316. df_datatable.columns = ['asin_', 'sku_', 'seller_id_', 'marketplace_id_', 'country_code_',
  317. 'afn-fulfillable-quantity']
  318. return df_datatable
  319. def get_fba_neccessary_segment(self,conn,seller_id):
  320. para = {"reportType": ReportType.GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA}
  321. reportid = self.create_report(**para)
  322. df = self.decompression(reportid)
  323. if len(df) == 0:
  324. return self.fba_inventorySQL(conn, seller_id)
  325. # pd.DataFrame()
  326. df['seller_id'] = seller_id
  327. df['marketplace_id'] = self.marketplace.marketplace_id
  328. df['country_code'] = str(self.marketplace)[-2:]
  329. df_rel = df.query("condition=='New'")
  330. df_rel = df_rel.groupby(['asin', 'sku', 'seller_id', 'marketplace_id', 'country_code']).agg(
  331. {'afn-fulfillable-quantity': sum}).reset_index()
  332. df_rel.columns = ['asin_', 'sku_', 'seller_id_', 'marketplace_id_', 'country_code_', 'afn-fulfillable-quantity']
  333. print(f"{seller_id}_{str(self.marketplace)[-2:]}_FBA_Inventory_OK")
  334. return df_rel
  335. def GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA(self,refresh_token,conn=None,seller_id=None,days=-1,**kwargs): # FBA库存信息
  336. try:
  337. return self.get_fba_neccessary_segment(conn,seller_id)
  338. except Exception as e:
  339. print(e)
  340. try:
  341. time.sleep(15)
  342. return self.get_fba_neccessary_segment(conn, seller_id)
  343. except Exception as e:
  344. print(e)
  345. df_rel = pd.DataFrame(columns=['asin_', 'sku_', 'seller_id_', 'marketplace_id_', 'country_code_','afn-fulfillable-quantity'])
  346. return df_rel
  347. def GET_FLAT_FILE_OPEN_LISTINGS_DATA(self,refresh_token,conn=None,seller_id=None,days=-1): # To datatable asj_ads.seller_listings- listing信息,包括fbm库存
  348. para = {"reportType": ReportType.GET_MERCHANT_LISTINGS_ALL_DATA}
  349. reportid = self.create_report(**para)
  350. df = self.decompression(reportid)
  351. if len(df)>0:
  352. if self.marketplace.marketplace_id =='A1VC38T7YXB528': # 该站点的数据列有所不同
  353. df.columns = ['item-name','listing-id','seller-sku','price','quantity','open-date','product-id-type','item-description',
  354. 'item-condition','overseas shipping','fast shipping','asin1','stock_number','fulfillment-channel','merchant-shipping-group','status']
  355. df['seller_id'] = seller_id
  356. df['marketplace_id'] = self.marketplace.marketplace_id
  357. df['country_code'] = str(self.marketplace)[-2:]
  358. if 'fulfilment-channel' in df.columns: # 判断是否存在’fulfilment‘字段(1个film),如果存在则添加一个’fulfillment‘字段(两个fillm)
  359. df['fulfillment-channel'] = df['fulfilment-channel'].copy()
  360. # 如果是amazon,则字段改为FBA
  361. df['fulfillment_channel'] = df['fulfillment-channel'].map(lambda x:"FBA" if not pd.isna(x) and len(x)>0 and str(x)[1:4] in "AMAZON" else x)
  362. # 如果是DEFAULT,则字段该为FBM
  363. df['fulfillment_channel'] = df['fulfillment_channel'].map(lambda x: "FBM" if not pd.isna(x) and len(x)>0 and str(x)[1:4] in "DEFAULT" else x)
  364. if 'asin1' not in df.columns: # 如果不存在asin1,则添加asin1字段
  365. df['asin1'] = ''
  366. if 'product-id' not in df.columns: # 如果不存在product-id,则添加product-id字段
  367. df['product-id'] = ''
  368. # 空值处理
  369. # df['quantity'] = df['quantity'].fillna(0).astype('int64',errors='ignore')
  370. df['quantity'] = df['quantity'].map(lambda x:0 if pd.isna(x)==True else int(x))
  371. #库存数量格式处理
  372. df['quantity'] = df['quantity'].astype('int64')
  373. # 填充NA值
  374. df[['listing-id','seller_id','asin1','seller-sku','country_code','marketplace_id','fulfillment_channel','status','product-id']] = df[['listing-id','seller_id','asin1','seller-sku','country_code','marketplace_id','fulfillment_channel','status','product-id']].fillna('').astype('string',errors='ignore')
  375. # 为NA的价格填充0
  376. df['price'] = df['price'].fillna(0.0).astype('float64',errors='ignore')
  377. df.fillna('',inplace=True)
  378. # 时间处理
  379. df['opendate'] = df['open-date'].map(lambda x: self.datetime_deal(x))
  380. df['update_datetime'] = datetime.now(pytz.UTC).date()
  381. # 保留列
  382. origin_columns = ['listing-id','seller_id',
  383. 'asin1','seller-sku','title','image_link','country_code',
  384. 'marketplace_id','quantity','fulfillment_channel',
  385. 'price','opendate','status','update_datetime','product-id','product-id-type','modifier'
  386. ]
  387. # 连接数据库
  388. conn = SpApiRequest.Data_auth()
  389. cursor = conn.cursor()
  390. # 执行语句,筛选出asin不为空并且product_id不为空的两列唯一数据。
  391. cursor.execute("""select product_id,asin from (select * from asj_ads.seller_listings where asin is not null
  392. and asin<>'' and product_id is not null and product_id <>'') t1 group by product_id,asin""")
  393. query_ = cursor.fetchall()
  394. col_name = [i[0] for i in cursor.description]
  395. df_datatable = pd.DataFrame(query_, columns=col_name)
  396. # 合并数据,左表为新下载的数据,右表为数据库查询的数据
  397. merged_df = df.merge(df_datatable[['product_id','asin']],how='left',left_on='product-id',right_on='product_id')
  398. # 功能函数,提取asin
  399. def func_(asin,asin1,product_id,cred,market_p,seller_id,sku):
  400. if 'B0' in str(product_id)[:3]:
  401. return str(product_id)
  402. if (pd.isna(asin1) or asin1=='') and (pd.isna(asin)==False and asin !=''):
  403. if 'B0' in asin[:3]:
  404. return asin
  405. elif (pd.isna(asin1)==False and asin1!=''):
  406. if 'B0' in asin1[:3]:
  407. return asin1
  408. listingClient = ListingsItems(credentials=cred, marketplace=market_p)
  409. try:
  410. r1 = listingClient.get_listings_item(sellerId=seller_id, sku=sku)
  411. print(r1.payload)
  412. asin = r1.payload.get("summaries")[0].get("asin")
  413. return asin
  414. except Exception as e:
  415. print("获取图片url过程错误重试, 错误message: ", e)
  416. time.sleep(3)
  417. r1 = listingClient.get_listings_item(sellerId=seller_id, sku=sku)
  418. print(r1.payload)
  419. asin = r1.payload.get("summaries")[0].get("asin")
  420. return asin
  421. # 应用处理函数,返回asin
  422. merged_df['asin1'] = merged_df.apply(lambda x:func_(x['asin'],x['asin1'],x['product-id'],self.credentials,self.marketplace,seller_id,x['seller-sku']),axis=1) #x['asin'] if pd.isna(x['asin1']) or x['asin1']=='' else x['asin1']
  423. merged_df['image_link'] = ''
  424. # 暂时将refresh_token添加在title列,后面获取asin详细数据时需要用到
  425. merged_df['title'] = refresh_token
  426. merged_df['modifier'] = ''
  427. # 填充NA值
  428. merged_df.fillna('',inplace=True)
  429. df1 = merged_df.copy()
  430. # df1.to_csv("第一次合并处理后.csv")
  431. #获取FBA库存数据
  432. df_fbaInventory = self.GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA(refresh_token, conn, seller_id, days)
  433. # 合并fba库存数据
  434. if len(df_fbaInventory)>0:
  435. df1 = df1.merge(df_fbaInventory,how='left',left_on=['asin1','seller-sku','seller_id','marketplace_id','country_code'],right_on=['asin_','sku_','seller_id_','marketplace_id_','country_code_'])
  436. df1['quantity'] = df1.apply(lambda x:x['afn-fulfillable-quantity'] if x['fulfillment_channel']=='FBA' or pd.isna(['afn-fulfillable-quantity'])==False else x['quantity'],axis=1)
  437. df1['quantity'] = df1['quantity'].map(lambda x:0 if pd.isna(x) else int(x))
  438. df1['quantity'] = df1['quantity'].fillna(0)
  439. # df1.to_csv("第二次合并处理后的数据.csv")
  440. # 判断更新数据
  441. update_df = self.update_data(df1,seller_id,str(self.marketplace)[-2:],conn)
  442. if len(update_df)==0:
  443. return '无更新数据插入'
  444. # update_df['country_code'] = update_df['country_code'].map({"GB":"UK"})
  445. conn = SpApiRequest.Data_auth()
  446. cursor = conn.cursor()
  447. # 插入更新的数据
  448. try:
  449. insertsql = """insert into
  450. asj_ads.seller_listings(listing_id,seller_id,asin,sku,title,image_link,country_code,marketplace_id,quantity,
  451. fulfillment_channel,price,launch_datetime,status,update_datetime,product_id,product_id_type,modifier)
  452. values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"""
  453. conn.begin()
  454. cursor.executemany(insertsql,tuple(update_df[origin_columns].to_numpy().tolist()))
  455. conn.commit()
  456. print("插入完成")
  457. delete_sql = f"""delete from asj_ads.seller_listings where update_datetime<'{(datetime.today()+timedelta(days=-3)).date().isoformat()}'"""
  458. cursor.execute(delete_sql)
  459. conn.commit()
  460. return '插入完成'
  461. except Exception as e:
  462. print("插入错误:",e)
  463. conn.rollback()
  464. return '出错回滚'
  465. return ''
  466. # def get_listing_info(self, sku,seller_id): # desprecated
  467. # listingClient = ListingsItems(credentials=self.credentials, marketplace=self.marketplace)
  468. # try:
  469. # r1 = listingClient.get_listings_item(sellerId=seller_id, sku=sku)
  470. # # print(r1.payload)
  471. # json_content = r1.payload.get("summaries")[0]
  472. # item_name = json_content.get("itemName")
  473. # item_name ='###' if item_name==None else item_name
  474. # img = json_content.get("mainImage")
  475. # img_url = '###' if img is None else img.get("link")
  476. # return str(img_url)+"-----"+ str(item_name)
  477. # except Exception as e:
  478. # try:
  479. # print("获取图片url过程错误重试, 错误message: ",e)
  480. # time.sleep(3)
  481. # r1 = listingClient.get_listings_item(sellerId=seller_id, sku=sku)
  482. # print(r1.payload)
  483. # json_content = r1.payload.get("summaries")[0]
  484. #
  485. # item_name = json_content.get("itemName")
  486. # item_name = '###' if item_name == None else item_name
  487. # img = json_content.get("mainImage")
  488. # img_url = '###' if img is None else img.get("link")
  489. # return str(img_url)+"-----"+ str(item_name)
  490. # except Exception as e:
  491. # print(e)
  492. # return "###-----###"
  493. def datetime_deal(self,timestring): # used in GET_FLAT_FILE_OPEN_LISTINGS_DATA, time deal -时间处理函数
  494. timezone_ = {"AEST":"Australia/Sydney","AEDT":"Australia/Sydney","PST":"America/Los_Angeles",
  495. "PDT":"America/Los_Angeles","CST":"America/Chicago","CDT":"America/Chicago",
  496. "MET":"MET","MEST":"MET","BST":"Europe/London","GMT":"GMT","CET":"CET",
  497. "CEST":"CET","JST":"Asia/Tokyo","BRT":"America/Sao_Paulo"}
  498. date_list = str.split(timestring,sep = ' ')
  499. if len(date_list)<3:
  500. try:
  501. return datetime.strptime(date_list[0],"%Y-%m-%d")
  502. except:
  503. try:
  504. return datetime.strptime(date_list[0], "%Y/%m/%d")
  505. except:
  506. try:
  507. return datetime.strptime(date_list[0], "%d/%m/%Y")
  508. except Exception as e:
  509. print(e)
  510. return datetime(1999, 12, 31, 0, 0, 0)
  511. try:
  512. time_date = datetime.strptime(date_list[0]+date_list[1],"%Y-%m-%d%H:%M:%S")
  513. timezone = pytz.timezone(timezone_[date_list[2]])
  514. time_ = timezone.localize(time_date)
  515. return time_.astimezone(pytz.UTC)
  516. except:
  517. try:
  518. time_date = datetime.strptime(date_list[0] + date_list[1], "%d/%m/%Y%H:%M:%S")
  519. timezone = pytz.timezone(timezone_[date_list[2]])
  520. time_ = timezone.localize(time_date)
  521. return time_.astimezone(pytz.UTC)
  522. except :
  523. try:
  524. time_date = datetime.strptime(date_list[0] + date_list[1], "%Y/%m/%d%H:%M:%S")
  525. timezone = pytz.timezone(timezone_[date_list[2]])
  526. time_ = timezone.localize(time_date)
  527. return time_.astimezone(pytz.UTC)
  528. except Exception as e1:
  529. print(e1)
  530. return datetime(1999,12,31,0,0,0)
  531. def update_data(self,df,seller_id,country_code,conn): # used in GET_FLAT_FILE_OPEN_LISTINGS_DATA, data compare
  532. conn = SpApiRequest.Data_auth()
  533. cursor = conn.cursor()
  534. columns = ['listing-id', 'seller_id',
  535. 'asin1', 'seller-sku', 'title', 'image_link', 'country_code',
  536. 'marketplace_id', 'quantity', 'fulfillment_channel',
  537. 'price', 'opendate', 'status', 'update_datetime', 'product-id', 'product-id-type','modifier'
  538. ]
  539. if country_code=='GB':
  540. country_code="UK"
  541. df['country_code'] = "UK"
  542. df_data = pd.DataFrame(columns=columns)
  543. delete_list = []
  544. marketplace_id = self.marketplace.marketplace_id
  545. try:
  546. cursor.execute(f"""select * from
  547. asj_ads.seller_listings where seller_id='{seller_id}' and marketplace_id='{marketplace_id}'""")
  548. col = [i[0] for i in cursor.description]
  549. query_rel = cursor.fetchall()
  550. df_rel = pd.DataFrame(query_rel, columns=col)
  551. # df_rel.to_csv("数据库数据.csv")
  552. #数据库数据
  553. df_rel['quantity'] = df_rel['quantity'].fillna(0).astype('int64')
  554. df_rel['price'] = df_rel['price'].fillna(0.0).astype('float64')
  555. df_rel['product_id_type'] = df_rel['product_id_type'].astype('int64')
  556. # 新数据
  557. df['update_datetime'] =df['update_datetime'].astype('datetime64[ns]')
  558. df['quantity'] = df['quantity'].fillna(0).astype('int64')
  559. df['price']= df['price'].fillna(0.0).astype('float64')
  560. row = 0
  561. while row < len(df):
  562. temp_df = df.iloc[row, :]
  563. temp_d = df.iloc[row:row+1, :]
  564. listing_id = temp_df['listing-id']
  565. asin = temp_df['asin1']
  566. sku = temp_df['seller-sku']
  567. quantity = temp_df['quantity']
  568. fulfillment_channel = temp_df['fulfillment_channel']
  569. price = temp_df['price']
  570. product_id = temp_df['product-id']
  571. title = temp_df['title']
  572. imageurl = temp_df['image_link']
  573. modifier = temp_df['modifier']
  574. temp = df_rel.query("""listing_id==@listing_id and asin==@asin and sku==@sku and quantity==@quantity and fulfillment_channel==@fulfillment_channel and price==@price and product_id==@product_id and country_code==@country_code and seller_id==@seller_id and title==@title and image_link==@imageurl and modifier==@modifier""")
  575. # print("需要关注数据(是否异常):",len(temp),temp.to_numpy().tolist()) if len(temp)>1 else 1
  576. if len(temp)>1:
  577. # temp = temp.head(1).to_numpy().tolist()
  578. df_data = pd.concat((df_data,temp_d),ignore_index=True) #df_data.append(temp_df, ignore_index=True)
  579. delete_list.append((seller_id, marketplace_id, sku, listing_id, product_id))
  580. # print(len(temp))
  581. elif len(temp)==0:
  582. df_data = pd.concat((df_data,temp_d),ignore_index=True)
  583. delete_list.append((seller_id,marketplace_id,sku,listing_id,product_id))
  584. row += 1
  585. print("判断不同数据条数",len(delete_list))
  586. print("预计更新数据条数",len(df_data))
  587. try:
  588. # print(tuple(delete_list))
  589. if len(delete_list)>0:
  590. query = f"""delete from asj_ads.seller_listings
  591. where (seller_id,marketplace_id,sku,listing_id,product_id) in %s""" #where (seller_id,country_code) in %s"""
  592. cursor.execute(query,(delete_list,))
  593. conn.commit()
  594. # print(delete_list)
  595. print("进行中...")
  596. except Exception as e:
  597. print(e)
  598. conn.rollback()
  599. return df_data
  600. except Exception as e:
  601. print("错误:", e)
  602. return df
  603. def GET_FLAT_FILE_RETURNS_DATA_BY_RETURN_DATE(self,seller_id,days=-2): # not be used,退货报告,空数据
  604. shopReportday = (datetime.now() + timedelta(days=days)).strftime("%Y-%m-%d")
  605. # print(shopReportday)
  606. para = {"reportType": ReportType.GET_SELLER_FEEDBACK_DATA,
  607. "dataStartTime": shopReportday, "dataEndTime": shopReportday,
  608. }
  609. reportid = self.create_report(**para) # {"ShowSalesChannel":"true"}
  610. decom_df = self.decompression(reportid)
  611. print(decom_df)
  612. # print(decom_df.columns)
  613. def GET_SALES_AND_TRAFFIC_REPORT(self, refresh_token,seller_id,days=-2,**kwargs): # To datatable asj_ads.SalesAndTrafficByAsin,销售流量表
  614. # ,level:Literal["PARENT","CHILD","SKU"]="PARENT")
  615. level = "PARENT" if len(kwargs.get("level"))==0 else kwargs.get("level")
  616. countryCode = None if kwargs.get("countryCode")==None else kwargs.get("countryCode")
  617. # print(level)
  618. shopReportday = (datetime.now() + timedelta(days=days)).strftime("%Y-%m-%d")
  619. print(shopReportday,countryCode,seller_id)
  620. try:
  621. conn = self.Data_auth()
  622. cursor = conn.cursor()
  623. except:
  624. time.sleep(5)
  625. conn = self.Data_auth()
  626. cursor = conn.cursor()
  627. if level == 'SKU':
  628. query_judge = f"""select count(*) from asj_ads.SalesAndTrafficByAsin where seller_id='{seller_id}' and data_date='{shopReportday}' and countryCode='{countryCode}' and childAsin is not Null and sku is not Null"""
  629. elif level == 'CHILD':
  630. query_judge = f"""select count(*) from asj_ads.SalesAndTrafficByAsin where seller_id='{seller_id}' and data_date='{shopReportday}' and countryCode='{countryCode}' and sku is null and childAsin is not null"""
  631. elif level == 'PARENT':
  632. query_judge = f"""select count(*) from asj_ads.SalesAndTrafficByAsin where seller_id='{seller_id}' and data_date='{shopReportday}' and countryCode='{countryCode}' and sku is null and childAsin is null"""
  633. else:
  634. return ''
  635. print(query_judge)
  636. cursor.execute(query_judge)
  637. rel = cursor.fetchall()
  638. # print()
  639. if rel[0][0]!=0:
  640. return '已存在'
  641. # print(shopReportday)
  642. para = {"reportType": ReportType.GET_SALES_AND_TRAFFIC_REPORT,
  643. "dataStartTime": shopReportday, "dataEndTime": shopReportday,
  644. "reportOptions":{"dateGranularity":"DAY","asinGranularity":level}
  645. }
  646. reportid = self.create_report(**para) # {"ShowSalesChannel":"true"}
  647. decom_df = self.decompression(reportid)
  648. # print(decom_df.columns[0])
  649. data_rel = self.sales_traffic_datadeal(decom_df.columns[0],seller_id,countryCode)
  650. try:
  651. conn = self.Data_auth()
  652. cursor = conn.cursor()
  653. except:
  654. time.sleep(5)
  655. conn = self.Data_auth()
  656. cursor = conn.cursor()
  657. # print(list(conn.query("select * from amz_sp_api.orderReport")))
  658. sql = f"""
  659. insert into asj_ads.SalesAndTrafficByAsin(data_date,data_marketpalceId,parent_asin,
  660. childAsin,sku,sBA_unitsOrdered,sBA_unitsOrderedB2B,sBA_amount,
  661. currencyCode,totalOrderItems,totalOrderItemsB2B,tBA_browserSessions,
  662. tBA_browserSessionsB2B,tBA_mobileAppSessions,tBA_mobileAppSessionsB2B,
  663. tBA_sessions,tBA_sessionsB2B,tBA_browserSessionPercentage,
  664. tBA_browserSessionPercentageB2B,tBA_mobileAppSessionPercentage,
  665. tBA_mobileAppSessionPercentageB2B,tBA_sessionPercentage,
  666. tBA_sessionPercentageB2B,tBA_browserPageViews,tBA_browserPageViewsB2B,
  667. tBA_mobileAppPageViews,tBA_mobileAppPageViewsB2B,tBA_pageViews,
  668. tBA_pageViewsB2B,tBA_browserPageViewsPercentage,tBA_browserPageViewsPercentageB2B,
  669. tBA_mobileAppPageViewsPercentage,tBA_mobileAppPageViewsPercentageB2B,
  670. tBA_pageViewsPercentage,tBA_pageViewsPercentageB2B,tBA_buyBoxPercentage,
  671. tBA_buyBoxPercentageB2B,tBA_unitSessionPercentage,tBA_unitSessionPercentageB2B,seller_id,countryCode)
  672. values (%s,%s,%s,%s,%s,%s,%s, %s,%s,%s,%s,%s,%s,%s, %s,%s,%s,%s,%s,%s,%s, %s,%s,%s,%s,%s,%s,%s, %s,%s,%s,%s,%s,%s,%s, %s,%s,%s,%s,%s,%s)
  673. """ # ok
  674. try:
  675. # TODO
  676. conn.begin()
  677. cursor.executemany(sql, data_rel)
  678. conn.commit()
  679. print("插入完成")
  680. conn.close()
  681. time.sleep(1)
  682. except Exception as e:
  683. conn.rollback()
  684. print(e)
  685. def sales_traffic_datadeal(self,data,seller_id,countryCode): # used in GET_SALES_AND_TRAFFIC_REPORT
  686. data = eval(data)
  687. if len(data['salesAndTrafficByAsin'])==0:
  688. return []
  689. data_list = []
  690. data_date = data["reportSpecification"]["dataEndTime"]
  691. data_marketpalceId = data["reportSpecification"]["marketplaceIds"][0]
  692. # print(data_marketpalceId)
  693. for single_item in data["salesAndTrafficByAsin"]:
  694. # print(single_item)
  695. parent_asin = single_item.get("parentAsin")
  696. childAsin = single_item.get("childAsin")
  697. sku = single_item.get("sku")
  698. salesByAsin = single_item.get("salesByAsin")
  699. # if salesByAsin is not None:
  700. sBA_unitsOrdered = salesByAsin.get("unitsOrdered") if salesByAsin is not None else ''
  701. sBA_unitsOrderedB2B = salesByAsin.get("unitsOrderedB2B") if salesByAsin is not None else ''
  702. orderedProductSales = salesByAsin.get("orderedProductSales")
  703. sBA_amount = orderedProductSales.get("amount") if orderedProductSales is not None else ''
  704. currencyCode = orderedProductSales.get("currencyCode") if orderedProductSales is not None else ''
  705. orderedProductSalesB2B = salesByAsin.get("orderedProductSalesB2B") if salesByAsin is not None else None
  706. # if orderedProductSalesB2B is not None:
  707. oPS_amount = orderedProductSalesB2B.get("amount") if orderedProductSalesB2B is not None else ''
  708. totalOrderItems = salesByAsin.get("totalOrderItems") if salesByAsin is not None else ''
  709. totalOrderItemsB2B = salesByAsin.get("totalOrderItemsB2B") if salesByAsin is not None else ''
  710. trafficByAsin = single_item.get("trafficByAsin")
  711. # if trafficByAsin is not None:
  712. tBA_browserSessions = trafficByAsin.get("browserSessions") if trafficByAsin is not None else ''
  713. tBA_browserSessionsB2B = trafficByAsin.get("browserSessionsB2B") if trafficByAsin is not None else ''
  714. tBA_mobileAppSessions = trafficByAsin.get("mobileAppSessions") if trafficByAsin is not None else ''
  715. tBA_mobileAppSessionsB2B = trafficByAsin.get("mobileAppSessionsB2B") if trafficByAsin is not None else ''
  716. tBA_sessions = trafficByAsin.get("sessions") if trafficByAsin is not None else ''
  717. tBA_sessionsB2B = trafficByAsin.get("sessionsB2B") if trafficByAsin is not None else ''
  718. tBA_browserSessionPercentage = trafficByAsin.get("browserSessionPercentage") if trafficByAsin is not None else ''
  719. tBA_browserSessionPercentageB2B = trafficByAsin.get("browserSessionPercentageB2B") if trafficByAsin is not None else ''
  720. tBA_mobileAppSessionPercentage = trafficByAsin.get("mobileAppSessionPercentage") if trafficByAsin is not None else ''
  721. tBA_mobileAppSessionPercentageB2B = trafficByAsin.get("mobileAppSessionPercentageB2B") if trafficByAsin is not None else ''
  722. tBA_sessionPercentage = trafficByAsin.get("sessionPercentage") if trafficByAsin is not None else ''
  723. tBA_sessionPercentageB2B = trafficByAsin.get("sessionPercentageB2B") if trafficByAsin is not None else ''
  724. tBA_browserPageViews = trafficByAsin.get("browserPageViews") if trafficByAsin is not None else ''
  725. tBA_browserPageViewsB2B = trafficByAsin.get("browserPageViewsB2B") if trafficByAsin is not None else ''
  726. tBA_mobileAppPageViews = trafficByAsin.get("mobileAppPageViews") if trafficByAsin is not None else ''
  727. tBA_mobileAppPageViewsB2B = trafficByAsin.get("mobileAppPageViewsB2B") if trafficByAsin is not None else ''
  728. tBA_pageViews = trafficByAsin.get("pageViews") if trafficByAsin is not None else ''
  729. tBA_pageViewsB2B = trafficByAsin.get("pageViewsB2B") if trafficByAsin is not None else ''
  730. tBA_browserPageViewsPercentage = trafficByAsin.get("browserPageViewsPercentage") if trafficByAsin is not None else ''
  731. tBA_browserPageViewsPercentageB2B = trafficByAsin.get("browserPageViewsPercentageB2B") if trafficByAsin is not None else ''
  732. tBA_mobileAppPageViewsPercentage = trafficByAsin.get("mobileAppPageViewsPercentage") if trafficByAsin is not None else ''
  733. tBA_mobileAppPageViewsPercentageB2B = trafficByAsin.get("mobileAppPageViewsPercentageB2B") if trafficByAsin is not None else ''
  734. tBA_pageViewsPercentage = trafficByAsin.get("pageViewsPercentage") if trafficByAsin is not None else ''
  735. tBA_pageViewsPercentageB2B = trafficByAsin.get("pageViewsPercentageB2B") if trafficByAsin is not None else ''
  736. tBA_buyBoxPercentage = trafficByAsin.get("buyBoxPercentage") if trafficByAsin is not None else ''
  737. tBA_buyBoxPercentageB2B = trafficByAsin.get("buyBoxPercentageB2B") if trafficByAsin is not None else ''
  738. tBA_unitSessionPercentage = trafficByAsin.get("unitSessionPercentage") if trafficByAsin is not None else ''
  739. tBA_unitSessionPercentageB2B = trafficByAsin.get("unitSessionPercentageB2B") if trafficByAsin is not None else ''
  740. data_list.append([data_date,data_marketpalceId,parent_asin,
  741. childAsin,sku,sBA_unitsOrdered,sBA_unitsOrderedB2B,sBA_amount,
  742. currencyCode,totalOrderItems,totalOrderItemsB2B,tBA_browserSessions,
  743. tBA_browserSessionsB2B,tBA_mobileAppSessions,tBA_mobileAppSessionsB2B,
  744. tBA_sessions,tBA_sessionsB2B,tBA_browserSessionPercentage,
  745. tBA_browserSessionPercentageB2B,tBA_mobileAppSessionPercentage,
  746. tBA_mobileAppSessionPercentageB2B,tBA_sessionPercentage,
  747. tBA_sessionPercentageB2B,tBA_browserPageViews,tBA_browserPageViewsB2B,
  748. tBA_mobileAppPageViews,tBA_mobileAppPageViewsB2B,tBA_pageViews,
  749. tBA_pageViewsB2B,tBA_browserPageViewsPercentage,tBA_browserPageViewsPercentageB2B,
  750. tBA_mobileAppPageViewsPercentage,tBA_mobileAppPageViewsPercentageB2B,
  751. tBA_pageViewsPercentage,tBA_pageViewsPercentageB2B,tBA_buyBoxPercentage,
  752. tBA_buyBoxPercentageB2B,tBA_unitSessionPercentage,tBA_unitSessionPercentageB2B,seller_id,countryCode
  753. ])
  754. # print(data_list)
  755. return data_list
  756. def GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE_GENERAL(self, refresh_token,seller_id,days=-1,**kwargs): # To datatable asj_ads.orderReport_ - 获取订单报告
  757. countryCode = None if kwargs.get("countryCode")==None else kwargs.get("countryCode")
  758. shopReportday = (datetime.now() + timedelta(days=days)).strftime("%Y-%m-%d")
  759. print(shopReportday)
  760. try:
  761. conn = self.Data_auth()
  762. cursor = conn.cursor()
  763. except:
  764. time.sleep(5)
  765. conn = self.Data_auth()
  766. cursor = conn.cursor()
  767. query_judge = f"""select count(*) from asj_ads.orderReport_ where ReportDate='{shopReportday}' and country_code='{countryCode}'"""
  768. print(query_judge)
  769. cursor.execute(query_judge)
  770. rel = cursor.fetchall()
  771. # print()
  772. if rel[0][0]!=0:
  773. print("已存在")
  774. return '已存在'
  775. para = {"reportType": ReportType.GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE_GENERAL,
  776. "dataStartTime": shopReportday, "dataEndTime": shopReportday,
  777. "reportOptions": {"ShowSalesChannel": "true"}}
  778. reportid = self.create_report(**para) # {"ShowSalesChannel":"true"}
  779. decom_df = self.decompression(reportid)
  780. decom_df[decom_df.select_dtypes(float).columns] = decom_df[decom_df.select_dtypes(float).columns].fillna(0.0)
  781. decom_df[decom_df.select_dtypes(int).columns] = decom_df[decom_df.select_dtypes(int).columns].fillna(0)
  782. decom_df[decom_df.select_dtypes(datetime).columns] = decom_df[decom_df.select_dtypes(datetime).columns].astype(
  783. 'string')
  784. if "purchase-order-number" in decom_df.columns:
  785. decom_df['purchase-order-number'] = decom_df['purchase-order-number'].astype("string")
  786. decom_df.fillna('', inplace=True)
  787. # decom_df.to_csv('order.csv')
  788. decom_df["ReportDate"] = parse(shopReportday)
  789. # decom_df['timezone'] = decom_df["purchase-date"].map(lambda x: parse(x).tzname()).fillna(method='bfill')
  790. decom_df['timezone'] = "UTC"
  791. print("==========================================================")
  792. decom_df[["purchase-date", "last-updated-date"]] = decom_df[["purchase-date", "last-updated-date"]].applymap(
  793. lambda x: self.timeDeal(x) if pd.isna(x) == False or x != None else x)
  794. if 'is-business-order' not in decom_df.columns:
  795. decom_df['is-business-order'] = None
  796. if 'purchase-order-number' not in decom_df.columns:
  797. decom_df['purchase-order-number'] = '-'
  798. if 'price-designation' not in decom_df.columns:
  799. decom_df['price-designation'] = '-'
  800. decom_df['seller_id'] = seller_id
  801. country_code = str(self.marketplace)[-2:]
  802. if country_code == 'GB':
  803. country_code = "UK"
  804. # decom_df['country_code'] = "UK"
  805. decom_df['country_code'] = country_code
  806. decom_df['insert_time'] = datetime.now()
  807. # print(decom_df[])
  808. reserve_columns = ["amazon-order-id", "merchant-order-id", "purchase-date", "last-updated-date", "order-status",
  809. "fulfillment-channel", "sales-channel", "order-channel", "ship-service-level",
  810. "product-name",
  811. "sku", "asin", "item-status", "quantity", "currency", "item-price", "item-tax",
  812. "shipping-price",
  813. "shipping-tax", "gift-wrap-price", "gift-wrap-tax", "item-promotion-discount",
  814. "ship-promotion-discount", "ship-city", "ship-state", "ship-postal-code", "ship-country",
  815. "promotion-ids", "is-business-order", "purchase-order-number", "price-designation",
  816. "ReportDate",
  817. "timezone", "seller_id", "country_code",'insert_time'
  818. ]
  819. list_df = decom_df[reserve_columns].to_numpy().tolist()
  820. try:
  821. conn = self.Data_auth()
  822. cursor = conn.cursor()
  823. except:
  824. time.sleep(5)
  825. conn = self.Data_auth()
  826. cursor = conn.cursor()
  827. # print(list(conn.query("select * from amz_sp_api.orderReport")))
  828. sql = f"""
  829. insert into asj_ads.orderReport_(`amazon_order_id`, `merchant_order_id`, `purchase_date`, `last_updated_date`, `order_status`,
  830. `fulfillment_channel`, `sales_channel`, `order_channel`, `ship_service_level`,
  831. `product_name`,
  832. `sku`, `asin`, `item_status`, `quantity`, `currency`, `item_price`, `item_tax`,
  833. `shipping_price`,
  834. `shipping_tax`, `gift_wrap_price`, `gift_wrap_tax`, `item_promotion_discount`,
  835. `ship_promotion_discount`, `ship_city`, `ship_state`, `ship_postal_code`, `ship_country`,
  836. `promotion_ids`, `is_business_order`, `purchase_order_number`, `price_designation`,
  837. `ReportDate`,
  838. `timezone`, `seller_id`, `country_code`,`insert_time`)
  839. values (%s,%s,%s,%s,%s,%s,%s, %s,%s,%s,%s,%s,%s,%s, %s,%s,%s,%s,%s,%s,%s, %s,%s,%s,%s,%s,%s,%s, %s,%s,%s,%s,%s,%s,%s,%s)
  840. """ # ok
  841. try:
  842. conn.begin()
  843. cursor.executemany(sql, list_df)
  844. conn.commit()
  845. print("插入完成")
  846. conn.close()
  847. time.sleep(1)
  848. except Exception as e:
  849. conn.rollback()
  850. print(e)
  851. def timeDeal(self, orgTime): # time-deal
  852. orgTime = parse(orgTime)
  853. timezone = pytz.timezone("UTC")
  854. shopTime = orgTime.astimezone(timezone)
  855. shopTime_datetime = datetime(shopTime.year, shopTime.month, shopTime.day, shopTime.hour, shopTime.minute,
  856. shopTime.second)
  857. return shopTime_datetime
  858. @classmethod
  859. def listing_infoTable(cls): # To datatable asj_ads.Goods - Goods表,包括排名,图片,父子关系
  860. conn = SpApiRequest.Data_auth()
  861. cursor = conn.cursor()
  862. #
  863. cursor.execute(f"""select seller_id,country_code,asin,title from asj_ads.seller_listings where title is not null and title <>'' and (seller_id,country_code,asin) not in (select seller_id,countryCode,asin from asj_ads.Goods where update_time>='{datetime.today().date()}') group by seller_id,title,country_code,asin order by country_code desc""")
  864. query_ = cursor.fetchall()
  865. # print(query_)
  866. col_name = [i[0] for i in cursor.description]
  867. df_datatable = pd.DataFrame(query_, columns=col_name)
  868. count=0
  869. distance = 50
  870. print(len(df_datatable))
  871. while count<len(df_datatable):
  872. print(f"进度:{round(count / len(df_datatable) * 100, 2)}%")
  873. df = df_datatable.iloc[count:count+distance,:]
  874. count = count+distance
  875. df['detail_info'] = df.apply(lambda x: cls.get_listing_info01(x['title'],x['country_code'],x['asin'],x['seller_id']),axis=1)
  876. detail_info_k = df['detail_info'].map(lambda x: list(x.keys())).to_numpy().tolist()
  877. detail_info = df['detail_info'].to_numpy().tolist() #df['detail_info'].map(lambda x: list(x.values())).to_numpy().tolist()
  878. conn = SpApiRequest.Data_auth()
  879. print(count)
  880. SpApiRequest.Goods_insert(conn,detail_info,detail_info_k)
  881. if count%distance==0:
  882. cursor = conn.cursor()
  883. cursor.execute(
  884. f"""select seller_id,countryCode,asin from asj_ads.Goods where update_time>='{datetime.today().date()}'""")
  885. query_d = cursor.fetchall()
  886. # print(query_d)
  887. try:
  888. # print(tuple(delete_list))
  889. query = f"""delete from asj_ads.Goods where update_time<'{datetime.today().date()}'
  890. and (seller_id,countryCode,asin) in {query_d}
  891. """ #where (seller_id,country_code) in %s"""
  892. cursor.execute(query)
  893. conn.commit()
  894. # print(delete_list)
  895. # print("进行中...")
  896. except Exception as e:
  897. print(e)
  898. conn.rollback()
  899. print("Success")
  900. conn.close()
  901. @classmethod
  902. def Goods_drop_duplicates(cls):
  903. conn = SpApiRequest.Data_auth()
  904. cursor = conn.cursor()
  905. cursor.execute(
  906. f"""select seller_id,countryCode,asin as count_ from asj_ads.Goods group by seller_id,countryCode,asin having count(asin)>=2""")
  907. query_ = cursor.fetchall()
  908. print(len(query_))
  909. if len(query_)>0:
  910. query_sql2 = cursor.execute(
  911. f"""select distinct main_image, productTypes, BigCat_rank, BigCat_title, SmallCat_rank, SmallCat_title, brandName, browseNode, itemName, IsParent, parent_asin, asin, countryCode, marketplace_id, seller_id, update_time from asj_ads.Goods where (seller_id,countryCode,asin) in {query_}""")#
  912. query_2 = cursor.fetchall()
  913. try:
  914. query = f"""delete from asj_ads.Goods where (seller_id,countryCode,asin) in {query_}
  915. """ # where (seller_id,country_code) in %s"""
  916. cursor.execute(query)
  917. conn.commit()
  918. except Exception as e:
  919. print("错误过程1",e)
  920. conn.rollback()
  921. sql = """insert into
  922. asj_ads.Goods(main_image, productTypes, BigCat_rank, BigCat_title, SmallCat_rank, SmallCat_title, brandName, browseNode, itemName, IsParent, parent_asin, asin, countryCode, marketplace_id, seller_id, update_time)
  923. values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"""
  924. try:
  925. conn.begin()
  926. cursor.executemany(sql, query_2)
  927. conn.commit()
  928. print("插入完成")
  929. conn.close()
  930. time.sleep(1)
  931. except Exception as e:
  932. conn.rollback()
  933. print("错误过程2",e)
  934. @staticmethod
  935. def get_listing_info01(refresh_token, countryCode, asin, seller_id): # used in listing_infoTable
  936. # print(refresh_token)
  937. aws_credentials = {
  938. 'refresh_token': refresh_token,
  939. 'lwa_app_id': 'amzn1.application-oa2-client.1f9d3d4747e14b22b4b598e54e6b922e', # 卖家中心里面开发者资料LWA凭证
  940. 'lwa_client_secret': 'amzn1.oa2-cs.v1.3af0f5649f5b8e151cd5bd25c10f2bf3113172485cd6ffc52ccc6a5e8512b490',
  941. 'aws_access_key': 'AKIARBAGHTGOZC7544GN',
  942. 'aws_secret_key': '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',
  943. 'role_arn': 'arn:aws:iam::070880041373:role/Amazon_SP_API_ROLE'
  944. }
  945. mak = {'AE': Marketplaces.AE, 'BE': Marketplaces.BE, 'DE': Marketplaces.DE,
  946. 'PL': Marketplaces.PL, 'EG': Marketplaces.EG, 'ES': Marketplaces.ES,
  947. 'FR': Marketplaces.FR, 'GB': Marketplaces.GB, 'IN': Marketplaces.IN,
  948. 'IT': Marketplaces.IT, 'NL': Marketplaces.NL, 'SA': Marketplaces.SA,
  949. 'SE': Marketplaces.SE, 'TR': Marketplaces.TR, 'UK': Marketplaces.UK,
  950. 'AU': Marketplaces.AU, 'JP': Marketplaces.JP, 'SG': Marketplaces.SG,
  951. 'US': Marketplaces.US,
  952. 'BR': Marketplaces.BR, 'CA': Marketplaces.CA, 'MX': Marketplaces.MX
  953. }
  954. cate_item = CatalogItems(credentials=aws_credentials, marketplace=mak[countryCode],version='2022-04-01')
  955. try:
  956. variations_info = SpApiRequest.variations_judge(cate_item, asin)
  957. except:
  958. time.sleep(2.5)
  959. variations_info = SpApiRequest.variations_judge(cate_item, asin)
  960. try:
  961. cate_item = CatalogItems(credentials=aws_credentials, marketplace=mak[countryCode], version='2020-12-01')
  962. detail_info = SpApiRequest.get_detail_cat(cate_item, asin, mak, countryCode)
  963. except:
  964. time.sleep(2.5)
  965. cate_item = CatalogItems(credentials=aws_credentials, marketplace=mak[countryCode], version='2020-12-01')
  966. detail_info = SpApiRequest.get_detail_cat(cate_item, asin, mak, countryCode)
  967. detail_info.update(variations_info)
  968. detail_info['asin'] = asin
  969. detail_info['countryCode'] = countryCode
  970. detail_info['marketplace_id'] = mak[countryCode].marketplace_id
  971. detail_info['seller_id'] = seller_id
  972. detail_info['update_time'] = datetime.now()
  973. return detail_info
  974. @staticmethod
  975. def variations_judge(cate_item, asin): # used in listing_infoTable, 判断是否有父子关系
  976. def temp_func(cate_item, asin):
  977. variations = cate_item.get_catalog_item(asin=asin, **{"includedData": ['relationships']}) # 'variations',
  978. var_info = variations.payload
  979. # print(variations)
  980. IsParent = 'Y'
  981. parent_asin = ''
  982. try:
  983. relationships = var_info.get("relationships")[0]['relationships']
  984. except:
  985. relationships = []
  986. if len(relationships) > 0:
  987. variationType = relationships[0]['type']
  988. if relationships[0].get('parentAsins') is not None:
  989. parent_asin = relationships[0]['parentAsins'][0]
  990. IsParent = 'N'
  991. elif relationships[0].get('childAsins') is not None:
  992. IsParent = 'Y'
  993. parent_asin = asin
  994. else:
  995. parent_asin = 'Erro_01'
  996. else:
  997. IsParent = 'SG'
  998. parent_asin = asin
  999. print(IsParent, '父asin:', parent_asin, '子asin', asin)
  1000. return {"IsParent": IsParent, "parent_asin": parent_asin}
  1001. try:
  1002. return temp_func(cate_item, asin)
  1003. except:
  1004. try:
  1005. time.sleep(12)
  1006. return temp_func(cate_item, asin)
  1007. except Exception as e:
  1008. print("判断是否为父子asin时出错:", e)
  1009. return {"IsParent": 'Erro', "parent_asin": 'Erro'}
  1010. @staticmethod
  1011. def Goods_insert(conn,detail_info,detail_info_k): # To datatable asj.Goods
  1012. # print(detail_info)
  1013. df = pd.DataFrame(detail_info)
  1014. # print(df.columns)
  1015. try:
  1016. cursor = conn.cursor()
  1017. except:
  1018. time.sleep(2.5)
  1019. conn = SpApiRequest.Data_auth()
  1020. cursor = conn.cursor()
  1021. query_sql = "select * from asj_ads.Goods"
  1022. cursor.execute(query_sql)
  1023. col = [i[0] for i in cursor.description]
  1024. query_rel = cursor.fetchall()
  1025. df_query = pd.DataFrame(query_rel, columns=col)
  1026. merge_df = df.merge(df_query,how='left',on=['asin', 'countryCode', 'marketplace_id', 'seller_id'],suffixes=['','_right'])
  1027. merge_df['IsParent'] = merge_df.apply(lambda x:x['IsParent_right'] if x['IsParent']=='Erro' else x['IsParent'],axis=1)
  1028. merge_df['parent_asin'] = merge_df.apply(lambda x: x['parent_asin_right'] if x['parent_asin'] == 'Erro' else x['parent_asin'], axis=1)
  1029. erro_df = merge_df.query("IsParent=='Erro' or parent_asin=='Erro'")
  1030. merge_df.drop(erro_df.index,inplace=True)
  1031. detail_info_value = merge_df[['main_image', 'productTypes', 'BigCat_rank', 'BigCat_title', 'SmallCat_rank',
  1032. 'SmallCat_title', 'brandName', 'browseNode', 'itemName', 'IsParent', 'parent_asin',
  1033. 'asin', 'countryCode', 'marketplace_id', 'seller_id', 'update_time']].to_numpy().tolist()
  1034. try:
  1035. insertsql = """insert into
  1036. asj_ads.Goods(main_image, productTypes, BigCat_rank, BigCat_title, SmallCat_rank, SmallCat_title, brandName, browseNode, itemName, IsParent, parent_asin, asin, countryCode, marketplace_id, seller_id, update_time)
  1037. values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"""
  1038. conn.begin()
  1039. cursor.executemany(insertsql, tuple(detail_info_value))
  1040. conn.commit()
  1041. print("插入完成Goods")
  1042. except Exception as e:
  1043. print("插入错误Goods:", e)
  1044. conn.rollback()
  1045. sales_rankData = []
  1046. for i in detail_info_value:
  1047. tmp_list = []
  1048. for j in [2,3,4,5,6,8,11,12,13,14]:
  1049. tmp_list.extend([i[j]])
  1050. tmp_list.extend([datetime.now(),datetime.utcnow()])
  1051. sales_rankData.append(tmp_list)
  1052. # print(sales_rankData,len(sales_rankData))
  1053. try:
  1054. insertsql = """insert into
  1055. asj_ads.ProductRank(BigCat_rank, BigCat_title, SmallCat_rank, SmallCat_title, brandName, itemName, asin, countryCode, marketplace_id, seller_id, update_time,time_UTC)
  1056. values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"""
  1057. conn.begin()
  1058. cursor.executemany(insertsql, tuple(sales_rankData))
  1059. conn.commit()
  1060. print("插入完成rank")
  1061. # return '插入完成'
  1062. except Exception as e:
  1063. print("插入错误rank:", e)
  1064. conn.rollback()
  1065. @staticmethod
  1066. def get_detail_cat(cate_item, asin, mak, countryCode): # used in listing_infoTable, category sp-api - 获取listing的信息数据
  1067. try:
  1068. detail_info = cate_item.get_catalog_item(asin=asin, **{
  1069. "includedData": ["images,productTypes,salesRanks,summaries"],
  1070. "marketplaceIds": [str(mak[countryCode].marketplace_id)]})
  1071. payload = detail_info.payload
  1072. # print(payload)
  1073. try:
  1074. main_image = payload['images'][0]['images'][0]['link'] if len(payload['images']) > 0 else "#"
  1075. except:
  1076. main_image = '#-'
  1077. try:
  1078. productTypes = payload['productTypes'][0]['productType'] if len(payload['productTypes'][0]) > 0 else "#"
  1079. except:
  1080. productTypes = '#-'
  1081. try:
  1082. # print(payload['ranks'][0])
  1083. if len(payload['ranks'][0]) > 0:
  1084. BigCat_rank = payload['ranks'][0]['ranks'][0]['rank']
  1085. BigCat_title = payload['ranks'][0]['ranks'][0]['title']
  1086. SmallCat_rank = payload['ranks'][0]['ranks'][1]['rank']
  1087. SmallCat_title = payload['ranks'][0]['ranks'][1]['title']
  1088. else:
  1089. BigCat_rank, BigCat_title, SmallCat_rank, SmallCat_title = 0, '#', 0, '#'
  1090. except:
  1091. BigCat_rank, BigCat_title, SmallCat_rank, SmallCat_title = 0, '#-', 0, '#-'
  1092. try:
  1093. if len(payload['summaries'][0]) > 0:
  1094. brandName = payload['summaries'][0]['brandName']
  1095. browseNode = payload['summaries'][0]['browseNode']
  1096. itemName = payload['summaries'][0]['itemName']
  1097. else:
  1098. brandName, browseNode, itemName = '#', '#', '#'
  1099. except:
  1100. brandName, browseNode, itemName = '#-', '#-', '#-'
  1101. return {'main_image': main_image, 'productTypes': productTypes, 'BigCat_rank': BigCat_rank,
  1102. 'BigCat_title': BigCat_title, 'SmallCat_rank': SmallCat_rank, 'SmallCat_title': SmallCat_title,
  1103. 'brandName': brandName, 'browseNode': browseNode, 'itemName': itemName}
  1104. except:
  1105. return {'main_image': '', 'productTypes': '', 'BigCat_rank': 0,
  1106. 'BigCat_title': '', 'SmallCat_rank': 0, 'SmallCat_title': '',
  1107. 'brandName': '', 'browseNode': '', 'itemName': ''}
  1108. def GET_BRAND_ANALYTICS_SEARCH_TERMS_REPORT(self, refresh_token,seller_id,days=-3,**kwargs):
  1109. shopReportday = (datetime.now() + timedelta(days=days)).strftime("%Y-04-21")
  1110. shopReportday_E = (datetime.now() + timedelta(days=days)).strftime("%Y-04-27")
  1111. print(shopReportday)
  1112. para = {"reportType": ReportType.GET_BRAND_ANALYTICS_SEARCH_TERMS_REPORT,"reportOptions":{"reportPeriod": "WEEK"},"dataStartTime": shopReportday, "dataEndTime": shopReportday_E,}
  1113. reportid = self.create_report(**para)
  1114. def BRAND_ANALYTICS_TEXT_deal(self,text):
  1115. pass
  1116. @staticmethod
  1117. def data_judge_secondTry(refresh_token,sp_api,data_type,seller_id,auth_conn,days=-1,**kwargs): # Main-retry, 重试函数,重试次数2次
  1118. a_kw = kwargs
  1119. try:
  1120. SpApiRequest.data_judge(refresh_token,sp_api, data_type, seller_id, auth_conn,days=days,**a_kw)
  1121. except Exception as e:
  1122. try:
  1123. if e.args[0][0]['code']=='InvalidInput':
  1124. return ''
  1125. print('first time to try...')
  1126. time.sleep(15)
  1127. SpApiRequest.data_judge(refresh_token,sp_api, data_type, seller_id, auth_conn,days=days,**a_kw)
  1128. except Exception as e:
  1129. print(e)
  1130. print('twice time to try...')
  1131. time.sleep(20)
  1132. SpApiRequest.data_judge(refresh_token, sp_api, data_type, seller_id, auth_conn, days=days, **a_kw)
  1133. @staticmethod
  1134. def data_judge(refresh_token,sp_api,data_type,seller_id,auth_conn,days=-1,**kwargs): # select Report type - 报告获取类型判断
  1135. a_kw = kwargs
  1136. if data_type == "GET_FLAT_FILE_OPEN_LISTINGS_DATA":
  1137. return sp_api.GET_FLAT_FILE_OPEN_LISTINGS_DATA(refresh_token,auth_conn,seller_id,days)
  1138. elif data_type =="GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE_GENERAL":
  1139. # for day_ in range(31,1):
  1140. # sp_api.GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE_GENERAL(seller_id,days=day_*-1)
  1141. return sp_api.GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE_GENERAL(refresh_token,seller_id,days,**a_kw)
  1142. elif data_type =="GET_FLAT_FILE_RETURNS_DATA_BY_RETURN_DATE":
  1143. return sp_api.GET_FLAT_FILE_RETURNS_DATA_BY_RETURN_DATE(refresh_token,seller_id,days)
  1144. elif data_type =="GET_SALES_AND_TRAFFIC_REPORT":
  1145. return sp_api.GET_SALES_AND_TRAFFIC_REPORT(refresh_token,seller_id,days,**a_kw)
  1146. elif data_type == "GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA":
  1147. return sp_api.GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA(refresh_token,auth_conn,seller_id,days,**a_kw)
  1148. elif data_type=="GET_BRAND_ANALYTICS_SEARCH_TERMS_REPORT":
  1149. return sp_api.GET_BRAND_ANALYTICS_SEARCH_TERMS_REPORT(refresh_token,seller_id,days,**a_kw)
  1150. else:
  1151. return ""
  1152. @classmethod
  1153. def get_allShops(cls,data_type=Literal["GET_FLAT_FILE_OPEN_LISTINGS_DATA","GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE_GENERAL"],days=-1,**kwargs): # Main-AllCountries-AuthAndPost, 所有店铺数据报告获取的主要函数
  1154. df = cls.auth_info()
  1155. zosi = df.query("account_name=='AM-ZOSI-US'")['refresh_token'].to_numpy().tolist()
  1156. # print(zosi)
  1157. refreshtoken_list = df.query("account_name!='AM-ZOSI-US'")['refresh_token'].to_numpy().tolist()
  1158. zosi.extend(refreshtoken_list)
  1159. refreshtoken_list = zosi.copy()
  1160. print(len(refreshtoken_list))
  1161. # refreshtoken_list = refreshtoken_list+refreshtoken_li
  1162. a_kw = kwargs
  1163. for refresh_token in refreshtoken_list:
  1164. aws_credentials = {
  1165. 'refresh_token': refresh_token,
  1166. 'lwa_app_id': 'amzn1.application-oa2-client.1f9d3d4747e14b22b4b598e54e6b922e', # 卖家中心里面开发者资料LWA凭证
  1167. 'lwa_client_secret': 'amzn1.oa2-cs.v1.3af0f5649f5b8e151cd5bd25c10f2bf3113172485cd6ffc52ccc6a5e8512b490',
  1168. 'aws_access_key': 'AKIARBAGHTGOZC7544GN',
  1169. 'aws_secret_key': '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',
  1170. 'role_arn': 'arn:aws:iam::070880041373:role/Amazon_SP_API_ROLE'
  1171. }
  1172. single_info = df.query("refresh_token==@refresh_token")
  1173. region_circle = single_info['region'].values[0]
  1174. seller_id = single_info['selling_partner_id'].values[0]
  1175. account_name = single_info['account_name'].values[0]
  1176. if region_circle == 'NA':
  1177. pass
  1178. for marketplace in [Marketplaces.US, Marketplaces.BR, Marketplaces.CA,Marketplaces.MX]:
  1179. sp_api = SpApiRequest(aws_credentials, marketplace)
  1180. a_kw['countryCode'] = str(marketplace)[-2:]
  1181. # print(a_kw)
  1182. try:
  1183. print("refresh_token:",refresh_token,'data_type:',data_type,'seller_id:',seller_id,'marketplace:',marketplace.marketplace_id,'country_code:',a_kw['countryCode'],sep='\n')
  1184. auth_conn = SpApiRequest.Token_auth()
  1185. # print(a_kw)
  1186. cls.data_judge_secondTry(refresh_token,sp_api, data_type, seller_id, auth_conn,days,**a_kw)
  1187. ## sp_api.GET_FLAT_FILE_OPEN_LISTINGS_DATA(auth_conn, seller_id)
  1188. except Exception as e:
  1189. print(e)
  1190. time.sleep(3.5)
  1191. elif region_circle == 'EU':
  1192. pass
  1193. for marketplace in [Marketplaces.DE,Marketplaces.AE, Marketplaces.BE, Marketplaces.PL,
  1194. Marketplaces.EG,Marketplaces.ES, Marketplaces.GB, Marketplaces.IN, Marketplaces.IT,
  1195. Marketplaces.NL, Marketplaces.SA, Marketplaces.SE, Marketplaces.TR,Marketplaces.UK,Marketplaces.FR,
  1196. ]:
  1197. sp_api = SpApiRequest(aws_credentials, marketplace)
  1198. a_kw['countryCode'] = str(marketplace)[-2:]
  1199. try:
  1200. auth_conn = SpApiRequest.Token_auth()
  1201. cls.data_judge_secondTry(refresh_token,sp_api, data_type, seller_id, auth_conn,days,**a_kw)
  1202. ## sp_api.GET_FLAT_FILE_OPEN_LISTINGS_DATA(auth_conn, seller_id)
  1203. except Exception as e:
  1204. print(e)
  1205. time.sleep(3.5)
  1206. else:
  1207. # if region_circle not in ['NA','EU']:
  1208. auth_conn = SpApiRequest.Token_auth()
  1209. print(region_circle)
  1210. marketplace = eval(f'Marketplaces.{region_circle}')
  1211. sp_api = SpApiRequest(aws_credentials, marketplace)
  1212. a_kw['countryCode'] = str(marketplace)[-2:]
  1213. cls.data_judge_secondTry(refresh_token,sp_api, data_type, seller_id, auth_conn,days,**a_kw)
  1214. ## sp_api.GET_FLAT_FILE_OPEN_LISTINGS_DATA(auth_conn, seller_id)
  1215. if __name__ == '__main__':
  1216. # for days in range(35,45):
  1217. # SpApiRequest.get_allShops("GET_SALES_AND_TRAFFIC_REPORT",days=-days,**{"level":"SKU"})
  1218. # SpApiRequest.listing_infoTable()
  1219. # rel = SpApiRequest.get_catelog(account_name='AM-ZOSI-US',country=Marketplaces.US,asin='B0B8CPHSL4')
  1220. # print(rel)
  1221. # SpApiRequest.get_allShops("GET_BRAND_ANALYTICS_SEARCH_TERMS_REPORT")
  1222. # pass
  1223. # SpApiRequest.listing_infoTable()
  1224. SpApiRequest.Goods_drop_duplicates()