Browse Source

Merge branch 'yifan' of ASJ_ADS/sync_amz_data into master

新增class SD_Client
yifan_huang96 1 year ago
parent
commit
263d4aab40

+ 102 - 18
sync_amz_data/DataTransform/Data_ETL.py

@@ -1,27 +1,21 @@
-from sync_amz_data.public.amz_ad_client import SPClient,Account
+from sync_amz_data.public.amz_ad_client import SPClient,Account,SBClient,SDClient
 import pandas as pd
 import numpy as np
 from dateutil.parser import parse
+pd.set_option('display.max_columns', None)
+import warnings
+warnings.filterwarnings('ignore')
+pd.set_option('expand_frame_repr', False)
+from datetime import datetime,timezone
 
-class Acount_ETL(Account):
+class Common_ETLMethod:
     def columnsName_modify(self,df):
-        df.columns = [i.replace(".","_") for i in df.columns]
-        return df
-
-    def portfolio_ETL(self):
-        list_portfolio = self.get_portfolio()
-        df_portfolio = pd.json_normalize(list_portfolio)
-        print(self.columnsName_modify(df_portfolio))
-        return self.columnsName_modify(df_portfolio)
-
-class SP_ETL(SPClient):
-    def columnsName_modify(self,df):
-        df.columns = [i.replace(".","_") for i in df.columns]
+        df.columns = [i.replace(".","_").lower() for i in df.columns]
         return df
 
     def time_stamp_convert(self,df,time_columns:list):
         for time_column in time_columns:
-            df[time_column] = pd.to_datetime(df[time_column])
+            df[time_column] = pd.to_datetime(df[time_column]*1000000).map(lambda x: x.strftime("%Y-%m-%d %H:%M:%S"))
         df[time_columns] = df[time_columns].astype("datetime64")
         return df
 
@@ -39,6 +33,23 @@ class SP_ETL(SPClient):
         df.drop(columns=[segment],inplace=True)
         return df
 
+    def expression_split(self,df,segment):
+        df[segment] = df[segment].astype("string")
+        df[segment+str("_type")] = df[segment].str.extract(r"'type':\s{0,1}'(.+?)',")
+        df[segment+str("_value")] = df[segment].str.extract(r"'value':\s{0,1}[',[,{](.+)'")
+        df[segment+str("_value")] = df[segment+str("_value")].map(lambda x: x if pd.isna(x) or "," not in x else "["+x+"'}]")
+        df.replace(['nan','Nan','NaN'],np.nan,inplace=True)
+        df.drop(columns=[segment],inplace=True)
+        return df
+
+class Acount_ETL(Account,Common_ETLMethod):
+    def portfolio_ETL(self):
+        list_portfolio = self.get_portfolios()
+        df_portfolio = pd.json_normalize(list_portfolio)
+        print(self.columnsName_modify(df_portfolio))
+        return self.columnsName_modify(df_portfolio)
+
+class SP_ETL(SPClient,Common_ETLMethod):
     def campaigns_ETL(self):
         list_campaign_SP = list(self.iter_campaigns(**{"includeExtendedDataFields":True}))
         df_campaign = pd.json_normalize(list_campaign_SP)
@@ -75,8 +86,81 @@ class SP_ETL(SPClient):
         list_budget = self.get_budget(campaign_ids = campaign_ids)['success']
         df_budget = pd.json_normalize(list_budget)
         df_budget = self.TZ_Deal(df_budget,["usageUpdatedTimestamp"])
+        return self.columnsName_modify(df_budget)
+
+class SB_ETL(SBClient,Common_ETLMethod):
+    def campaigns_ETL(self):
+        list_campaign_SB = list(self.iter_campaigns(**{"includeExtendedDataFields":True}))
+        df_campaign = pd.json_normalize(list_campaign_SB)
+        df_campaign = self.placement_segmentsplit(df_campaign, "bidding.bidAdjustmentsByPlacement")
+        df_campaign = self.time_stamp_convert(df_campaign,["extendedData.creationDate","extendedData.lastUpdateDate"])
+        # print(df_campaign)
+        return self.columnsName_modify(df_campaign)
+
+    def adGroup_ETL(self):
+        list_adGroup_SB = list(self.iter_adGroups(**{"includeExtendedDataFields":True}))
+        df_adGroup_SP = pd.json_normalize(list_adGroup_SB)
+        df_adGroup_SP = self.time_stamp_convert(df_adGroup_SP,["extendedData.creationDate","extendedData.lastUpdateDate"])
+        return self.columnsName_modify(df_adGroup_SP)
+
+    def ads_ETL(self):
+        list_adId_SB = list(self.iter_ads(**{"includeExtendedDataFields":True}))
+        df_adId_SP = pd.json_normalize(list_adId_SB)
+        df_adId_SP = self.time_stamp_convert(df_adId_SP,["extendedData.creationDate","extendedData.lastUpdateDate"])
+        return self.columnsName_modify(df_adId_SP)
+
+    def keyword_ETL(self):
+        list_keywords_SB = [row for _ in list(self.iter_keywords()) for row in _]
+        df_keywords_SP = pd.json_normalize(list_keywords_SB)
+        return self.columnsName_modify(df_keywords_SP)
+
+
+    def targets_ETL(self):
+        list_targets = list(self.iter_targets())
+        df_targets = pd.json_normalize(list_targets)
+        # df_targets = self.TZ_Deal(df_targets, ["extendedData.creationDateTime", "extendedData.lastUpdateDateTime"])
+        df_targets = self.expression_split(df_targets,"resolvedExpressions")
+
+        return self.columnsName_modify(df_targets)
+
+    def budget_ETL(self,campaign_ids:list):
+        list_budget = self.get_budget(campaignIds = campaign_ids)['success']
+        df_budget = pd.json_normalize(list_budget)
+        df_budget = self.TZ_Deal(df_budget,["usageUpdatedTimestamp"])
         print(df_budget)
 
+class SD_ETL(SDClient,Common_ETLMethod):
+    def campaigns_ETL(self):
+        list_campaign_SD = self.get_campaigns()
+        df_campaign = pd.json_normalize(list_campaign_SD)
+        df_campaign['startDate'] = df_campaign['startDate'].map(lambda x: datetime.strptime(x,"%Y%m%d").date())
+        df_campaign['portfolioId'] = df_campaign['portfolioId'].fillna(-1).astype("int64")
+        return self.columnsName_modify(df_campaign)
+
+    def adGroups_ETL(self,**param):
+        list_adGroups_SD = [row for _ in list(self.iter_adGroups(**param)) for row in _]
+        df_adGroups_SD = pd.json_normalize(list_adGroups_SD)
+        tactic = {"T00020":"Contextual targeting","T00030":"Audiences targeting"}
+        df_adGroups_SD["tactic_type"] = df_adGroups_SD['tactic'].map(tactic)
+        return self.columnsName_modify(df_adGroups_SD)
+
+    def ads_ETL(self):
+        list_ads_SD = [row for _ in list(self.iter_ads()) for row in _]
+        df_ads_SD = pd.json_normalize(list_ads_SD)
+        return self.columnsName_modify(df_ads_SD)
+
+    def targets_ETL(self,**param):
+        list_targets = [row for _ in list(self.iter_targets(**param)) for row in _]
+        df_targets = pd.json_normalize(list_targets)
+        df_targets = self.expression_split(df_targets, "resolvedExpression")
+        print(df_targets)
+
+    def budget_ETL(self,campaignsIds:list):
+        list_budget = self.get_budget(campaignIds=campaignsIds)['success']
+        df_budget = pd.json_normalize(list_budget)
+        df_budget = self.TZ_Deal(df_budget,["usageUpdatedTimestamp"])
+        return self.columnsName_modify(df_budget)
+
 if __name__ == '__main__':
     AWS_CREDENTIALS = {
         'lwa_client_id': 'amzn1.application-oa2-client.ebd701cd07854fb38c37ee49ec4ba109',
@@ -84,6 +168,6 @@ if __name__ == '__main__':
         'lwa_client_secret': 'cbf0514186db4df91e04a8905f0a91b605eae4201254ced879d8bb90df4b474d',
         'profile_id': "3006125408623189"
     }
-    ac_etl = SP_ETL(**AWS_CREDENTIALS)
-    print(ac_etl.budget_ETL(campaign_ids=["126327624499318"]))
-
+    ac_etl = SD_ETL(**AWS_CREDENTIALS)
+    # print(ac_etl.budget_ETL(campaign_ids=["126327624499318"]))
+    print(ac_etl.budget_ETL(["257424912382921"]))

+ 0 - 0
sync_amz_data/DataTransform/__init__.py


+ 0 - 286
sync_amz_data/public/SP_SB_SD_jsonDeal.py

@@ -1,286 +0,0 @@
-from sync_amz_data.public.adstoken_OAUTH import Ads_Api_Token
-import requests
-import datetime,time
-import pandas as pd
-import numpy as np
-
-access_tokenapi = Ads_Api_Token(shop_name='ZosiDirect', profileId='3006125408623189')
-access_token = access_tokenapi._get_access_token()
-
-class DataDeal:
-    def __int__(self):
-        self.public_url = "https://advertising-api.amazon.com"
-        self.ClientId = "amzn1.application-oa2-client.ebd701cd07854fb38c37ee49ec4ba109"
-        self.Scope = "3006125408623189"
-    def token_(self):
-        access_tokenapi = Ads_Api_Token(shop_name='ZosiDirect', profileId='3006125408623189')
-        access_token = access_tokenapi._get_access_token()
-        Authorization = 'Bearer ' + access_token
-        return Authorization
-
-    def time_stamp_convert(self,df,segment:list):
-        for time_column in segment:
-            df[time_column] = pd.to_datetime(df[time_column]*1000000)
-        return df
-
-    def placement_segmentsplit(self,df,segment):
-        df[segment] = df[segment].astype("string")
-        df[segment+str("_percentage")] = df[segment].str.extract("'percentage':.+([\d\.]{1,}),").astype('float32')
-        df[segment+str("_placement")] = df[segment].str.extract("'placement':.+'(.+)'")
-        df.replace(['nan','Nan','NaN'],np.nan,inplace=True)
-        df.drop(columns=[segment],inplace=True)
-        return df
-
-    def columnsName_modify(self,df):
-        df.columns = [i.replace(".","_") for i in df.columns]
-        return df
-
-    def get_profilio_info(self,token):
-        header = {'Amazon-Advertising-API-ClientId': self.ClientId,
-                  'Amazon-Advertising-API-Scope': self.Scope,
-                  'Authorization': self.token_()}
-
-        url_ = "https://advertising-api.amazon.com/v2/portfolios/extended"  # V3版本
-        req_time = 0
-        while (req_time != 3):
-            req_time += 1
-            res = requests.get(url_, headers=header)  # V3版本为post请求
-            if res.status_code not in [200, 207]:
-                time.sleep(3)
-            else:
-                list_portfolio =  res.json()
-                df_portfolio = pd.json_normalize(list_portfolio)
-                return self.columnsName_modify(df_portfolio)
-        return res.text
-
-
-    def get_campaign_info_SP(self,token):
-        header = {'Amazon-Advertising-API-ClientId': self.ClientId,
-                  'Amazon-Advertising-API-Scope': self.Scope,
-                  'Authorization': self.token_(),
-                  'Content-Type': 'application/vnd.spCampaign.v3+json',
-                  'Accept': """application/vnd.spCampaign.v3+json"""}
-
-        url_ = self.public_url+"/sp/campaigns/list"  # V3版本
-        req_time = 0
-        while (req_time != 3):
-            req_time += 1
-            res = requests.post(url_, headers=header)  # V3版本为post请求
-            print(res.status_code)
-            if res.status_code not in [200, 207]:
-                time.sleep(3)
-            else:
-                list_campaign_SP = res.json()
-                df_campaign = pd.json_normalize(list_campaign_SP['campaigns'])
-                df_campaign = self.placement_segmentsplit(df_campaign,"dynamicBidding.placementBidding")
-                return self.columnsName_modify(df_campaign)
-        return res.text
-
-
-
-    def get_campaign_info_SB(self,token):
-        header = {'Amazon-Advertising-API-ClientId': self.ClientId,
-                  'Amazon-Advertising-API-Scope': self.Scope,
-                  'Authorization':  self.token_(),
-                  'Content-Type': 'application/vnd.sbcampaignresource.v4+json',
-                  'Accept': """application/vnd.sbcampaignresource.v4+json"""}
-
-        url_ = self.public_url+"/sb/v4/campaigns/list"
-
-        req_time = 0
-        while (req_time != 3):
-            req_time += 1
-            res = requests.post(url_, headers=header)
-            # print(res.status_code)
-            if res.status_code not in [200, 207]:
-                time.sleep(3)
-            else:
-                list_campaign_SB = res.json()
-                df_campaign_SB = pd.json_normalize(list_campaign_SB['campaigns'])
-                df_campaign_SB = self.placement_segmentsplit(df_campaign_SB,"bidding.bidAdjustmentsByPlacement")
-                return self.columnsName_modify(df_campaign_SB)
-        return res.text
-
-
-    def get_campaign_info_SD(self,token):
-        header = {'Amazon-Advertising-API-ClientId': self.ClientId,
-                  'Amazon-Advertising-API-Scope': self.Scope,
-                  'Authorization':  self.token_(),}
-
-        url_ = self.public_url+"/sd/campaigns"
-
-        req_time = 0
-        while (req_time != 3):
-            req_time += 1
-            res = requests.get(url_, headers=header)  # V3版本为post请求
-            print(res.status_code)
-            if res.status_code not in [200, 207]:
-                time.sleep(3)
-            else:
-                list_campaign_SD = res.json()
-                df_campaign_SD = pd.json_normalize(list_campaign_SD)
-                df_campaign_SD['portfolioId'] = df_campaign_SD['portfolioId'].map(lambda x: int(x) if pd.isna(x)==False else -1)
-                return self.columnsName_modify(df_campaign_SD)
-        return res.text
-
-
-    def get_adGroup_info_SP(self,token):
-        header = {'Amazon-Advertising-API-ClientId': self.ClientId,
-                  'Amazon-Advertising-API-Scope': self.Scope,
-                  'Authorization':  self.token_(),
-                  'Content-Type': "application/vnd.spAdGroup.v3+json",
-                  'Accept': "application/vnd.spAdGroup.v3+json"
-                  }
-
-        url_ = self.public_url+"/sp/adGroups/list"
-        res = requests.post(url_, headers=header)
-        if res.status_code not in [200, 207]:
-            return res.text
-
-        token_ = res.json().get('nextToken')
-        temp_list = [res.json()['adGroups']]
-        while token_ != None:
-            res = requests.post(url_, headers=header, json={'nextToken': token_,"includeExtendedDataFields":True})
-            if res.status_code in [200, 207]:
-                res = res.json()
-                token_ = res.get('nextToken')
-                temp_list[0].extend(res['adGroups'])
-
-            else:
-                print(res.text)
-                break
-        list_adGroup_SP = temp_list[0]
-        df_adGroup_SP = pd.json_normalize(list_adGroup_SP)
-        return self.columnsName_modify(df_adGroup_SP)
-
-
-    def get_adGroup_info_SB(self,token):
-        header = {'Amazon-Advertising-API-ClientId': self.ClientId,
-                  'Amazon-Advertising-API-Scope': self.Scope,
-                  'Authorization':  self.token_(),
-                  'Content-Type': "application/vnd.sbadgroupresource.v4+json",
-                  'Accept': "application/vnd.sbadgroupresource.v4+json"
-                  }
-
-        url_ = self.public_url+"/sb/v4/adGroups/list"  # V3版本
-        res = requests.post(url_, headers=header,json={"includeExtendedDataFields":True})  # V3版本为post请求
-        if res.status_code not in [200, 207]:
-            return res.text
-
-        token_ = res.json().get('nextToken')
-        temp_list = [res.json()['adGroups']]
-        while token_ != None:
-            res = requests.post(url_, headers=header, json={'nextToken': token_,"includeExtendedDataFields":True})
-            if res.status_code in [200, 207]:
-                res = res.json()
-                token_ = res.get('nextToken')
-                temp_list[0].extend(res['adGroups'])
-            else:
-                print(res.text)
-                break
-        list_adGroup_SB = temp_list[0]
-        df_adGroup_SB = pd.json_normalize(list_adGroup_SB)
-        df_adGroup_SB = self.time_stamp_convert(df_adGroup_SB,['extendedData.creationDate','extendedData.lastUpdateDate'])
-        return self.columnsName_modify(df_adGroup_SB)
-
-
-
-
-    def get_adGroup_info_SD(self,token):
-        header = {'Amazon-Advertising-API-ClientId': self.ClientId,
-                  'Amazon-Advertising-API-Scope': self.Scope,
-                  'Authorization':  self.token_(),
-                  }
-        url_ = self.public_url+"/sd/adGroups/extended"  # V3版本
-
-        res = requests.get(url_, headers=header)  # ,params={"startIndex":0,"count":1}
-        #
-        list_adGroup_SD = res.json()
-        df_adGroup_SD = pd.json_normalize(list_adGroup_SD)
-        df_adGroup_SD = self.time_stamp_convert(df_adGroup_SD,['creationDate','lastUpdatedDate'])
-        return self.columnsName_modify(df_adGroup_SD)
-
-
-    def get_adId_info_SP(self,token):
-        header = {'Amazon-Advertising-API-ClientId': self.ClientId,
-                  'Amazon-Advertising-API-Scope': self.Scope,
-                  'Authorization':  self.token_(),
-                  'Content-Type': "application/vnd.spProductAd.v3+json",
-                  'Accept': "application/vnd.spProductAd.v3+json"
-                  }
-        url_ = self.public_url+"/sp/productAds/list"
-
-        res = requests.post(url_, headers=header, json={"includeExtendedDataFields": True})  # V3版本为post请求
-        if res.status_code not in [200, 207]:
-            return res.text
-        print(res.json())
-
-        token_ = res.json().get('nextToken')
-        temp_list = [res.json()['productAds']]
-        while token_ != None:
-            res = requests.post(url_, headers=header, json={'nextToken': token_, "includeExtendedDataFields": True})
-            if res.status_code in [200, 207]:
-                res = res.json()
-                print(res)
-                token_ = res.get('nextToken')
-                temp_list[0].extend(res['productAds'])
-
-            else:
-                print(res.text)
-                break
-
-        list_adId_SP = temp_list[0]
-        df_adId_SP = pd.json_normalize(list_adId_SP)
-        return self.columnsName_modify(df_adId_SP)
-
-
-    def get_adId_info_SB(self,token):
-        header = {'Amazon-Advertising-API-ClientId': self.ClientId,
-                  'Amazon-Advertising-API-Scope': self.Scope,
-                  'Authorization':  self.token_(),
-                  'Content-Type': "application/vnd.sbadresource.v4+json",
-                  'Accept': "application/vnd.sbadresource.v4+json"
-                  }
-        url_ = self.public_url+"/sb/v4/ads/list"
-
-        res = requests.post(url_, headers=header)  # V3版本为post请求
-        if res.status_code not in [200, 207]:
-            return res.text
-        token_ = res.json().get('nextToken')
-        temp_list = [res.json()['ads']]
-        while token_ != None:
-            res = requests.post(url_, headers=header, json={'nextToken': token_})
-            if res.status_code in [200, 207]:
-                res = res.json()
-                print(res)
-                token_ = res.get('nextToken')
-                temp_list[0].extend(res['ads'])
-
-            else:
-                print(res.text)
-                break
-        list_adId_SB = temp_list[0]
-        return self.SB_segmentDeal(list_adId_SB)
-
-    def SB_segmentDeal(self,rel):
-        df = pd.json_normalize(rel)
-        df = self.time_stamp_convert(df,['extendedData.creationDate','extendedData.lastUpdateDate'])
-        df[["creative.asin1","creative.asin2","creative.asin3"]] = df['creative.asins'].map(str).str.slice(1,-1).str.replace("'","").str.split(",",expand=True).applymap(lambda x:None if x==None else x.strip())
-        df.drop(columns="creative.asins",inplace=True)
-        df = self.columnsName_modify(df)
-        return df
-
-
-
-    def get_adId_info_SD(self,token):
-        header = {'Amazon-Advertising-API-ClientId': self.ClientId,
-                  'Amazon-Advertising-API-Scope': self.Scope,
-                  'Authorization':  self.token_(),
-                  }
-        url_ = self.public_url+"/sd/productAds/extended"
-
-        res = requests.get(url_, headers=header)
-        return pd.json_normalize(res.json())
-
-
-

+ 1 - 0
sync_amz_data/public/__init__.py

@@ -1,2 +1,3 @@
 from .amz_ad_client import SPClient, SBClient, SDClient, BaseClient, AccountClient
+
 from .asj_client import asj_api

+ 0 - 197
sync_amz_data/public/adstoken_OAUTH.py

@@ -1,197 +0,0 @@
-import json
-import requests
-import sys
-import time
-import os
-# from myapp.temp_get_budget_black_five.info import *
-
-#"C:\Users\ansjer\Documents\WXWork\1688858253398958\Cache\File\2023-08\autobid\autobid\info\token_info.json"
-class Ads_Api_Token(object):
-
-    def __init__(self, authorization_code='-1', profileId='-1', shop_name='-1') -> None:
-        sub_dir = os.path.abspath(os.path.dirname(__file__))
-        self.return_url = 'https://www.amazon.com/'
-        self.save_json_file_name = r"./token_info.json"# r"{sub_dir}\info\token_info.json".format(sub_dir=sub_dir)
-        self.lwa_info_file_name = r"./lwa_info.json"# r"{sub_dir}\info\lwa_info.json".format(sub_dir=sub_dir)
-        self.headers = {'Content-Type': 'application/x-www-form-urlencoded'}
-        self.authorization_url = 'https://api.amazon.com/auth/o2/token'
-        self.authorization_code = authorization_code
-
-        # self.region = 'NA'
-        lwa_info = self._read_lwa_info()
-        self.lwa_client_id = lwa_info['lwa_client_id']
-        self.lwa_client_secret = lwa_info['lwa_client_secret']
-        self.access_token = self._get_access_token()
-
-        # 检查错误
-        if shop_name == '-1' or profileId == '-1':
-            print('错误:【shop_name或profileId没有初始化】')
-            print('作为广告商,你的客户列表:')
-            self._get_profile()
-            print('\n确认客户区域、名字等,选择name和profileId重新初始化shop_name和profileId')
-            sys.exit()
-        # print(self._get_profileId(name=shop_name),type(self._get_profileId(name=shop_name)))
-        if self._get_profileId(name=shop_name) != profileId:
-            print('错误:【检查profileId与shop_name不匹配】')
-            print('作为广告商,你的客户列表:')
-            self._get_profile()
-
-            print('\n确认客户区域、名字等,选择name和profileId重新初始化shop_name和profileId')
-            sys.exit()
-
-        self.shop_name = shop_name
-        self.profileId = profileId
-
-    def _read_lwa_info(self) -> str:
-        with open(self.lwa_info_file_name, 'r') as file_obj:
-            lwa_info = json.load(file_obj)
-        file_obj.close()
-        return lwa_info
-
-    def _read_token(self) -> str:
-        with open(self.save_json_file_name, 'r') as file_obj:
-            token = json.load(file_obj)
-        file_obj.close()
-        return token
-
-    def _write_token(self, token: dict) -> None:
-        """转换过期时间到秒级时间戳写入token
-
-        Args:
-            token (dict): token
-        """
-        token['expires_in'] += int(time.time())
-        with open(self.save_json_file_name, 'w') as file_obj:
-            json.dump(token, file_obj)
-
-    def _check_token_json(self, token: dict) -> bool:
-        """检查token合法性
-
-        Args:
-            token (dict): token
-
-        Returns:
-            bool: 是否合法
-        """
-        if 'access_token' in token and 'refresh_token' in token and 'expires_in' in token:
-            return True
-        else:
-            self._print_authorization_grant_info(error_type=1)
-
-    def _print_authorization_grant_info(self, error_type='-1'):
-        """打印授权的授权信息,获取授权code
-
-        Args:
-            error_type (str, optional): 0为找不到文件,1为文件内容不通过. Defaults to '-1'.
-        """
-        url = 'https://www.amazon.com/ap/oa?client_id=%s&scope=advertising::campaign_management&response_type=code&redirect_uri=%s' % (
-        self.lwa_client_id, self.return_url)
-        if error_type == 0:
-            print('==' * 10 + '未检测' + self.save_json_file_name + '==' * 10)
-        if error_type == 1:
-            print('==' * 10 + '内容不通过' + self.save_json_file_name + '==' * 10)
-        print('\t\t1.打开登陆地址' + url)
-        print('\t\t2.点击允许并登陆zhangside账号')
-        print('\t\t3.将重定向的url中的code保存下来')
-        print('\t\t4.将code填入初始化Token的authorization_code')
-        print('==' * 30)
-        sys.exit()
-
-    def _first_get_token(self, authorization_code: str) -> str:
-        """从授权的授权code申请token
-
-        Args:
-            authorization_code (str): 授权的授权code
-
-        Returns:
-            str: access_token
-        """
-        data = 'grant_type=authorization_code&code=%s&redirect_uri=%s&client_id=%s&client_secret=%s' % (
-        authorization_code, self.return_url, self.lwa_client_id, self.lwa_client_secret)
-        res = requests.post(self.authorization_url, data=data, headers=self.headers)
-        res = res.json()
-        self._check_token_json(res)
-        self._write_token(res)
-        return res['access_token']
-
-    def _refresh_token(self, limit_time_minute=3) -> str:
-        """刷新token,如果在授权时间还有多余limit_time_minute分钟不刷新直接返回access_token
-
-        Args:
-            limit_time_minute (int, optional): 剩余时间分钟. Defaults to 15.
-
-        Returns:
-            str: access_token
-        """
-        token = self._read_token()
-        self._check_token_json(token)
-        token_timestamp = token['expires_in']
-        if token_timestamp - int(time.time()) > limit_time_minute * 60:
-            return token['access_token']
-        data = 'grant_type=refresh_token&client_id=%s&refresh_token=%s&client_secret=%s' % (
-        self.lwa_client_id, token['refresh_token'], self.lwa_client_secret)
-        res = requests.post(self.authorization_url, data=data, headers=self.headers)
-        res = res.json()
-        self._check_token_json(res)
-        self._write_token(res)
-        return res['access_token']
-
-    def _get_access_token(self) -> str:
-        """根据状态获取token
-
-        Returns:
-            str: access_token
-        """
-        # 检查状态
-        if self.authorization_code == '-1':
-            if not os.path.exists(self.save_json_file_name):
-                self._print_authorization_grant_info(error_type=0)
-            token = self._read_token()
-            self._check_token_json(token)
-            access_token = self._refresh_token()
-            return access_token
-        else:
-            print('填入了code,获取授权的授权,下一次可不用填入code')
-            access_token = self._first_get_token(self.authorization_code)
-            return access_token
-
-    def _get_profileId(self, name):
-        profiles_url = 'https://advertising-api.amazon.com/v2/profiles'
-        data = {
-            'Amazon-Advertising-API-ClientId': self.lwa_client_id,
-            'Authorization': 'Bearer ' + self.access_token
-        }
-        res = requests.get(profiles_url, headers=data)
-        res = res.json()
-        profileId = '-1'
-        for customer_info in res:
-            if customer_info['accountInfo']['name'] == name:
-                profileId = customer_info['profileId']
-        return str(profileId)
-
-    def _get_profile(self):
-        profiles_url = 'https://advertising-api.amazon.com/v2/profiles'
-        data = {
-            'Amazon-Advertising-API-ClientId': self.lwa_client_id,
-            'Authorization': 'Bearer ' + self.access_token
-        }
-        res = requests.get(profiles_url, headers=data)
-        res = res.json()
-        print(res)
-
-
-if __name__ == "__main__":
-    # authorization_code = 'ANzRQnVlaRziQlNxrHGG'
-    access_token = Ads_Api_Token(shop_name = 'ZosiDirect',profileId='3006125408623189')
-    tken = access_token._get_access_token()
-    print(type(tken),tken)
-# {'profileId': 420999963953676,
-#  'countryCode': 'BR',
-#  'currencyCode': 'BRL',
-#  'dailyBudget': 999999999.0,
-#  'timezone': 'America/Sao_Paulo',
-#  'accountInfo': {'marketplaceStringId': 'A2Q3Y263D00KWC',
-#                  'id': 'A252W7I0ACJHS1',
-#                  'type': 'seller',
-#                  'name': 'ZosiDirect',
-#                  'validPaymentMethod': False}}

+ 122 - 44
sync_amz_data/public/amz_ad_client.py

@@ -294,9 +294,21 @@ class SBClient(BaseClient):
                 break
             body["nextToken"] = info["nextToken"]
 
-    def get_keywords(self):
+    def get_keywords(self,**param):
         url_path = "/sb/keywords"
-        return self._request(url_path, method="GET")
+        return self._request(url_path, method="GET",params=param)
+
+    def iter_keywords(self,**param):
+        if "startIndex" not in param:
+            param["startIndex"] = 0
+            param["count"] = 5000
+        while True:
+            info:list = self.get_keywords(**param)
+            # print(info)
+            if len(info) == 0:
+                break
+            param["startIndex"] += 5000
+            yield info
 
     def get_targets(self, **body):
         url_path = "/sb/targets/list"
@@ -385,15 +397,80 @@ class SBClient(BaseClient):
         logger.info(f"解压完成:{de_file}")
         return de_file
 
-    get_groups = get_ad_groups
-    iter_groups = iter_adGroups
-
-
 class SDClient(BaseClient):
     def get_campaigns(self, **params) -> List[dict]:
         url_path = "/sd/campaigns"
         return self._request(url_path, params=params)
 
+    def get_adGroups(self,**params):
+        url_path = '/sd/adGroups'
+        return self._request(url_path, params=params)
+    def iter_adGroups(self,**param):
+        if "startIndex" not in param:
+            param["startIndex"] = 0
+            param["count"] = 5000
+        while True:
+            info:list = self.get_adGroups(**param)
+            # print(info)
+            if len(info) == 0:
+                break
+            param["startIndex"] += 5000
+            yield info
+
+    def get_ads(self,**params):
+        url_path = '/sd/productAds'
+        return self._request(url_path, params=params)
+
+    def iter_ads(self,**param):
+        if "startIndex" not in param:
+            param["startIndex"] = 0
+            param["count"] = 5000
+        while True:
+            info:list = self.get_ads(**param)
+            # print(info)
+            if len(info) == 0:
+                break
+            param["startIndex"] += 5000
+            yield info
+
+    def get_targets(self,**params):
+        url_path = '/sd/targets'
+        return self._request(url_path, params=params)
+
+    def iter_targets(self,**param):
+        if "startIndex" not in param:
+            param["startIndex"] = 0
+            param["count"] = 5000
+        while True:
+            info:list = self.get_targets(**param)
+            # print(info)
+            if len(info) == 0:
+                break
+            param["startIndex"] += 5000
+            yield info
+    def get_budget(self, campaignIds: list):
+        url_path = "/sd/campaigns/budget/usage"
+        body = {"campaignIds": campaignIds}
+        return self._request(url_path, method="POST", body=body)
+
+    def get_target_bidrecommendation(self,tactic:str,products:list,typeFilter:list,themes:dict,locale:str='en_US'):#
+        url_path = '/sd/targets/recommendations'
+        headers ={
+            'Content-Type':"application/vnd.sdtargetingrecommendations.v3.3+json",
+            'Accept':"application/vnd.sdtargetingrecommendations.v3.3+json"
+        }
+        # "tactic":"T00020",
+        # "products":[{"asin":"B00MP57IOY"}],
+        # "typeFilter":["PRODUCT"],
+        # "themes":{"product":[{"name":"TEST","expression":[{"type":"asinBrandSameAs"}]}]}
+        body = {
+            "tactic":tactic,
+            "products":products,
+            "typeFilter":typeFilter,
+            "themes":themes
+                 }
+
+        return self._request(url_path, method="POST", headers=headers,body=body,params={"locale":locale})
 
 class Account(BaseClient):
     def get_portfolios(self):
@@ -404,6 +481,7 @@ class Account(BaseClient):
         yield from self.get_portfolios()
 
 
+
 AccountClient = Account
 
 if __name__ == '__main__':
@@ -418,45 +496,45 @@ if __name__ == '__main__':
     # adGroupId="119753215871672",
     # keyword=["8mp security camera system","8mp security camera system"],
     # matchType=["broad","exact"]))
-    sb = SBClient(**AWS_CREDENTIALS)
-    # print(list(sb.iter_targets()))
-    print(sb.get_keyword_bidrecommendation(**{'campaignId': 27333596383941, 'keywords': [
-        {"matchType": 'broad', "keywordText": "4k security camera system"}]}))
-    print(sb.get_budget([27333596383941]))
-    # sd = SDClient(**AWS_CREDENTIALS)
-    # print(sd.get_campaigns(startIndex=10, count=10))
-
-    sb = SBClient(**AWS_CREDENTIALS)
-    metrics = [
-        'applicableBudgetRuleId',
-        'applicableBudgetRuleName',
-        'attributedConversions14d',
-        'attributedConversions14dSameSKU',
-        'attributedDetailPageViewsClicks14d',
-        'attributedOrderRateNewToBrand14d',
-        'attributedOrdersNewToBrand14d',
-        'attributedOrdersNewToBrandPercentage14d',
-        'attributedSales14d',
-        'attributedSales14dSameSKU',
-        'attributedSalesNewToBrand14d',
-        'attributedSalesNewToBrandPercentage14d',
-        'attributedUnitsOrderedNewToBrand14d',
-        'attributedUnitsOrderedNewToBrandPercentage14d',
-        'campaignBudget',
-        'campaignBudgetType',
-        'campaignId',
-        'campaignName',
-        'campaignRuleBasedBudget',
-        'campaignStatus',
-        'clicks',
-        'cost',
-        'dpv14d',
-        'impressions',
-        'unitsSold14d',
-        'attributedBrandedSearches14d',
-        'topOfSearchImpressionShare']
+
+    sd = SDClient(**AWS_CREDENTIALS)
+
+    # print(sb.get_keyword_bidrecommendation(**{'campaignId': 27333596383941, 'keywords': [
+    #     {"matchType": 'broad', "keywordText": "4k security camera system"}]}))
+    a = list(sd.iter_targets(**{"campaignIdFilter":"257424912382921"})) #list(sd.iter_targets())#
+    print(a,len(a))
+
+    # sb = SBClient(**AWS_CREDENTIALS)
+    # metrics = [
+    #     'applicableBudgetRuleId',
+    #     'applicableBudgetRuleName',
+    #     'attributedConversions14d',
+    #     'attributedConversions14dSameSKU',
+    #     'attributedDetailPageViewsClicks14d',
+    #     'attributedOrderRateNewToBrand14d',
+    #     'attributedOrdersNewToBrand14d',
+    #     'attributedOrdersNewToBrandPercentage14d',
+    #     'attributedSales14d',
+    #     'attributedSales14dSameSKU',
+    #     'attributedSalesNewToBrand14d',
+    #     'attributedSalesNewToBrandPercentage14d',
+    #     'attributedUnitsOrderedNewToBrand14d',
+    #     'attributedUnitsOrderedNewToBrandPercentage14d',
+    #     'campaignBudget',
+    #     'campaignBudgetType',
+    #     'campaignId',
+    #     'campaignName',
+    #     'campaignRuleBasedBudget',
+    #     'campaignStatus',
+    #     'clicks',
+    #     'cost',
+    #     'dpv14d',
+    #     'impressions',
+    #     'unitsSold14d',
+    #     'attributedBrandedSearches14d',
+    #     'topOfSearchImpressionShare']
     # sb.get_report(
     #     record_type="campaigns",
     #     report_date="20231008",
     #     metrics=metrics
-    # )
+    # )