|
@@ -0,0 +1,160 @@
|
|
|
+import datetime
|
|
|
+import json
|
|
|
+import traceback
|
|
|
+import pandas as pd
|
|
|
+import requests
|
|
|
+import tornado.web
|
|
|
+from db_config import *
|
|
|
+
|
|
|
+
|
|
|
+class AiCheckAndUpTOFullCreative(tornado.web.RequestHandler):
|
|
|
+ """
|
|
|
+ 每天22:00 调用该任务,检查当天创意是否创建达到上限,否则使用历史跑量素材填满
|
|
|
+ """
|
|
|
+ def initialize(self, logger):
|
|
|
+ self.logger = logger
|
|
|
+
|
|
|
+ def post(self):
|
|
|
+ data = self.request.body
|
|
|
+ data = str(data, 'utf8')
|
|
|
+ data = json.loads(data, encoding='utf8')
|
|
|
+ self.logger.info("*************************************** NEW REQUEST ***************************************")
|
|
|
+ self.logger.info("raw data from request is %s" % data)
|
|
|
+
|
|
|
+ account_id = data.get('account_id')
|
|
|
+ try:
|
|
|
+ inst = GetRequestData(account_id)
|
|
|
+ if inst.video_cnt == 0:
|
|
|
+ self.logger.info("创意已经建满,不需要补充素材!")
|
|
|
+ self.write(json.dumps("message: 创意已经建满,不需要补充素材!"))
|
|
|
+ self.flush()
|
|
|
+ else:
|
|
|
+ inst.get_video_info()
|
|
|
+ if inst.video.get('code', None) != 0:
|
|
|
+ self.logger.info("没有成功获取到视频信息: %s !" % inst.video.get('message'))
|
|
|
+ self.write(json.dumps("message: %s" % inst.video.get('message')))
|
|
|
+ self.flush()
|
|
|
+ else:
|
|
|
+ inst.get_request_data()
|
|
|
+ request = requests.post(ai_strategy_request_url, inst.data)
|
|
|
+ self.logger.info("ai策略的返回信息:%s" % request.text)
|
|
|
+ self.write(request.text)
|
|
|
+ self.flush()
|
|
|
+ except Exception:
|
|
|
+ self.logger.error(traceback.format_exc())
|
|
|
+ self.write(json.dumps(traceback.format_exc()))
|
|
|
+ self.flush()
|
|
|
+
|
|
|
+
|
|
|
+class GetRequestData(object):
|
|
|
+ def __init__(self, account_id):
|
|
|
+ self.video = None
|
|
|
+ self.account_id = account_id
|
|
|
+ self.campaign_id = None
|
|
|
+ self.data = None
|
|
|
+ self.campaign_name = None
|
|
|
+ self.group_name = None
|
|
|
+ self.video_cnt = 0
|
|
|
+ self.get_campaign_id()
|
|
|
+ self.get_video_cnt()
|
|
|
+ self.get_campaign_and_group_name_rule()
|
|
|
+
|
|
|
+ def get_campaign_id(self):
|
|
|
+ """
|
|
|
+ 获取当天计划中包含“跑量素材”计划的,计划id
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+ start_time = (datetime.date.today()).strftime('%Y-%m-%d %H:%M:%S')
|
|
|
+ end_time = (datetime.datetime.now()).strftime('%Y-%m-%d %H:%M:%S')
|
|
|
+ sql = """
|
|
|
+ select campaign_id, campaign_name from ctop_kuaishou_campaign
|
|
|
+ where account_id = %s
|
|
|
+ and put_create_time >= '%s'
|
|
|
+ and put_create_time <= '%s'
|
|
|
+ """ % (self.account_id, start_time, end_time)
|
|
|
+ df = pd.read_sql(sql, engine)
|
|
|
+ for row in df.itertuples():
|
|
|
+ if '跑量素材' in getattr(row, 'campaign_name'):
|
|
|
+ self.campaign_id = getattr(row, 'campaign_id')
|
|
|
+ break
|
|
|
+
|
|
|
+ def get_video_cnt(self):
|
|
|
+ """
|
|
|
+ 获取需要补充的视频个数
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+ # 从客户策略表中获取该账户下 每个素材搭配的封面个数, 来计算需要补充的素材个数
|
|
|
+ sql = """
|
|
|
+ select image_cnt from ctop_ai_kuaishou_advertiser_strategy
|
|
|
+ where account_id = %s
|
|
|
+ and status = 1
|
|
|
+ limit 1
|
|
|
+ """ % self.account_id
|
|
|
+ df = pd.read_sql(sql, engine)
|
|
|
+ image_cnt = df['image_cnt'].values[0]
|
|
|
+
|
|
|
+ # 从 ctop_kuaishou_creative 获取当天该账户到此刻 已经创建的创意个数
|
|
|
+ start_time = (datetime.date.today()).strftime('%Y-%m-%d %H:%M:%S')
|
|
|
+ end_time = (datetime.datetime.now()).strftime('%Y-%m-%d %H:%M:%S')
|
|
|
+ sql = """
|
|
|
+ select count(1) creative_cnt from ctop_kuaishou_creative
|
|
|
+ where account_id = %s
|
|
|
+ and creative_id is not NULL
|
|
|
+ and creative_create_time <= '%s'
|
|
|
+ and creative_create_time >= '%s'
|
|
|
+ """ % (self.account_id, end_time, start_time)
|
|
|
+ df = pd.read_sql(sql, engine)
|
|
|
+ creative_cnt = df['creative_cnt'].values[0]
|
|
|
+ if creative_cnt >= 2000:
|
|
|
+ self.video_cnt = 0
|
|
|
+ else:
|
|
|
+ self.video_cnt = (2000-creative_cnt) // image_cnt
|
|
|
+
|
|
|
+ def get_video_info(self):
|
|
|
+ now = datetime.datetime.now()
|
|
|
+ video_request_data = {
|
|
|
+ "accountId": self.account_id,
|
|
|
+ "num": self.video_cnt,
|
|
|
+ "startTime": (now + datetime.timedelta(days=-2*high_quality_video_days)).strftime("%Y-%m-%d"),
|
|
|
+ "endTime": (now + datetime.timedelta(days=-high_quality_video_days)).strftime("%Y-%m-%d")
|
|
|
+ }
|
|
|
+ request = requests.post(get_historical_high_quality_video_url,
|
|
|
+ headers=headers,
|
|
|
+ data=json.JSONEncoder().encode(video_request_data))
|
|
|
+ self.video = request
|
|
|
+
|
|
|
+ def get_campaign_and_group_name_rule(self):
|
|
|
+ sql = """
|
|
|
+ select campaign_name, unit_name
|
|
|
+ from ctop_ai_kuaishou_advertiser_strategy
|
|
|
+ where account_id = %d
|
|
|
+ and status = 1
|
|
|
+ limit 1
|
|
|
+ """ % self.account_id
|
|
|
+ df = pd.read_sql(sql, engine)
|
|
|
+ self.campaign_name = df['campaign_name'].values[0]
|
|
|
+ self.group_name = df['unit_name'].values[0]
|
|
|
+
|
|
|
+ def get_request_data(self):
|
|
|
+ self.data = {
|
|
|
+ "video": self.video['data'],
|
|
|
+ "operation_type": 1,
|
|
|
+ "account_id": self.account_id,
|
|
|
+ "ai_strategy_remark": "跑量素材",
|
|
|
+ "campaign_info":
|
|
|
+ {
|
|
|
+ "campaign_id": self.campaign_id,
|
|
|
+ "campaign_name": self.campaign_name.replace('自定义', '跑量素材')
|
|
|
+ + str(datetime.datetime.now())
|
|
|
+ },
|
|
|
+ 'group_info':
|
|
|
+ {
|
|
|
+ 'group_name': self.group_name.replace('自定义', '跑量素材')
|
|
|
+ + str(datetime.datetime.now()),
|
|
|
+ 'begin_time': str(datetime.date.today())
|
|
|
+ },
|
|
|
+ 'creative_info':
|
|
|
+ {
|
|
|
+ 'is_sticky': 0
|
|
|
+ }
|
|
|
+ }
|