|
@@ -8,6 +8,8 @@ from urllib.parse import urljoin
|
|
|
from typing import List, Literal, Iterable, Iterator
|
|
|
import gzip
|
|
|
from pathlib import Path
|
|
|
+import s3fs
|
|
|
+from s3fs import S3FileSystem
|
|
|
|
|
|
import logging
|
|
|
|
|
@@ -234,7 +236,77 @@ class SPClient(BaseClient):
|
|
|
body = {"adGroupId": adGroupId,
|
|
|
"keywords": keywords}
|
|
|
return self._request(url_path, method="POST", body=body)
|
|
|
+ def get_v3_report(self,
|
|
|
+ groupby:list,
|
|
|
+ columns:list,
|
|
|
+ startDate:str,
|
|
|
+ endDate:str,
|
|
|
+ reportType: Literal['spCampaigns','spAdvertisedProduct' ,'spPurchasedProduct', 'spTargeting', 'spSearchTerm'],
|
|
|
+ timeUnit="DAILY",
|
|
|
+ download=True):
|
|
|
+ """
|
|
|
+ groupby: 聚合条件
|
|
|
+ columns: 需要获取的字段[campaign,adGroup, searchTerm,purchasedAsin,campaignPlacement,targeting,searchTerm,advertiser,asin]
|
|
|
+ """
|
|
|
+ url_path = "/reporting/reports"
|
|
|
+ headers = {
|
|
|
+ "Content-Type":"application/vnd.createasyncreportrequest.v3+json"
|
|
|
+ }
|
|
|
+ body = {
|
|
|
+ "name":"SP campaigns report",
|
|
|
+ "startDate":startDate,
|
|
|
+ "endDate":endDate,
|
|
|
+ "configuration":{
|
|
|
+ "adProduct":"SPONSORED_PRODUCTS",
|
|
|
+ "groupBy":groupby,
|
|
|
+ "columns":columns,
|
|
|
+ "reportTypeId":reportType,
|
|
|
+ "timeUnit":timeUnit,
|
|
|
+ "format":"GZIP_JSON"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ret = self._request(url_path,method="POST",headers=headers,body=body)
|
|
|
+ # print(ret)
|
|
|
+ report_id = ret["reportId"]
|
|
|
+ status = ret["status"]
|
|
|
+ if status == "FAILURE":
|
|
|
+ raise Exception(ret)
|
|
|
+ logger.info(f"创建报告成功:{ret}")
|
|
|
+ while status in ["PROCESSING","PENDING"]:
|
|
|
+ logger.debug(f"报告{report_id}正在处理中...")
|
|
|
+ time.sleep(3)
|
|
|
+ ret = self._request(f"/reporting/reports/{report_id}")
|
|
|
+ print(ret)
|
|
|
+ status = ret["status"]
|
|
|
+ if status == "FAILURE":
|
|
|
+ raise Exception(ret)
|
|
|
+ logger.info(f"报告处理完成:{ret}")
|
|
|
+ if download:
|
|
|
+ pid = self.profile_id
|
|
|
+ reportrel= self.download_v3_report(ret['url'],f"s3://reportforspsbsd/zosi/us/sp/{str(groupby)}_{startDate}_{endDate}_{reportType}_{str(pid)}.json.gz")
|
|
|
+ return reportrel
|
|
|
+ else:
|
|
|
+ return ret
|
|
|
|
|
|
+ def download_v3_report(self, url, file_path: str, decompress: bool = True) -> str:
|
|
|
+ resp = requests.get(url, stream=True, allow_redirects=True)
|
|
|
+ print(resp)
|
|
|
+ kwargs = {'region_name': 'us-east-1', 'endpoint_url': "https://s3.amazonaws.com",
|
|
|
+ 'aws_access_key_id': 'AKIARBAGHTGORIFN44VQ',
|
|
|
+ 'aws_secret_access_key': 'IbEGAU66zOJ9jyvs2TSzv/W6VC6F4nlTmPx2dako'}
|
|
|
+ s3_ = S3FileSystem(client_kwargs=kwargs)
|
|
|
+ # print()
|
|
|
+ with s3_.open(file_path, 'wb') as f:
|
|
|
+ for data in resp.iter_content(chunk_size=10 * 1024):
|
|
|
+ f.write(data)
|
|
|
+ if not decompress:
|
|
|
+ return file_path
|
|
|
+ with s3_.open(file_path, 'rb') as f: # 读取s3数据
|
|
|
+ data = gzip.GzipFile(fileobj=f, mode='rb')
|
|
|
+ de_file = json.load(data)
|
|
|
+ logger.info(f"解压完成:{de_file}")
|
|
|
+ # print(de_file)
|
|
|
+ return de_file
|
|
|
|
|
|
class SBClient(BaseClient):
|
|
|
def get_campaigns(self, **body):
|
|
@@ -334,7 +406,79 @@ class SBClient(BaseClient):
|
|
|
url_path = "/sb/recommendations/bids"
|
|
|
return self._request(url_path, method="POST", body=body)
|
|
|
|
|
|
- def get_report(
|
|
|
+ def get_v3_report(self,
|
|
|
+ groupby:list,
|
|
|
+ columns:list,
|
|
|
+ startDate:str,
|
|
|
+ endDate:str,
|
|
|
+ reportType: Literal['sbCampaigns', 'sbPurchasedProduct', 'sbTargeting', 'sbSearchTerm'],
|
|
|
+ timeUnit="DAILY",
|
|
|
+ download=True):
|
|
|
+ """
|
|
|
+ groupby: 聚合条件
|
|
|
+ columns: 需要获取的字段[campaign,targeting,searchTerm,purchasedAsin]
|
|
|
+ """
|
|
|
+ url_path = "/reporting/reports"
|
|
|
+ headers = {
|
|
|
+ "Content-Type":"application/vnd.createasyncreportrequest.v3+json"
|
|
|
+ }
|
|
|
+ body = {
|
|
|
+ "name":"SB campaigns report",
|
|
|
+ "startDate":startDate,
|
|
|
+ "endDate":endDate,
|
|
|
+ "configuration":{
|
|
|
+ "adProduct":"SPONSORED_BRANDS",
|
|
|
+ "groupBy":groupby,
|
|
|
+ "columns":columns,
|
|
|
+ "reportTypeId":reportType,
|
|
|
+ "timeUnit":timeUnit,
|
|
|
+ "format":"GZIP_JSON"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ret = self._request(url_path,method="POST",headers=headers,body=body)
|
|
|
+ # print(ret)
|
|
|
+ report_id = ret["reportId"]
|
|
|
+ status = ret["status"]
|
|
|
+ if status == "FAILURE":
|
|
|
+ raise Exception(ret)
|
|
|
+ logger.info(f"创建报告成功:{ret}")
|
|
|
+ while status in ["PROCESSING","PENDING"]:
|
|
|
+ logger.debug(f"报告{report_id}正在处理中...")
|
|
|
+ time.sleep(3)
|
|
|
+ ret = self._request(f"/reporting/reports/{report_id}")
|
|
|
+ print(ret)
|
|
|
+ status = ret["status"]
|
|
|
+ if status == "FAILURE":
|
|
|
+ raise Exception(ret)
|
|
|
+ logger.info(f"报告处理完成:{ret}")
|
|
|
+ if download:
|
|
|
+ pid = self.profile_id
|
|
|
+ reportrel= self.download_v3_report(ret['url'],f"s3://reportforspsbsd/zosi/us/sb/{startDate}_{endDate}_{reportType}_{str(pid)}.json.gz")
|
|
|
+ return reportrel
|
|
|
+ else:
|
|
|
+ return ret
|
|
|
+
|
|
|
+ def download_v3_report(self, url, file_path: str, decompress: bool = True) -> str:
|
|
|
+ resp = requests.get(url, stream=True, allow_redirects=True)
|
|
|
+ print(resp)
|
|
|
+ kwargs = {'region_name': 'us-east-1', 'endpoint_url': "https://s3.amazonaws.com",
|
|
|
+ 'aws_access_key_id': 'AKIARBAGHTGORIFN44VQ',
|
|
|
+ 'aws_secret_access_key': 'IbEGAU66zOJ9jyvs2TSzv/W6VC6F4nlTmPx2dako'}
|
|
|
+ s3_ = S3FileSystem(client_kwargs=kwargs)
|
|
|
+ # print()
|
|
|
+ with s3_.open(file_path, 'wb') as f:
|
|
|
+ for data in resp.iter_content(chunk_size=10 * 1024):
|
|
|
+ f.write(data)
|
|
|
+ if not decompress:
|
|
|
+ return file_path
|
|
|
+ with s3_.open(file_path, 'rb') as f: # 读取s3数据
|
|
|
+ data = gzip.GzipFile(fileobj=f, mode='rb')
|
|
|
+ de_file = json.load(data)
|
|
|
+ logger.info(f"解压完成:{de_file}")
|
|
|
+ # print(de_file)
|
|
|
+ return de_file
|
|
|
+
|
|
|
+ def get_v2_report(
|
|
|
self,
|
|
|
record_type: Literal['campaigns', 'adGroups', 'ads', 'targets', 'keywords'],
|
|
|
report_date: str,
|
|
@@ -379,22 +523,33 @@ class SBClient(BaseClient):
|
|
|
raise Exception(ret)
|
|
|
logger.info(f"报告处理完成:{ret}")
|
|
|
if download:
|
|
|
- self.download_report(report_id, str(self.data_path / f"sb_{record_type}.json.gz"))
|
|
|
+ pid = self.profile_id
|
|
|
+ reportrel= self.download_v2_report(report_id, f"s3://reportforspsbsd/zosi/us/sb/{str(report_date)}_{record_type}_{str(pid)}.gz")
|
|
|
+ return reportrel
|
|
|
else:
|
|
|
return ret
|
|
|
|
|
|
- def download_report(self, report_id: str, file_path: str, decompress: bool = True) -> str:
|
|
|
+ def download_v2_report(self, report_id: str, file_path: str, decompress: bool = True) -> str:
|
|
|
url = urljoin(URL_AD_API, f"/v2/reports/{report_id}/download")
|
|
|
resp = requests.get(url, headers=self.auth_headers, stream=True, allow_redirects=True)
|
|
|
logger.info(f"开始下载报告:{report_id}")
|
|
|
- with open(file_path, "wb") as file:
|
|
|
+ kwargs = {'region_name': 'us-east-1', 'endpoint_url': "https://s3.amazonaws.com",
|
|
|
+ 'aws_access_key_id': 'AKIARBAGHTGORIFN44VQ',
|
|
|
+ 'aws_secret_access_key': 'IbEGAU66zOJ9jyvs2TSzv/W6VC6F4nlTmPx2dako'}
|
|
|
+ s3_ = S3FileSystem(client_kwargs=kwargs)
|
|
|
+ # print()
|
|
|
+ with s3_.open(file_path, 'wb') as f:
|
|
|
for data in resp.iter_content(chunk_size=10 * 1024):
|
|
|
- file.write(data)
|
|
|
+ f.write(data)
|
|
|
+
|
|
|
logger.info(f"报告{report_id}下载完成:{file_path}")
|
|
|
if not decompress:
|
|
|
return file_path
|
|
|
- de_file = gz_decompress(file_path)
|
|
|
+ with s3_.open(file_path, 'rb') as f: # 读取s3数据
|
|
|
+ data = gzip.GzipFile(fileobj=f, mode='rb')
|
|
|
+ de_file = json.load(data)
|
|
|
logger.info(f"解压完成:{de_file}")
|
|
|
+ # print(de_file)
|
|
|
return de_file
|
|
|
|
|
|
class SDClient(BaseClient):
|
|
@@ -405,6 +560,7 @@ class SDClient(BaseClient):
|
|
|
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
|
|
@@ -448,6 +604,7 @@ class SDClient(BaseClient):
|
|
|
break
|
|
|
param["startIndex"] += 5000
|
|
|
yield info
|
|
|
+
|
|
|
def get_budget(self, campaignIds: list):
|
|
|
url_path = "/sd/campaigns/budget/usage"
|
|
|
body = {"campaignIds": campaignIds}
|
|
@@ -497,44 +654,40 @@ if __name__ == '__main__':
|
|
|
# keyword=["8mp security camera system","8mp security camera system"],
|
|
|
# matchType=["broad","exact"]))
|
|
|
|
|
|
- sd = SDClient(**AWS_CREDENTIALS)
|
|
|
+ sd = SPClient(**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))
|
|
|
+ # 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
|
|
|
- # )
|
|
|
+ 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']
|
|
|
+ print(sd.get_v3_report(groupby=['campaign','campaignPlacement'],columns=['impressions'],startDate="2023-10-01",endDate="2023-10-01",reportType="spCampaigns"))
|