|
@@ -14,6 +14,7 @@ import datetime
|
|
|
from sqlalchemy import create_engine
|
|
|
from db_config import *
|
|
|
import traceback
|
|
|
+import uuid
|
|
|
|
|
|
|
|
|
class AiStrategyRequestParse(tornado.web.RequestHandler):
|
|
@@ -28,7 +29,29 @@ class AiStrategyRequestParse(tornado.web.RequestHandler):
|
|
|
|
|
|
# 1、新增广告组操作
|
|
|
if data["operation_type"] == "add":
|
|
|
- inst = ParseModifyRequest(data)
|
|
|
+ inst = ParseAddCampaignOrAddGroupRequest(data)
|
|
|
+ inst.get_advertiser_strategy_info()
|
|
|
+ inst.write_intelligence_strategy_table()
|
|
|
+ if inst.campaign_id == "" or inst.campaign_id is None:
|
|
|
+ if inst.add_campaign() == -1:
|
|
|
+ self.write(json.dumps({"message": "广告计划创建失败"}))
|
|
|
+ self.flush()
|
|
|
+ return
|
|
|
+
|
|
|
+ inst.get_group_dict()
|
|
|
+ res = inst.res_data
|
|
|
+ url = ""
|
|
|
+ request = requests.post(url, res)
|
|
|
+ # TODO 先测试,如果有问题,让他们返回一个true,或者设置timeout=1,
|
|
|
+ res_data = simplejson.loads(request.text)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ # 返回接口结果
|
|
|
+ result_str = json.dumps(res)
|
|
|
+ self.write(result_str)
|
|
|
+ self.flush()
|
|
|
|
|
|
|
|
|
# 该类解析的是 手动请求的新增广告计划或者新增广告组的数据
|
|
@@ -38,7 +61,9 @@ class ParseAddCampaignOrAddGroupRequest(object):
|
|
|
self.video = self.request_data['video']
|
|
|
self.account_id = self.request_data['account_id']
|
|
|
self.campaign_info = self.request_data['campaign_info']
|
|
|
+ self.campaign_id = self.request_data['campaign_info'].get('campaign_id', None)
|
|
|
self.group_info = self.request_data['group_info']
|
|
|
+ self.creative_info = self.request_data['creative_info']
|
|
|
self.operation_type = self.request_data['operation_type']
|
|
|
|
|
|
self.advertiser_strategy_id = None
|
|
@@ -69,24 +94,20 @@ class ParseAddCampaignOrAddGroupRequest(object):
|
|
|
请求信息写入 ctop_ai_kuaishou_intelligence_strategy 表中
|
|
|
:return:
|
|
|
"""
|
|
|
+ self.ai_strategy_id = uuid.uuid4()
|
|
|
intelligence_strategy_dict = \
|
|
|
- {'advertiser_strategy_id': self.advertiser_strategy_id,
|
|
|
- 'account_id': self.account_id,
|
|
|
- 'ai_strategy_request_content': self.request_data,
|
|
|
- 'create_time': datetime.datetime.now()}
|
|
|
+ {
|
|
|
+ 'ai_strategy_id': self.ai_strategy_id,
|
|
|
+ 'advertiser_strategy_id': self.advertiser_strategy_id,
|
|
|
+ 'account_id': self.account_id,
|
|
|
+ 'ai_strategy_request_content': self.request_data,
|
|
|
+ 'create_time': datetime.datetime.now()
|
|
|
+ }
|
|
|
|
|
|
df = pd.DataFrame.from_dict(intelligence_strategy_dict, orient='index').T
|
|
|
engine = create_engine(db_con_str, connect_args={'charset': 'utf8'})
|
|
|
df.to_sql(name="ctop_ai_kuaishou_intelligence_strategy", con=engine, if_exists='append', index=False)
|
|
|
|
|
|
- # 获取新插入的 intelligence_strategy 的唯一标识ID
|
|
|
- # TODO 这个方法的缺点是不适合高并发。如果同时插入的时候返回的值可能不准确。
|
|
|
- sql = """
|
|
|
- select max(id) from ctop_ai_kuaishou_intelligence_strategy where account_id = %d
|
|
|
- """ % self.account_id
|
|
|
- df = pd.read_sql(sql,engine)
|
|
|
- self.ai_strategy_id = df['id'].values[0]
|
|
|
-
|
|
|
# 如果手动请求的数据结构中,"campaign" 中的 campaign_id 为空则调用该新增计划方法
|
|
|
def add_campaign(self):
|
|
|
"""
|
|
@@ -98,58 +119,209 @@ class ParseAddCampaignOrAddGroupRequest(object):
|
|
|
# TODO 写入日志信息
|
|
|
return -1
|
|
|
|
|
|
-
|
|
|
-
|
|
|
# 3、从请求的信息中更新计划层级信息
|
|
|
# if len(self.request_data['campaign']) > 0:
|
|
|
# for key, value in self.request_data['campaign'].items():
|
|
|
# self.campaign_dict.update({key: value})
|
|
|
|
|
|
- create_campaign_req_data = {'account_id': self.account_id,
|
|
|
+ create_campaign_req_data = {
|
|
|
+ 'account_id': self.account_id,
|
|
|
'campaign_name': self.campaign_info['campaign_name'],
|
|
|
- 'type': self.campaign_info['campaign_type']}
|
|
|
+ 'type': self.campaign_info['campaign_type']
|
|
|
+ }
|
|
|
url = "http://192.168.1.8:8080/jeecg-boot//jeecg-boot/kuaishou/create/campaignCreate"
|
|
|
request = requests.post(url, create_campaign_req_data)
|
|
|
res_data = simplejson.loads(request.text)
|
|
|
|
|
|
if res_data['code'] == 0:
|
|
|
- campaign_info_to_db = {'account_id': self.account_id,
|
|
|
- 'ai_strategy_id': 1,
|
|
|
+ self.campaign_id = res_data['data']['campaign_id']
|
|
|
+ campaign_info_to_db = {
|
|
|
+ 'uid': uuid.uuid4(),
|
|
|
+ 'account_id': self.account_id,
|
|
|
+ 'ai_strategy_id': self.ai_strategy_id,
|
|
|
'campaign_name': self.campaign_info['campaign_name'],
|
|
|
- 'campaign_id': res_data['data']['campaign_id'],
|
|
|
+ 'campaign_id': self.campaign_id,
|
|
|
'campaign_type': self.campaign_info['campaign_type'],
|
|
|
'operation_type': self.operation_type,
|
|
|
'campaign_create_time': res_data['data']['campaign_create_time'],
|
|
|
- 'create_time': datetime.datetime.now()}
|
|
|
+ 'create_time': datetime.datetime.now()
|
|
|
+ }
|
|
|
df = pd.DataFrame.from_dict(campaign_info_to_db, orient='index').T
|
|
|
engine = create_engine(db_con_str, connect_args={'charset': 'utf8'})
|
|
|
df.to_sql(name="ctop_ai_kuaishou_campaign_level_operation_record", con=engine, if_exists='append', index=False)
|
|
|
-
|
|
|
else:
|
|
|
# TODO 写入计划创建失败的原因
|
|
|
return -1
|
|
|
|
|
|
- # 写入数据库 ctop_ai_kuaishou_campaign_level_operation_record
|
|
|
+ def get_group_dict(self):
|
|
|
+ """
|
|
|
+ 拼接组和创意层级参数
|
|
|
+ 写入数据库
|
|
|
+ 返回 table_id
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+ # 一个视频一个广告组
|
|
|
+ # 先写入数据库,然后读取数据库组装参数
|
|
|
|
|
|
+ # 1、TODO 校验请求信息中 有没有 与客户策略信息 中存在冲突的地方 -- 暂时不实现
|
|
|
+ # 客户策略 和 请求信息 都有值 才会进行校验比对操作 -- 不得高于,不得不等于,不得超过集合
|
|
|
+ # 因此分为3类 字段
|
|
|
+ # is_equal_cols = ['template_id','bid_type']
|
|
|
+ # is_less_than_cols = []
|
|
|
+ # is_contain_cols = []
|
|
|
+ #
|
|
|
+ # for col in is_equal_cols:
|
|
|
+ # if (self.advertiser_strategy[col] is not None) and \
|
|
|
+ # (self.group_info.get(col, None) is not None) and \
|
|
|
+ # (self.group_info.get(col) != self.advertiser_strategy[col]):
|
|
|
+ # return -1
|
|
|
+ #
|
|
|
+ # for col in is_less_than_cols:
|
|
|
+ # if (self.advertiser_strategy[col] is not None) and \
|
|
|
+ # (self.group_info.get(col, None) is not None) and \
|
|
|
+ # (self.group_info.get(col) > self.advertiser_strategy[col]):
|
|
|
+ # return -1
|
|
|
+ #
|
|
|
+ # for col in is_contain_cols:
|
|
|
+ # if (self.advertiser_strategy[col] is not None) and \
|
|
|
+ # (self.group_info.get(col, None) is not None) and \
|
|
|
+ # (self.group_info.get(col) > self.advertiser_strategy[col]):
|
|
|
+ # return -1
|
|
|
|
|
|
+ basic_group_info = {'template_id': self.advertiser_strategy['template_id'],
|
|
|
+ 'bid_type': self.advertiser_strategy['bid_type'],
|
|
|
+ 'use_app_market': self.advertiser_strategy['use_app_market'],
|
|
|
+ 'app_store': self.advertiser_strategy['app_store'],
|
|
|
+ 'bid': self.advertiser_strategy['bid'],
|
|
|
+ 'cpa_bid': self.advertiser_strategy['cpa_bid'],
|
|
|
+ 'smart_bid': self.advertiser_strategy['smart_bid'],
|
|
|
+ 'ocpx_action_type': self.advertiser_strategy['ocpx_action_type'],
|
|
|
+ 'deep_conversion_type': self.advertiser_strategy['deep_conversion_type'],
|
|
|
+ 'roi_ratio': self.advertiser_strategy['roi_ratio'],
|
|
|
+ 'scene_id': self.advertiser_strategy['scene_id'],
|
|
|
+ 'unit_type': self.advertiser_strategy['unit_type'],
|
|
|
+ 'begin_time': self.advertiser_strategy['begin_time'],
|
|
|
+ 'end_time': self.advertiser_strategy['end_time'],
|
|
|
+ 'schedule_time': self.advertiser_strategy['schedule_time'],
|
|
|
+ 'day_budget': self.advertiser_strategy['day_budget'],
|
|
|
+ 'day_budget_schedule': self.advertiser_strategy['day_budget_schedule'],
|
|
|
+ 'convert_id': self.advertiser_strategy['convert_id'],
|
|
|
+ 'url_type': self.advertiser_strategy['url_type'],
|
|
|
+ 'web_uri_type': self.advertiser_strategy['web_uri_type'],
|
|
|
+ 'url': self.advertiser_strategy['url'],
|
|
|
+ 'schema_uri': self.advertiser_strategy['schema_uri'],
|
|
|
+ 'app_id': self.advertiser_strategy['app_id'],
|
|
|
+ 'show_mode': self.advertiser_strategy['show_mode'],
|
|
|
+ 'speed': self.advertiser_strategy['speed'],
|
|
|
+ 'site_type': self.advertiser_strategy['site_type'],
|
|
|
+ 'gift_data': self.advertiser_strategy['gift_data'],
|
|
|
+ 'video_landing_page': self.advertiser_strategy['video_landing_page'],
|
|
|
+ 'auto_target': self.advertiser_strategy['auto_target'],
|
|
|
+ 'auto_create_photo': self.advertiser_strategy['auto_create_photo'],
|
|
|
+ 'region': self.advertiser_strategy['region'],
|
|
|
+ 'district_ids': self.advertiser_strategy['district_ids'],
|
|
|
+ 'user_type': self.advertiser_strategy['user_type'],
|
|
|
+ 'age_min': self.advertiser_strategy['age_min'],
|
|
|
+ 'age_max': self.advertiser_strategy['age_max'],
|
|
|
+ 'ages_range': self.advertiser_strategy['ages_range'],
|
|
|
+ 'gender': self.advertiser_strategy['gender'],
|
|
|
+ 'platform_os': self.advertiser_strategy['platform_os'],
|
|
|
+ 'android_osv': self.advertiser_strategy['android_osv'],
|
|
|
+ 'ios_osv': self.advertiser_strategy['ios_osv'],
|
|
|
+ 'network': self.advertiser_strategy['network'],
|
|
|
+ 'device_brand': self.advertiser_strategy['device_brand'],
|
|
|
+ 'device_price': self.advertiser_strategy['device_price'],
|
|
|
+ 'business_interest_type': self.advertiser_strategy['business_interest_type'],
|
|
|
+ 'business_interest': self.advertiser_strategy['business_interest'],
|
|
|
+ 'fans_star': self.advertiser_strategy['fans_star'],
|
|
|
+ 'interest_video': self.advertiser_strategy['interest_video'],
|
|
|
+ 'app_interest': self.advertiser_strategy['app_interest'],
|
|
|
+ 'app_ids': self.advertiser_strategy['app_ids'],
|
|
|
+ 'filter_converted_level': self.advertiser_strategy['filter_converted_level'],
|
|
|
+ 'population': self.advertiser_strategy['population'],
|
|
|
+ 'exclude_population': self.advertiser_strategy['exclude_population'],
|
|
|
+ 'paid_audience': self.advertiser_strategy['paid_audience'],
|
|
|
+ 'is_open': self.advertiser_strategy['is_open'],
|
|
|
+ 'no_age_break': self.advertiser_strategy['no_age_break'],
|
|
|
+ 'no_gender_break': self.advertiser_strategy['no_gender_break'],
|
|
|
+ 'no_area_break': self.advertiser_strategy['no_area_break'],
|
|
|
+ 'behavior_interest': self.advertiser_strategy['behavior_interest']}
|
|
|
|
|
|
+ # 3、从请求的信息中更新计划层级信息
|
|
|
+ if len(self.group_info) > 0:
|
|
|
+ for key, value in self.group_info.items():
|
|
|
+ basic_group_info.update({key: value})
|
|
|
|
|
|
- # 4、将计划层级的信息添加到 返回数据中
|
|
|
- self.res_data['campaign'] = self.campaign_dict
|
|
|
+ self.res_data['group_list'] = []
|
|
|
+ group_cnt = 1
|
|
|
+ for video in self.video:
|
|
|
+ single_group_info = {'group_uuid': uuid.uuid4()}
|
|
|
+ single_group_info.update(basic_group_info)
|
|
|
+ single_group_info['unit_name'] = self.group_info['unit_name'] + '-' + str(group_cnt)
|
|
|
|
|
|
+ # 组信息写入数据表中
|
|
|
+ single_group_info_to_db = single_group_info.copy()
|
|
|
+ single_group_info_to_db['ai_strategy_id'] = self.ai_strategy_id
|
|
|
+ single_group_info_to_db['account_id'] = self.account_id
|
|
|
+ single_group_info_to_db['campaign_id'] = self.campaign_id
|
|
|
+ single_group_info_to_db['create_time'] = datetime.datetime.now()
|
|
|
+ single_group_info_to_db['operation_type'] = self.operation_type
|
|
|
+ df = pd.DataFrame.from_dict(single_group_info_to_db, orient='index').T
|
|
|
+ engine = create_engine(db_con_str, connect_args={'charset': 'utf8'})
|
|
|
+ df.to_sql(name="ctop_ai_kuaishou_unit_level_operation_record",
|
|
|
+ con=engine,
|
|
|
+ if_exists='append',
|
|
|
+ index=False)
|
|
|
|
|
|
- def get_group_dict(self):
|
|
|
- """
|
|
|
- 拼接组和创意层级参数
|
|
|
- :return:
|
|
|
- """
|
|
|
+ single_group_info['creative_list'] = []
|
|
|
+ group_cnt += 1
|
|
|
|
|
|
- def update_intelligence_strategy_table(self):
|
|
|
- """
|
|
|
- 拼接完成的信息更新到 ctop_ai_kuaishou_intelligence_strategy 表中
|
|
|
- :return:
|
|
|
- """
|
|
|
- pass
|
|
|
+ creative_cnt = 1
|
|
|
+ for image in video['imageList']:
|
|
|
+ single_creative_info = {
|
|
|
+ 'creative_uuid': uuid.uuid4(),
|
|
|
+ 'is_sticky': 0,
|
|
|
+ 'creative_name': self.creative_info['creative_name'] + '_' + str(creative_cnt),
|
|
|
+ 'photo_id': video['photo_id'],
|
|
|
+ 'image_md5': image, # TODO 需要和蒙蒙确认字段名称
|
|
|
+ 'image_tokens': self.creative_info.get('image_tokens'),
|
|
|
+ 'action_bar_text': self.creative_info['action_bar_text'],
|
|
|
+ 'description': self.creative_info['description'],
|
|
|
+ 'short_slogan': self.creative_info.get('short_slogan'),
|
|
|
+ 'sticker_title': self.creative_info.get('sticker_title'),
|
|
|
+ 'overlay_type': self.creative_info.get('overlay_type'),
|
|
|
+ 'expose_tag': self.creative_info.get('expose_tag'),
|
|
|
+ 'new_expose_tag': self.creative_info.get('new_expose_tag'),
|
|
|
+ 'site_id': self.creative_info.get('site_id'),
|
|
|
+ 'click_track_url': self.advertiser_strategy.get('click_track_url'),
|
|
|
+ 'impression_url': self.advertiser_strategy.get('impression_url'),
|
|
|
+ 'ad_photo_played_t3s_url': self.advertiser_strategy.get('ad_photo_played_t3s_url'),
|
|
|
+ 'actionbar_click_url': self.advertiser_strategy.get('actionbar_click_url'),
|
|
|
+ 'creative_category': self.creative_info.get('creative_category'),
|
|
|
+ 'creative_tag': self.creative_info.get('creative_tag')}
|
|
|
+
|
|
|
+ single_group_info.creative_list.append(single_creative_info)
|
|
|
+
|
|
|
+ # 创意层级写入数据表中
|
|
|
+ single_creative_info_to_db = single_creative_info.copy()
|
|
|
+ single_creative_info_to_db['ai_strategy_id'] = self.ai_strategy_id
|
|
|
+ single_creative_info_to_db['account_id'] = self.account_id
|
|
|
+ single_creative_info_to_db['campaign_id'] = self.campaign_id
|
|
|
+ single_creative_info_to_db['create_time'] = datetime.datetime.now()
|
|
|
+ single_creative_info_to_db['operation_type'] = self.operation_type
|
|
|
+ df = pd.DataFrame.from_dict(single_creative_info_to_db, orient='index').T
|
|
|
+ engine = create_engine(db_con_str, connect_args={'charset': 'utf8'})
|
|
|
+ df.to_sql(name="ctop_ai_kuaishou_creative_level_operation_record",
|
|
|
+ con=engine,
|
|
|
+ if_exists='append',
|
|
|
+ index=False)
|
|
|
+
|
|
|
+ creative_cnt += 1
|
|
|
+ # 组和创意信息添加到最终返回数据 group_list 中
|
|
|
+ self.res_data['group_list'].append(single_group_info)
|
|
|
+
|
|
|
+ self.res_data['account_id'] = self.account_id
|
|
|
+ self.res_data['campaign_id'] = self.campaign_id
|
|
|
|
|
|
|
|
|
# TODO 修改操作
|