ai_strategy_request_func.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. import datetime
  2. import json
  3. import uuid
  4. import traceback
  5. from concurrent_log import ConcurrentTimedRotatingFileHandler
  6. import pandas as pd
  7. import pymysql
  8. import requests
  9. from utils.DataBaseConfig import *
  10. from utils.UrlConfig import *
  11. import logging
  12. from utils.BaseClass import NpEncoder
  13. log_formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s', '%m/%d/%Y %I:%M:%S %p')
  14. log_handler = ConcurrentTimedRotatingFileHandler("logs/ai_strategy_request.log", 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. 发送创建组和创意的请求
  23. :param data:
  24. :return:
  25. """
  26. try:
  27. account_id_for_logger = None
  28. if data["operation_type"] == 1:
  29. inst = ParseAddCampaignOrAddGroupRequest(data)
  30. account_id_for_logger = inst.account_id
  31. logger.info("账户信息=%s, 当前进程=%s, 当前进程的主进程=%s" % (inst.account_id, os.getpid(), os.getppid()))
  32. # 1 获取客户策略信息
  33. inst.get_advertiser_strategy_info()
  34. # 2 写入智能策略信息
  35. inst.write_intelligence_strategy_table()
  36. # 3 判断 campaign_id 是否为空,为空则发送创建计划的请求
  37. if inst.campaign_id == "" or inst.campaign_id is None:
  38. if inst.add_campaign() == -1:
  39. return {'code': -2, 'message': '广告计划创建失败!'}
  40. # 4 unit_type "4-自定义" or "7-程序化创意2.0" ,调用对应的拼装参数函数
  41. if data['group_info'].get('unit_type', 4) == 4:
  42. inst.assemble_group_and_creative_params()
  43. if data['group_info'].get('unit_type', 4) == 7:
  44. inst.assemble_group_and_programme_creative_params()
  45. # 5 发送的请求信息更新到数据库表
  46. inst.update_intelligence_strategy_table(request_content=inst.res_data, message=None)
  47. # 6 发送创建组和创意的请求
  48. request = requests.post(create_group_and_creative_url,
  49. headers=headers,
  50. data=json.dumps(inst.res_data, cls=NpEncoder))
  51. response_data = json.loads(request.text)
  52. # 7 接受的返回信息更新到数据库表
  53. inst.update_intelligence_strategy_table(message=response_data)
  54. # 8 写入日志信息
  55. logger.info("account_id = %s, 策略uuid = %s 的请求返回信息:%s" % (account_id_for_logger, inst.ai_strategy_uuid, response_data))
  56. return {'account_id': inst.account_id, 'code': 0, 'message': response_data}
  57. else:
  58. return {"account_id": account_id_for_logger, "code": -1, "message": "暂时不支持非新增的操作请求!"}
  59. except Exception:
  60. logger.error("account_id = %s, traceback is %s" % (account_id_for_logger, traceback.format_exc()))
  61. return {"account_id": account_id_for_logger, "message": traceback.format_exc(), "code": -2}
  62. # 该类解析的是 手动请求的新增广告计划或者新增广告组的数据
  63. class ParseAddCampaignOrAddGroupRequest(object):
  64. def __init__(self, request_data):
  65. self.ai_strategy_uuid = str(uuid.uuid4())
  66. self.request_data = request_data
  67. self.video = self.request_data['video']
  68. self.account_id = self.request_data['account_id']
  69. self.campaign_info = self.request_data['campaign_info']
  70. self.campaign_id = self.request_data['campaign_info'].get('campaign_id', None)
  71. self.group_info = self.request_data.get('group_info', None)
  72. self.creative_info = self.request_data.get('creative_info', None)
  73. self.operation_type = self.request_data['operation_type']
  74. self.advertiser_strategy_id = None
  75. self.advertiser_strategy = {}
  76. self.res_data = {}
  77. def get_advertiser_strategy_info(self):
  78. """
  79. 获取指定账户下客户的策略信息
  80. 为后续的写入库表,校验一致性做准备
  81. :return:
  82. """
  83. sql = """
  84. select *
  85. from ctop_ai_kuaishou_advertiser_strategy
  86. where account_id = %d
  87. limit 1
  88. """ % self.account_id
  89. advertiser_strategy_df = pd.read_sql(sql, engine)
  90. self.advertiser_strategy_id = int(advertiser_strategy_df['id'].values[0])
  91. self.advertiser_strategy = advertiser_strategy_df.T.to_dict()[0]
  92. def write_intelligence_strategy_table(self):
  93. """
  94. 请求信息写入 ctop_ai_kuaishou_intelligence_strategy 表中
  95. :return:
  96. """
  97. intelligence_strategy_dict = \
  98. {
  99. 'ai_strategy_uuid': self.ai_strategy_uuid,
  100. 'advertiser_strategy_id': self.advertiser_strategy_id,
  101. 'account_id': self.account_id,
  102. 'ai_strategy_receive_content': str(self.request_data),
  103. 'ai_strategy_remark': self.request_data['ai_strategy_remark'],
  104. 'create_time': datetime.datetime.now()
  105. }
  106. df = pd.DataFrame.from_dict(intelligence_strategy_dict, orient='index').T
  107. df.to_sql(name="ctop_ai_kuaishou_intelligence_strategy", con=engine, if_exists='append', index=False)
  108. def update_intelligence_strategy_table(self, request_content=None, message=None):
  109. """
  110. 更新 intelligence_strategy_table
  111. :return:
  112. """
  113. db_con = pymysql.connect(host=host,
  114. port=port,
  115. user=user,
  116. password=passwd,
  117. database=db,
  118. charset=charset)
  119. cursor = db_con.cursor()
  120. if request_content:
  121. cursor.execute("""UPDATE ctop_ai_kuaishou_intelligence_strategy
  122. SET ai_strategy_request_content= %s
  123. WHERE ai_strategy_uuid = %s""", (str(request_content), self.ai_strategy_uuid))
  124. if message:
  125. cursor.execute("""UPDATE ctop_ai_kuaishou_intelligence_strategy
  126. SET message = %s
  127. WHERE ai_strategy_uuid = %s""", (str(message), self.ai_strategy_uuid))
  128. db_con.commit()
  129. db_con.close()
  130. def add_campaign(self):
  131. """
  132. 新增广告计划, 创建成功之后写入计划层级操作表中
  133. :return:
  134. """
  135. create_campaign_req_data = \
  136. {'account_id': self.account_id,
  137. 'campaign_name': self.campaign_info['campaign_name'],
  138. 'type': self.advertiser_strategy['campaign_type']}
  139. request = requests.post(url=create_campaign_url,
  140. headers=headers,
  141. data=json.JSONEncoder().encode(create_campaign_req_data))
  142. res_data = json.loads(request.text)
  143. # res_data = {
  144. # "code": 0,
  145. # "data": {
  146. # "account_id": 23212,
  147. # "campaign_id": 30956133,
  148. # "campaign_create_time": "2021-01-13 13:50:16"
  149. # },
  150. # "message": "SUCCESS"}
  151. campaign_info_to_db = {
  152. 'campaign_uuid': str(uuid.uuid4()),
  153. 'account_id': self.account_id,
  154. 'ai_strategy_uuid': self.ai_strategy_uuid,
  155. 'campaign_name': self.campaign_info['campaign_name'],
  156. 'campaign_type': self.advertiser_strategy['campaign_type'],
  157. 'operation_type': self.operation_type,
  158. 'create_time': datetime.datetime.now()
  159. }
  160. res = 0
  161. logger.info("the res of create campaign is %s" % res_data)
  162. if res_data['code'] == 0:
  163. self.campaign_id = res_data['data'].get('campaign_id', None)
  164. campaign_info_to_db['campaign_id'] = self.campaign_id
  165. campaign_info_to_db['campaign_create_time'] = res_data['data'].get('campaign_create_time', None)
  166. campaign_info_to_db['status'] = res_data.get('code', None)
  167. campaign_info_to_db['message'] = res_data.get('message', None)
  168. logger.info("广告计划创建成功,campaign_id = %s, ai_strategy_uuid = %s" %
  169. (self.campaign_id, self.ai_strategy_uuid))
  170. else:
  171. campaign_info_to_db['message'] = res_data['message']
  172. campaign_info_to_db['status'] = res_data['code']
  173. logger.error("广告计划创建失败:%s, ai_strategy_uuid = %s" % (res_data['message'], self.ai_strategy_uuid))
  174. res = -1
  175. # 写入计划层级的操作表
  176. df = pd.DataFrame.from_dict(campaign_info_to_db, orient='index').T
  177. df.to_sql(name="ctop_ai_kuaishou_campaign_level_operation_record",
  178. con=engine,
  179. if_exists='append',
  180. index=False)
  181. return res
  182. def get_group_params(self):
  183. group_params = self.advertiser_strategy.copy()
  184. # 1 从客户策略表中,剔除掉不是组层级的参数(客户基本信息、计划层级信息、创意层级信息)
  185. drop_cols = ['id', 'account_id', 'status', 'campaign_type', 'campaign_name',
  186. 'creative_name', 'action_bar_text', 'description', 'short_slogan',
  187. 'sticker_title', 'overlay_type', 'expose_tag', 'new_expose_tag', 'site_id',
  188. 'click_track_url', 'impression_url', 'ad_photo_played_t3s_url', 'actionbar_click_url',
  189. 'creative_category', 'creative_tag', 'image_cnt',
  190. 'create_time', 'effective_time', 'expiry_time', 'timer_task_status',
  191. 'single_appid', 'app_id_array','general_track', 'open_program_create','user_id']
  192. for col in drop_cols:
  193. if col in group_params.keys():
  194. del group_params[col]
  195. # 2 从请求的信息中更新组层级信息, 如组的名称、测试定向、测试出价等, update客户策略信息
  196. if (self.group_info is not None) and (len(self.group_info) > 0):
  197. for key, value in self.group_info.items():
  198. if value is not None:
  199. group_params.update({key: value})
  200. # 3 smart_cover 和 asset_mining 需要将0/1 转化为 False/True
  201. group_params['smart_cover'] = True if group_params.get('smart_cover', 0) == 1 else False
  202. group_params['asset_mining'] = True if group_params.get('asset_mining', 0) == 1 else False
  203. # 4 拼装json的组参数
  204. group_params_to_request = group_params.copy()
  205. # 4-1 拼接发送请求json时, 以下字段需要转为 list 类型
  206. cols_to_list = ['app_store', 'scene_id', 'region', 'district_ids', 'ages_range', 'device_brand',
  207. 'device_price', 'business_interest', 'fans_star', 'interest_video', 'app_interest',
  208. 'app_ids', 'population', 'exclude_population', 'paid_audience', 'behavior_interest']
  209. for col in cols_to_list:
  210. group_params_to_request[col] = eval(group_params_to_request[col]) \
  211. if ((group_params_to_request[col] is not None) and (group_params_to_request[col] != '')) else None
  212. # 4-2 发送请求,需要将 group_name 改为 unit_name
  213. group_params_to_request['unit_name'] = group_params_to_request.pop('group_name')
  214. # 5 写入数据库的组参数
  215. group_params_to_db = group_params.copy()
  216. group_params_to_db['ai_strategy_uuid'] = self.ai_strategy_uuid
  217. group_params_to_db['account_id'] = self.account_id
  218. group_params_to_db['campaign_id'] = self.campaign_id
  219. group_params_to_db['operation_type'] = self.operation_type
  220. group_params_to_db['status'] = 1
  221. group_params_to_db['message'] = None
  222. return group_params_to_request, group_params_to_db
  223. def get_creative_params(self):
  224. # 1 从客户策略表中获取 创意层级基本信息
  225. creative_cols = ['creative_name', 'action_bar_text', 'description', 'short_slogan',
  226. 'sticker_title', 'overlay_type', 'expose_tag', 'new_expose_tag', 'site_id',
  227. 'click_track_url', 'impression_url', 'ad_photo_played_t3s_url', 'actionbar_click_url',
  228. 'creative_category', 'creative_tag']
  229. creative_params = {}
  230. for col in creative_cols:
  231. creative_params[col] = self.advertiser_strategy.get(col)
  232. # 2 从请求的信息中更新创意层级的信息,如广告语
  233. if (self.creative_info is not None) and (len(self.creative_info) > 0):
  234. for key, value in self.creative_info.items():
  235. if value is not None:
  236. creative_params.update({key: value})
  237. # 3 拼装json的 创意参数
  238. creative_params_to_request = creative_params.copy()
  239. # 3-1 拼接发送请求json时, 以下字段需要转为 list 类型
  240. cols_to_list = ['creative_tag']
  241. for col in cols_to_list:
  242. creative_params_to_request[col] = eval(creative_params_to_request[col]) \
  243. if ((creative_params_to_request[col] is not None) and (creative_params_to_request[col] != '')) else None
  244. # 4 写入数据库的创意参数
  245. creative_params_to_db = creative_params.copy()
  246. creative_params_to_db['ai_strategy_uuid'] = self.ai_strategy_uuid
  247. creative_params_to_db['account_id'] = self.account_id
  248. creative_params_to_db['campaign_id'] = self.campaign_id
  249. creative_params_to_db['operation_type'] = self.operation_type
  250. creative_params_to_db['status'] = 1
  251. creative_params_to_db['message'] = None
  252. return creative_params_to_request, creative_params_to_db
  253. def get_programme_creative_params(self):
  254. # 1 从客户策略表中获取 创意层级基本信息
  255. creative_cols = ['creative_name', 'action_bar_text', 'description', 'site_id',
  256. 'click_track_url', 'actionbar_click_url',
  257. 'creative_category', 'creative_tag']
  258. creative_params = {}
  259. for col in creative_cols:
  260. creative_params[col] = self.advertiser_strategy.get(col)
  261. # 2 从请求的信息中更新创意层级的信息,如广告语,创意名称等
  262. if (self.creative_info is not None) and (len(self.creative_info) > 0):
  263. for key, value in self.creative_info.items():
  264. if value is not None:
  265. creative_params.update({key: value})
  266. # 3 程序化创意部分字段发生改变,需要重命名
  267. # creative_name --> package_name(程序化创意名称)
  268. # action_bar_text --> action_bar(行动号召按钮)
  269. # description --> captions(作品广告语) string[]
  270. # click_track_url --> click_url(点击监测链接)
  271. creative_params['package_name'] = creative_params.pop('creative_name')
  272. creative_params['action_bar'] = creative_params.pop('action_bar_text')
  273. description = creative_params.pop('description')
  274. creative_params['captions'] = str([description])
  275. creative_params['click_url'] = creative_params.pop('click_track_url')
  276. # 4 拼装json的 创意参数
  277. creative_params_to_request = creative_params.copy()
  278. # 4-1 拼接发送请求json时, 以下字段需要转为 list 类型
  279. cols_to_list = ['creative_tag', 'captions']
  280. for col in cols_to_list:
  281. creative_params_to_request[col] = eval(creative_params_to_request[col]) \
  282. if ((creative_params_to_request[col] is not None) and (creative_params_to_request[col] != '')) else None
  283. # 5 写入数据库的创意参数
  284. creative_params_to_db = creative_params.copy()
  285. creative_params_to_db['ai_strategy_uuid'] = self.ai_strategy_uuid
  286. creative_params_to_db['account_id'] = self.account_id
  287. creative_params_to_db['campaign_id'] = self.campaign_id
  288. creative_params_to_db['operation_type'] = self.operation_type
  289. creative_params_to_db['status'] = 1
  290. creative_params_to_db['message'] = None
  291. return creative_params_to_request, creative_params_to_db
  292. def assemble_group_and_creative_params(self):
  293. """
  294. 拼接组和创意层级参数
  295. 写入数据库
  296. :return:
  297. """
  298. # 获取组和创意的基本参数
  299. group_params_to_request, group_params_to_db = self.get_group_params()
  300. creative_params_to_request, creative_params_to_db = self.get_creative_params()
  301. self.res_data['group_list'] = []
  302. group_cnt = 1
  303. batch_group_params_to_db = []
  304. batch_creative_params_to_db = []
  305. for video in self.video:
  306. group_uuid = str(uuid.uuid4())
  307. group_name = group_params_to_db['group_name'] + '-' + str(group_cnt)
  308. # 写入数据表中组信息
  309. single_group_params_to_db = group_params_to_db.copy()
  310. single_group_params_to_db['group_uuid'] = group_uuid
  311. single_group_params_to_db['group_name'] = group_name
  312. single_group_params_to_db['create_time'] = datetime.datetime.now()
  313. batch_group_params_to_db.append(single_group_params_to_db)
  314. # 拼装返回json的组信息
  315. single_group_params_to_request = group_params_to_request.copy()
  316. single_group_params_to_request['group_uuid'] = group_uuid
  317. single_group_params_to_request['unit_name'] = group_name
  318. single_group_params_to_request['creative_list'] = []
  319. group_cnt += 1
  320. # 拼装组下面创意的信息
  321. creative_cnt = 1
  322. for image_md5 in video['imageList'][: self.advertiser_strategy['image_cnt']]:
  323. creative_uuid = str(uuid.uuid4())
  324. creative_name = creative_params_to_db['creative_name'] + '_' + str(creative_cnt)
  325. single_creative_params_to_db = creative_params_to_db.copy()
  326. single_creative_params_to_db['creative_uuid'] = creative_uuid
  327. single_creative_params_to_db['creative_name'] = creative_name
  328. single_creative_params_to_db['photo_id'] = int(video['photo_id'])
  329. single_creative_params_to_db['image_md5'] = image_md5
  330. single_creative_params_to_db['create_time'] = datetime.datetime.now()
  331. batch_creative_params_to_db.append(single_creative_params_to_db)
  332. single_creative_params_to_request = creative_params_to_request.copy()
  333. single_creative_params_to_request['creative_uuid'] = creative_uuid
  334. single_creative_params_to_request['creative_name'] = creative_name
  335. single_creative_params_to_request['photo_id'] = int(video['photo_id'])
  336. single_creative_params_to_request['image_md5'] = image_md5
  337. # 单个创意信息加入到组里面的 creative_list 中
  338. single_group_params_to_request['creative_list'].append(single_creative_params_to_request)
  339. creative_cnt += 1
  340. # 组和创意信息添加到最终返回数据 group_list 中
  341. self.res_data['group_list'].append(single_group_params_to_request)
  342. # 创意层级信息批量写入数据库
  343. creative_df = pd.DataFrame(batch_creative_params_to_db)
  344. creative_df.to_sql(name="ctop_ai_kuaishou_creative_level_operation_record",
  345. con=engine,
  346. if_exists='append',
  347. index=False)
  348. # 组层级信息批量写入数据库
  349. group_df = pd.DataFrame(batch_group_params_to_db)
  350. group_df.to_sql(name="ctop_ai_kuaishou_unit_level_operation_record",
  351. con=engine,
  352. if_exists='append',
  353. index=False)
  354. self.res_data['account_id'] = self.account_id
  355. self.res_data['campaign_id'] = self.campaign_id
  356. def assemble_group_and_programme_creative_params(self):
  357. """
  358. 拼接组和程序化创意的参数
  359. 写入数据库
  360. :return:
  361. """
  362. # 获取组和创意的基本参数
  363. group_params_to_request, group_params_to_db = self.get_group_params()
  364. creative_params_to_request, creative_params_to_db = self.get_programme_creative_params()
  365. # 每5个视频一组,来拼接组层级 和 程序化创意 层级的参数
  366. self.res_data['group_list'] = []
  367. cnt = 1
  368. is_smart_cover = group_params_to_request.get('smart_cover', 0)
  369. batch_group_params_to_db = []
  370. batch_creative_params_to_db = []
  371. for i in range(0, len(self.video), 5):
  372. group_uuid = str(uuid.uuid4())
  373. group_name = group_params_to_db['group_name'] + '-' + str(cnt)
  374. # 写入数据表中组信息
  375. single_group_params_to_db = group_params_to_db.copy()
  376. single_group_params_to_db['group_uuid'] = group_uuid
  377. single_group_params_to_db['group_name'] = group_name
  378. single_group_params_to_db['create_time'] = datetime.datetime.now()
  379. batch_group_params_to_db.append(single_group_params_to_db)
  380. # 拼装返回json的组信息
  381. single_group_params_to_request = group_params_to_request.copy()
  382. single_group_params_to_request['group_uuid'] = group_uuid
  383. single_group_params_to_request['unit_name'] = group_name
  384. single_group_params_to_request['creative_list'] = []
  385. single_group_params_to_request['programCreative'] = None
  386. # 拼装程序化创意的信息
  387. horizontal_photo_ids = []
  388. vertical_photo_ids = []
  389. cover_image_tokens = []
  390. if i+5 < len(self.video):
  391. for j in range(i, i+5, 1):
  392. if self.video[j]['material_type'] == 2:
  393. horizontal_photo_ids.append(self.video[j]['photo_id'])
  394. cover_image_tokens.append(self.video[j]['imageList'][0])
  395. if self.video[j]['material_type'] == 1:
  396. vertical_photo_ids.append(self.video[j]['photo_id'])
  397. cover_image_tokens.append(self.video[j]['imageList'][0])
  398. if len(cover_image_tokens) >= 5:
  399. cover_image_tokens = cover_image_tokens[:4]
  400. creative_uuid = str(uuid.uuid4())
  401. package_name = creative_params_to_db['package_name'] + '_' + str(cnt)
  402. single_creative_params_to_db = creative_params_to_db.copy()
  403. single_creative_params_to_db['creative_uuid'] = creative_uuid
  404. single_creative_params_to_db['package_name'] = package_name
  405. single_creative_params_to_db['horizontal_photo_ids'] = str(horizontal_photo_ids)
  406. single_creative_params_to_db['vertical_photo_ids'] = str(vertical_photo_ids)
  407. single_creative_params_to_db['cover_image_tokens'] = str(cover_image_tokens) if not is_smart_cover else None
  408. single_creative_params_to_db['create_time'] = datetime.datetime.now()
  409. batch_creative_params_to_db.append(single_creative_params_to_db)
  410. single_creative_params_to_request = creative_params_to_request.copy()
  411. single_creative_params_to_request['creative_uuid'] = creative_uuid
  412. single_creative_params_to_request['package_name'] = package_name
  413. single_creative_params_to_request['horizontal_photo_ids'] = horizontal_photo_ids
  414. single_creative_params_to_request['vertical_photo_ids'] = vertical_photo_ids
  415. if not is_smart_cover:
  416. single_creative_params_to_request['image_md5s'] = cover_image_tokens
  417. else:
  418. # material_type=1 竖版
  419. # material_type=2 横版
  420. for j in range(i, len(self.video)):
  421. if self.video[j]['material_type'] == 2:
  422. horizontal_photo_ids.append(self.video[j]['photo_id'])
  423. cover_image_tokens.append(self.video[j]['imageList'][0])
  424. if self.video[j]['material_type'] == 1:
  425. vertical_photo_ids.append(self.video[j]['photo_id'])
  426. cover_image_tokens.append(self.video[j]['imageList'][0])
  427. if len(cover_image_tokens) >= 5:
  428. cover_image_tokens = cover_image_tokens[:4]
  429. creative_uuid = str(uuid.uuid4())
  430. package_name = creative_params_to_db['package_name'] + '_' + str(cnt)
  431. single_creative_params_to_db = creative_params_to_db.copy()
  432. single_creative_params_to_db['creative_uuid'] = creative_uuid
  433. single_creative_params_to_db['package_name'] = package_name
  434. single_creative_params_to_db['horizontal_photo_ids'] = str(horizontal_photo_ids)
  435. single_creative_params_to_db['vertical_photo_ids'] = str(vertical_photo_ids)
  436. single_creative_params_to_db['cover_image_tokens'] = str(cover_image_tokens) if not is_smart_cover else None
  437. single_creative_params_to_db['create_time'] = datetime.datetime.now()
  438. batch_creative_params_to_db.append(single_creative_params_to_db)
  439. single_creative_params_to_request = creative_params_to_request.copy()
  440. single_creative_params_to_request['creative_uuid'] = creative_uuid
  441. single_creative_params_to_request['package_name'] = package_name
  442. single_creative_params_to_request['horizontal_photo_ids'] = horizontal_photo_ids
  443. single_creative_params_to_request['vertical_photo_ids'] = vertical_photo_ids
  444. if not is_smart_cover:
  445. single_creative_params_to_request['image_md5s'] = cover_image_tokens
  446. single_group_params_to_request['programCreative'] = single_creative_params_to_request
  447. cnt += 1
  448. self.res_data['group_list'].append(single_group_params_to_request)
  449. # 创意层级信息批量写入数据库
  450. creative_df = pd.DataFrame(batch_creative_params_to_db)
  451. creative_df.to_sql(name="ctop_ai_kuaishou_program_creative_level_operation_record",
  452. con=engine,
  453. if_exists='append',
  454. index=False)
  455. # 组层级信息批量写入数据库
  456. group_df = pd.DataFrame(batch_group_params_to_db)
  457. group_df.to_sql(name="ctop_ai_kuaishou_unit_level_operation_record",
  458. con=engine,
  459. if_exists='append',
  460. index=False)
  461. self.res_data['account_id'] = self.account_id
  462. self.res_data['campaign_id'] = self.campaign_id
  463. # TODO 修改操作
  464. class ParseModifyRequest(object):
  465. def __init__(self):
  466. pass
  467. # TODO 关停操作
  468. class ParseShutDownRequest(object):
  469. def __init__(self):
  470. pass