ai_strategy_request_func.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. import datetime
  2. import json
  3. import traceback
  4. import uuid
  5. from logging.handlers import TimedRotatingFileHandler
  6. import pandas as pd
  7. import pymysql
  8. import requests
  9. from utils.BaseClass import *
  10. from utils.DataBaseConfig import *
  11. from utils.LogConfig import *
  12. from utils.UrlConfig import *
  13. log_handler = TimedRotatingFileHandler("logs/ai_strategy_request/ai_strategy_request.log",
  14. when="midnight", backupCount=100)
  15. log_handler.setFormatter(log_formatter)
  16. logger = logging.getLogger('ai_strategy_request_logger')
  17. logger.addHandler(log_handler)
  18. logger.setLevel(logging.DEBUG)
  19. print('id of ai_strategy_request_logger %s' % id(logger))
  20. def ai_strategy_request_parse(data):
  21. """
  22. :param data:
  23. :return:
  24. """
  25. if data["operation_type"] == 1:
  26. inst = ParseAddCampaignOrAddGroupRequest(data)
  27. inst.get_advertiser_strategy_info()
  28. inst.write_intelligence_strategy_table()
  29. if inst.campaign_id == "" or inst.campaign_id is None:
  30. if inst.add_campaign() == -1:
  31. return {'code': -2, 'message': '广告计划创建失败!'}
  32. inst.assemble_group_and_creative_params()
  33. create_group_and_creative_res = inst.res_data
  34. inst.update_intelligence_strategy_table()
  35. logger.info("create group and creative request info: %s" % create_group_and_creative_res)
  36. request = requests.post(create_group_and_creative_url,
  37. headers=headers,
  38. data=json.JSONEncoder().encode(create_group_and_creative_res)
  39. )
  40. response_data = json.loads(request.text)
  41. logger.info("请求返回:%s" % response_data)
  42. return {'code': 0, 'message': response_data}
  43. else:
  44. return {'code': -1, 'message': '暂时不支持非新增的操作请求!'}
  45. # 该类解析的是 手动请求的新增广告计划或者新增广告组的数据
  46. class ParseAddCampaignOrAddGroupRequest(object):
  47. def __init__(self, request_data):
  48. self.ai_strategy_uuid = str(uuid.uuid4())
  49. self.request_data = request_data
  50. self.video = self.request_data['video']
  51. self.account_id = self.request_data['account_id']
  52. self.campaign_info = self.request_data['campaign_info']
  53. self.campaign_id = self.request_data['campaign_info'].get('campaign_id', None)
  54. self.group_info = self.request_data.get('group_info', None)
  55. self.creative_info = self.request_data.get('creative_info',None)
  56. self.operation_type = self.request_data['operation_type']
  57. self.advertiser_strategy_id = None
  58. self.advertiser_strategy = {}
  59. self.res_data = {}
  60. def get_advertiser_strategy_info(self):
  61. """
  62. 获取指定账户下客户的策略信息
  63. 为后续的写入库表,校验一致性做准备
  64. :return:
  65. """
  66. sql = """
  67. select *
  68. from ctop_ai_kuaishou_advertiser_strategy
  69. where account_id = %d
  70. and status = 1
  71. limit 1
  72. """ % self.account_id
  73. advertiser_strategy_df = pd.read_sql(sql, engine)
  74. self.advertiser_strategy_id = advertiser_strategy_df['id'].values[0]
  75. self.advertiser_strategy = advertiser_strategy_df.T.to_dict()[0]
  76. def write_intelligence_strategy_table(self):
  77. """
  78. 请求信息写入 ctop_ai_kuaishou_intelligence_strategy 表中
  79. :return:
  80. """
  81. intelligence_strategy_dict = \
  82. {
  83. 'ai_strategy_uuid': self.ai_strategy_uuid,
  84. 'advertiser_strategy_id': self.advertiser_strategy_id,
  85. 'account_id': self.account_id,
  86. 'ai_strategy_receive_content': str(self.request_data),
  87. 'ai_strategy_remark': self.request_data['ai_strategy_remark'],
  88. 'create_time': datetime.datetime.now()
  89. }
  90. df = pd.DataFrame.from_dict(intelligence_strategy_dict, orient='index').T
  91. df.to_sql(name="ctop_ai_kuaishou_intelligence_strategy", con=engine, if_exists='append', index=False)
  92. def update_intelligence_strategy_table(self):
  93. """
  94. 拼装之后的json, 更新到 ai_strategy_request_content
  95. :return:
  96. """
  97. db_con = pymysql.connect(host=host,
  98. port=port,
  99. user=user,
  100. password=passwd,
  101. database=db,
  102. charset=charset)
  103. cursor = db_con.cursor()
  104. cursor.execute("""UPDATE ctop_ai_kuaishou_intelligence_strategy
  105. SET ai_strategy_request_content= %s
  106. WHERE ai_strategy_uuid = %s""", (str(self.res_data), self.ai_strategy_uuid))
  107. db_con.commit()
  108. db_con.close()
  109. # 如果手动请求的数据结构中,"campaign" 中的 campaign_id 为空则调用该新增计划方法
  110. def add_campaign(self):
  111. """
  112. 新增广告计划, 创建成功之后写入计划层级操作表中
  113. :return:
  114. """
  115. create_campaign_req_data = \
  116. {'account_id': self.account_id,
  117. 'campaign_name': self.campaign_info['campaign_name'],
  118. 'type': self.advertiser_strategy['campaign_type']}
  119. request = requests.post(url=create_campaign_url,
  120. headers=headers,
  121. data=json.JSONEncoder().encode(create_campaign_req_data))
  122. res_data = json.loads(request.text)
  123. # res_data = {
  124. # "code": 0,
  125. # "data": {
  126. # "account_id": 23212,
  127. # "campaign_id": 30956133,
  128. # "campaign_create_time": "2021-01-13 13:50:16"
  129. # },
  130. # "message": "SUCCESS"}
  131. if res_data['code'] == 0:
  132. self.campaign_id = res_data['data']['campaign_id']
  133. campaign_info_to_db = {
  134. 'campaign_uuid': str(uuid.uuid4()),
  135. 'account_id': self.account_id,
  136. 'ai_strategy_uuid': self.ai_strategy_uuid,
  137. 'campaign_name': self.campaign_info['campaign_name'],
  138. 'campaign_id': self.campaign_id,
  139. 'campaign_type': self.advertiser_strategy['campaign_type'],
  140. 'operation_type': self.operation_type,
  141. 'campaign_create_time': res_data['data']['campaign_create_time'],
  142. 'create_time': datetime.datetime.now()
  143. }
  144. df = pd.DataFrame.from_dict(campaign_info_to_db, orient='index').T
  145. df.to_sql(name="ctop_ai_kuaishou_campaign_level_operation_record",
  146. con=engine,
  147. if_exists='append',
  148. index=False)
  149. else:
  150. logger.info("广告计划创建失败:%s, ai_strategy_uuid is %s" %
  151. (res_data['message'], self.ai_strategy_uuid))
  152. return -1
  153. def assemble_group_and_creative_params(self):
  154. """
  155. 拼接组和创意层级参数
  156. 写入数据库
  157. :return:
  158. """
  159. # 1、组层级基本信息
  160. drop_cols = ['id', 'account_id', 'status', 'campaign_type', 'campaign_name',
  161. 'creative_name', 'action_bar_text', 'description', 'short_slogan',
  162. 'sticker_title', 'overlay_type', 'expose_tag', 'new_expose_tag', 'site_id',
  163. 'click_track_url', 'impression_url', 'ad_photo_played_t3s_url', 'actionbar_click_url',
  164. 'creative_category', 'creative_tag', 'image_cnt',
  165. 'create_time', 'effective_time', 'expiry_time']
  166. group_cols_to_list = ['app_store', 'scene_id', 'region', 'district_ids', 'ages_range', 'device_brand',
  167. 'device_price', 'business_interest', 'fans_star', 'interest_video', 'app_interest',
  168. 'app_ids', 'population', 'exclude_population', 'paid_audience', 'behavior_interest']
  169. basic_group_info = self.advertiser_strategy.copy()
  170. for col in drop_cols:
  171. del basic_group_info[col]
  172. # 3、从请求的信息中更新组层级信息, 如组的名称、测试定向、测试出价等, update客户策略信息
  173. if (self.group_info is not None) and (len(self.group_info) > 0):
  174. for key, value in self.group_info.items():
  175. basic_group_info.update({key: value})
  176. # 发送的请求,这几个字段需要转为 [] 数组
  177. group_info_to_res_data = basic_group_info.copy()
  178. for col in group_cols_to_list:
  179. group_info_to_res_data[col] = eval(group_info_to_res_data[col]) \
  180. if group_info_to_res_data[col] is not None else None
  181. if 'group_name' in group_info_to_res_data.keys():
  182. group_info_to_res_data['unit_name'] = group_info_to_res_data['group_name']
  183. del group_info_to_res_data['group_name']
  184. # 写入组层级操作记录数据表基本信息
  185. group_info_to_db = basic_group_info.copy()
  186. group_info_to_db['ai_strategy_uuid'] = self.ai_strategy_uuid
  187. group_info_to_db['account_id'] = self.account_id
  188. group_info_to_db['campaign_id'] = self.campaign_id
  189. group_info_to_db['operation_type'] = self.operation_type
  190. # 2、创意层级基本信息
  191. creative_cols = ['creative_name', 'action_bar_text', 'description', 'short_slogan',
  192. 'sticker_title', 'overlay_type', 'expose_tag', 'new_expose_tag', 'site_id',
  193. 'click_track_url', 'impression_url', 'ad_photo_played_t3s_url', 'actionbar_click_url',
  194. 'creative_category', 'creative_tag']
  195. basic_creative_info = {}
  196. for col in creative_cols:
  197. basic_creative_info[col] = self.advertiser_strategy.get(col)
  198. # 2.1从请求的信息中更新创意层级的信息,如广告语
  199. if (self.creative_info is not None) and (len(self.creative_info) > 0):
  200. for key, value in self.creative_info.items():
  201. basic_creative_info.update({key: value})
  202. # 2.2
  203. creative_info_to_res_data = basic_creative_info.copy()
  204. creative_cols_to_list = ['creative_tag']
  205. for col in creative_cols_to_list:
  206. creative_info_to_res_data[col] = eval(creative_info_to_res_data[col]) \
  207. if creative_info_to_res_data[col] is not None else None
  208. # 2.3 写入创意层级操作记录数据表基本信息
  209. creative_info_to_db = basic_creative_info.copy()
  210. creative_info_to_db['ai_strategy_uuid'] = self.ai_strategy_uuid
  211. creative_info_to_db['account_id'] = self.account_id
  212. creative_info_to_db['campaign_id'] = self.campaign_id
  213. creative_info_to_db['operation_type'] = self.operation_type
  214. # 拼接最终请求数据
  215. self.res_data['group_list'] = []
  216. group_cnt = 1
  217. for video in self.video:
  218. group_uuid = str(uuid.uuid4())
  219. group_name = basic_group_info['group_name'] + '-' + str(group_cnt)
  220. # 写入数据表中组信息
  221. single_group_info_to_db = group_info_to_db.copy()
  222. single_group_info_to_db['group_uuid'] = group_uuid
  223. single_group_info_to_db['group_name'] = group_name
  224. single_group_info_to_db['create_time'] = datetime.datetime.now()
  225. df = pd.DataFrame.from_dict(single_group_info_to_db, orient='index').T
  226. df.to_sql(name="ctop_ai_kuaishou_unit_level_operation_record",
  227. con=engine,
  228. if_exists='append',
  229. index=False)
  230. # 拼装返回json的组信息
  231. single_group_info_to_res_data = group_info_to_res_data.copy()
  232. single_group_info_to_res_data['group_uuid'] = group_uuid
  233. single_group_info_to_res_data['unit_name'] = group_name
  234. single_group_info_to_res_data['creative_list'] = []
  235. group_cnt += 1
  236. # 拼装组下面创意的信息
  237. creative_cnt = 1
  238. for image_md5 in video['imageList'][: self.advertiser_strategy['image_cnt']]:
  239. creative_uuid = str(uuid.uuid4())
  240. creative_name = basic_creative_info['creative_name'] + '_' + str(creative_cnt)
  241. single_creative_info_to_db = creative_info_to_db.copy()
  242. single_creative_info_to_db['creative_uuid'] = creative_uuid
  243. single_creative_info_to_db['creative_name'] = creative_name
  244. single_creative_info_to_db['photo_id'] = video['photo_id']
  245. single_creative_info_to_db['image_md5'] = image_md5
  246. single_creative_info_to_db['create_time'] = datetime.datetime.now()
  247. df = pd.DataFrame.from_dict(single_creative_info_to_db, orient='index').T
  248. df.to_sql(name="ctop_ai_kuaishou_creative_level_operation_record",
  249. con=engine,
  250. if_exists='append',
  251. index=False)
  252. single_creative_info_to_res_data = creative_info_to_res_data.copy()
  253. single_creative_info_to_res_data['creative_uuid'] = creative_uuid
  254. single_creative_info_to_res_data['creative_name'] = creative_name
  255. single_creative_info_to_res_data['photo_id'] = video['photo_id']
  256. single_creative_info_to_res_data['image_md5'] = image_md5
  257. single_group_info_to_res_data['creative_list'].append(single_creative_info_to_res_data)
  258. creative_cnt += 1
  259. # 组和创意信息添加到最终返回数据 group_list 中
  260. self.res_data['group_list'].append(single_group_info_to_res_data)
  261. self.res_data['account_id'] = self.account_id
  262. self.res_data['campaign_id'] = self.campaign_id
  263. # TODO 修改操作
  264. class ParseModifyRequest(object):
  265. def __init__(self):
  266. pass
  267. # TODO 关停操作
  268. class ParseShutDownRequest(object):
  269. def __init__(self):
  270. pass