ai_time_task_creative_handler.py 72 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  1. import pandas as pd
  2. from utils.UrlConfig import *
  3. import json
  4. import logging
  5. import traceback
  6. import random
  7. import tornado.web
  8. from concurrent_log import ConcurrentTimedRotatingFileHandler
  9. from utils.ConstantConfig import *
  10. from utils.DataBaseConfig import *
  11. from utils.CommonFunction import get_history_video_info, get_new_video_info, get_missing_video_info, \
  12. get_top_video_info, get_campaign_and_group_name_rule, get_app_detail, get_request_data, \
  13. refresh_video, get_app_list
  14. from ai_strategy_request_func import ai_strategy_request_parse
  15. log_formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s', '%m/%d/%Y %I:%M:%S %p')
  16. log_handler = ConcurrentTimedRotatingFileHandler("logs/ai_auto_create.log", when="midnight", backupCount=100)
  17. log_handler.setFormatter(log_formatter)
  18. logger = logging.getLogger('ai_time_task_creative_logger')
  19. logger.addHandler(log_handler)
  20. logger.setLevel(logging.DEBUG)
  21. print('id of ai_time_task_creative_logger %s' % id(logger))
  22. logger.info("ai_time_task_creative_server started!")
  23. class AiHistoricalMissingMaterial(tornado.web.RequestHandler):
  24. """
  25. 补充历史遗漏素材(关联创意个数为0个素材)
  26. """
  27. def post(self):
  28. data = self.request.body
  29. data = str(data, 'utf8')
  30. data = json.loads(data, encoding='utf8')
  31. logger.info("*************************************** NEW REQUEST ***************************************")
  32. account_id = data.get('account_id')
  33. campaign_id = data.get('campaign_id')
  34. logger.info("账户信息=%s, 当前进程=%s, 当前进程的主进程=%s, raw data from request is %s" %
  35. (account_id, os.getpid(), os.getppid(), data))
  36. try:
  37. sql = """
  38. select account_id, single_appid, app_id_array, general_track from ctop_ai_kuaishou_advertiser_strategy
  39. where account_id=%s order by create_time desc limit 1
  40. """ % account_id
  41. df = pd.read_sql(sql, engine)
  42. if df['general_track'].values[0] == 0:
  43. app_id_array = eval(df['app_id_array'].values[0])
  44. app_list = get_app_list(account_id=account_id, url=get_app_list_url)
  45. # app_dict key = ("appVersion": "ksjyrlyn-人类一脑涂地大败") , value = 完整的app_id信息
  46. app_dict = {}
  47. for app_info in app_list['data']:
  48. if app_info['appId'] in app_id_array:
  49. app_dict[app_info['appVersion']] = app_info
  50. video_list = get_missing_video_info(account_id=account_id,
  51. cnt=missing_video_cnt,
  52. url=get_missing_video_url,
  53. start_time=missing_video_start_time,
  54. end_time=missing_video_end_time)
  55. # 返回视频中有通用视频和特定视频,需要分开处理
  56. # "photo_name": "all",
  57. # "photo_name": "ksjytdrca-糖豆人冲啊",
  58. if video_list['code'] == 0:
  59. video_df = pd.DataFrame(video_list['data'])
  60. # 1-非通用视频的创建
  61. special_video_df = video_df[video_df.photo_name != 'all']
  62. for photo_name in special_video_df['photo_name'].unique():
  63. if photo_name in app_dict.keys():
  64. campaign_id = None
  65. app_id = app_dict[photo_name].get('appId', 'error')
  66. app_version = app_dict[photo_name].get('appVersion', 'error')
  67. track_url = app_dict[photo_name].get('trackUrl', 'error')
  68. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  69. campaign_df = pd.read_sql(sql, engine)
  70. for row in campaign_df.itertuples():
  71. if (app_version + '--优选广告位-' + '遗漏素材') == getattr(row, 'campaign_name'):
  72. campaign_id = getattr(row, 'campaign_id')
  73. break
  74. app_id_video_df = special_video_df[special_video_df.photo_name == photo_name]
  75. app_id_video_list = []
  76. for k, v in app_id_video_df.T.to_dict().items():
  77. app_id_video_list.append(v)
  78. request_data = get_request_data(account_id=account_id,
  79. campaign_id=campaign_id,
  80. video_info=app_id_video_list,
  81. campaign_name=app_version + '--优选广告位-' + '遗漏素材',
  82. group_name=app_version + '-优选广告位-不限-自定义-' + '遗漏素材',
  83. ai_strategy_remark="补充遗漏素材",
  84. unit_type=4,
  85. app_id=app_id,
  86. click_track_url=track_url)
  87. request = ai_strategy_request_parse(request_data)
  88. logger.info("account_id=%s, app_id=%s, 补充遗漏素材-特定视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  89. # 2-通用视频的创建,random.shuffle 选择 app_id
  90. general_video_df = video_df[video_df.photo_name == 'all']
  91. if not general_video_df.empty:
  92. general_video_cnt = len(general_video_df)
  93. app_version_list = list(app_dict)
  94. random.shuffle(app_version_list)
  95. video_cnt = 0
  96. for app_version in app_version_list[:general_video_cnt]:
  97. campaign_id = None
  98. app_id = app_dict[app_version].get('appId', 'error')
  99. track_url = app_dict[app_version].get('trackUrl', 'error')
  100. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  101. campaign_df = pd.read_sql(sql, engine)
  102. for row in campaign_df.itertuples():
  103. if (app_version + '--优选广告位-' + '遗漏素材') == getattr(row, 'campaign_name'):
  104. campaign_id = getattr(row, 'campaign_id')
  105. break
  106. single_video = [general_video_df.iloc[video_cnt, :].T.to_dict()]
  107. request_data = get_request_data(account_id=account_id,
  108. campaign_id=campaign_id,
  109. video_info=single_video,
  110. campaign_name=app_version + '--优选广告位-' + '遗漏素材',
  111. group_name=app_version + '-优选广告位-不限-自定义-' + '遗漏素材',
  112. ai_strategy_remark="补充遗漏素材",
  113. unit_type=4,
  114. app_id=app_id,
  115. click_track_url=track_url)
  116. request = ai_strategy_request_parse(request_data)
  117. video_cnt += 1
  118. logger.info("account_id=%s, app_id=%s, 补充遗漏素材-通用视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  119. else:
  120. logger.info("account_id=%s, 补充遗漏素材: 返回的视频中没有通用视频" % account_id)
  121. self.write(json.dumps({"message": "account_id=%s, 多应用的补充遗漏素材请求已走完!" % account_id}))
  122. self.flush()
  123. else:
  124. video_info = get_missing_video_info(account_id=account_id,
  125. cnt=missing_video_cnt,
  126. url=get_missing_video_url,
  127. start_time=missing_video_start_time,
  128. end_time=missing_video_end_time)
  129. if video_info['code'] != 0:
  130. logger.info("account_id = %s,补充历史遗漏素材,没有获取到视频,不发送ai策略请求!" % account_id)
  131. self.write(json.dumps({"account_id": account_id,
  132. "message": "补充历史遗漏素材,没有获取到视频,不发送ai策略请求!"}))
  133. self.flush()
  134. else:
  135. campaign_name, group_name = get_campaign_and_group_name_rule(account_id)
  136. if (campaign_name is None) or (group_name is None):
  137. logger.info("没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!")
  138. self.write(json.dumps({"message": "没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!"}))
  139. self.flush()
  140. else:
  141. request_data = get_request_data(account_id=account_id,
  142. campaign_id=campaign_id,
  143. video_info=video_info['data'],
  144. campaign_name=campaign_name,
  145. group_name=group_name,
  146. ai_strategy_remark="补充遗漏素材",
  147. name_replace="补充遗漏素材")
  148. request = ai_strategy_request_parse(request_data)
  149. logger.info("account_id = %s, 补充遗漏素材,ai策略的返回信息:%s" % (account_id, request))
  150. self.write(json.dumps(request))
  151. self.flush()
  152. except Exception:
  153. logger.error("account_id = %s, traceback is %s" % (account_id, traceback.format_exc()))
  154. self.write(json.dumps({"account_id": account_id, "message": traceback.format_exc(), "code": -1}))
  155. self.flush()
  156. class AiAutoCreative(tornado.web.RequestHandler):
  157. """
  158. 每5分钟,检查一次是否有上新素材,有的话,就自动创建
  159. """
  160. def post(self):
  161. data = self.request.body
  162. data = str(data, 'utf8')
  163. data = json.loads(data, encoding='utf8')
  164. logger.info("*************************************** NEW REQUEST ***************************************")
  165. account_id = data.get('account_id')
  166. campaign_id = data.get('campaign_id')
  167. logger.info("账户信息=%s, 当前进程=%s, 当前进程的主进程=%s, raw data from request is %s" %
  168. (account_id, os.getpid(), os.getppid(), data))
  169. try:
  170. # 刷新快手视频信息
  171. refresh_video(account_id=account_id, url=refresh_video_url)
  172. sql = """
  173. select account_id, single_appid, app_id_array, general_track from ctop_ai_kuaishou_advertiser_strategy
  174. where account_id=%s order by create_time desc limit 1
  175. """ % account_id
  176. df = pd.read_sql(sql, engine)
  177. if df['general_track'].values[0] == 0:
  178. app_id_array = eval(df['app_id_array'].values[0])
  179. app_list = get_app_list(account_id=account_id, url=get_app_list_url)
  180. # app_dict key = ("appVersion": "ksjyrlyn-人类一脑涂地大败") , value = 完整的app_id信息
  181. app_dict = {}
  182. for app_info in app_list['data']:
  183. if app_info['appId'] in app_id_array:
  184. app_dict[app_info['appVersion']] = app_info
  185. video_list = get_new_video_info(account_id=account_id,
  186. url=get_new_video_url)
  187. # 返回的视频中有通用视频和特定视频,需要分开处理
  188. # "photo_name": "all",
  189. # "photo_name": "ksjytdrca-糖豆人冲啊",
  190. if video_list['code'] == 0:
  191. video_df = pd.DataFrame(video_list['data'])
  192. # 1-特定视频的创建
  193. special_video_df = video_df[video_df.photo_name != 'all']
  194. for photo_name in special_video_df['photo_name'].unique():
  195. if photo_name in app_dict.keys():
  196. campaign_id = None
  197. app_id = app_dict[photo_name].get('appId', 'error')
  198. app_version = app_dict[photo_name].get('appVersion', 'error')
  199. track_url = app_dict[photo_name].get('trackUrl', 'error')
  200. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  201. campaign_df = pd.read_sql(sql, engine)
  202. for row in campaign_df.itertuples():
  203. if (app_version + '--优选广告位-' + '素材自动上新') == getattr(row, 'campaign_name'):
  204. campaign_id = getattr(row, 'campaign_id')
  205. break
  206. app_id_video_df = special_video_df[special_video_df.photo_name == photo_name]
  207. app_id_video_list = []
  208. for k, v in app_id_video_df.T.to_dict().items():
  209. app_id_video_list.append(v)
  210. request_data = get_request_data(account_id=account_id,
  211. campaign_id=campaign_id,
  212. video_info=app_id_video_list,
  213. campaign_name=app_version + '--优选广告位-' + '素材自动上新',
  214. group_name=app_version + '-优选广告位-不限-自定义-' + '素材自动上新',
  215. ai_strategy_remark="素材自动上新",
  216. unit_type=4,
  217. app_id=app_id,
  218. click_track_url=track_url)
  219. request = ai_strategy_request_parse(request_data)
  220. logger.info("account_id=%s, app_id=%s, 素材自动上新-特定视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  221. # 2-通用视频的创建,random.shuffle 选择 app_id
  222. general_video_df = video_df[video_df.photo_name == 'all']
  223. if not general_video_df.empty:
  224. general_video_cnt = len(general_video_df)
  225. app_version_list = list(app_dict)
  226. random.shuffle(app_version_list)
  227. video_cnt = 0
  228. for app_version in app_version_list[:general_video_cnt]:
  229. campaign_id = None
  230. app_id = app_dict[app_version].get('appId', 'error')
  231. track_url = app_dict[app_version].get('trackUrl', 'error')
  232. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  233. campaign_df = pd.read_sql(sql, engine)
  234. for row in campaign_df.itertuples():
  235. if (app_version + '--优选广告位-' + '素材自动上新') == getattr(row, 'campaign_name'):
  236. campaign_id = getattr(row, 'campaign_id')
  237. break
  238. single_video = [general_video_df.iloc[video_cnt, :].T.to_dict()]
  239. request_data = get_request_data(account_id=account_id,
  240. campaign_id=campaign_id,
  241. video_info=single_video,
  242. campaign_name=app_version + '--优选广告位-' + '素材自动上新',
  243. group_name=app_version + '-优选广告位-不限-自定义-' + '素材自动上新',
  244. ai_strategy_remark="素材自动上新",
  245. unit_type=4,
  246. app_id=app_id,
  247. click_track_url=track_url)
  248. request = ai_strategy_request_parse(request_data)
  249. video_cnt += 1
  250. logger.info("account_id=%s, app_id=%s, 素材自动上新-通用视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  251. else:
  252. logger.info("account_id=%s, 素材自动上新: 返回的视频中没有通用视频" % account_id)
  253. else:
  254. logger.info("account_id=%s, 素材自动上新: 没有获取到视频" % account_id)
  255. self.write(json.dumps({"message": "account_id=%s, 多应用的素材自动上新已走完!" % account_id}))
  256. self.flush()
  257. else:
  258. start_time = (datetime.date.today()).strftime('%Y-%m-%d %H:%M:%S')
  259. end_time = (datetime.datetime.now()).strftime('%Y-%m-%d %H:%M:%S')
  260. # 1-1 获取当天计划中包含“自动上新”计划的,计划id
  261. sql = """
  262. select campaign_id, campaign_name from ctop_kuaishou_campaign
  263. where account_id = %s
  264. and put_create_time >= '%s'
  265. and put_create_time <= '%s'
  266. """ % (account_id, start_time, end_time)
  267. df = pd.read_sql(sql, engine)
  268. for row in df.itertuples():
  269. if '素材自动上新' in getattr(row, 'campaign_name'):
  270. campaign_id = getattr(row, 'campaign_id')
  271. break
  272. video_info = get_new_video_info(account_id=account_id,
  273. url=get_new_video_url)
  274. if video_info['code'] != 0:
  275. self.write(json.dumps({"account_id": account_id, "message": "素材自动上新没有获取到视频,不发送ai策略请求!"}))
  276. self.flush()
  277. else:
  278. campaign_name, group_name = get_campaign_and_group_name_rule(account_id)
  279. if (campaign_name is None) or (group_name is None):
  280. logger.info("account_id = %s, 素材自动上新 没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!"
  281. % account_id)
  282. self.write(json.dumps({"account_id": account_id,
  283. "message": "素材自动上新 没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!"}))
  284. self.flush()
  285. else:
  286. request_data = get_request_data(account_id=account_id,
  287. campaign_id=campaign_id,
  288. video_info=video_info['data'],
  289. campaign_name=campaign_name,
  290. group_name=group_name,
  291. ai_strategy_remark="自动上新",
  292. name_replace="素材自动上新")
  293. request = ai_strategy_request_parse(request_data)
  294. logger.info("account_id = %s, 素材自动上新 ai策略的返回信息:%s" % (account_id, request))
  295. self.write(json.dumps(request))
  296. self.flush()
  297. except Exception:
  298. logger.error("account_id = %s, traceback is %s" % (account_id, traceback.format_exc()))
  299. self.write(json.dumps({"account_id": account_id, "message": traceback.format_exc(), "code": -1}))
  300. self.flush()
  301. class AiHighQualityMaterial(tornado.web.RequestHandler):
  302. """
  303. 补充历史高质量素材 -- 测试通过 在AD后台创建成功,检查AD信息和数据库表 没有问题
  304. """
  305. def post(self):
  306. data = self.request.body
  307. data = str(data, 'utf8')
  308. data = json.loads(data, encoding='utf8')
  309. logger.info("*************************************** NEW REQUEST ***************************************")
  310. account_id = data.get('account_id')
  311. campaign_id = data.get('campaign_id')
  312. logger.info("账户信息=%s, 当前进程=%s, 当前进程的主进程=%s, raw data from request is %s" %
  313. (account_id, os.getpid(), os.getppid(), data))
  314. try:
  315. sql = """select account_id, single_appid, app_id_array, general_track from ctop_ai_kuaishou_advertiser_strategy
  316. where account_id=%s order by create_time desc limit 1
  317. """ % account_id
  318. df = pd.read_sql(sql, engine)
  319. if df['general_track'].values[0] == 0:
  320. app_id_array = eval(df['app_id_array'].values[0])
  321. app_list = get_app_list(account_id=account_id, url=get_app_list_url)
  322. # app_dict key = ("appVersion": "ksjyrlyn-人类一脑涂地大败") , value = 完整的app_id信息
  323. app_dict = {}
  324. for app_info in app_list['data']:
  325. if app_info['appId'] in app_id_array:
  326. app_dict[app_info['appVersion']] = app_info
  327. video_list = get_top_video_info(account_id=account_id,
  328. cnt=high_quality_video_cnt,
  329. start_time=(datetime.datetime.now() +
  330. datetime.timedelta(days=-high_quality_video_days)).
  331. strftime("%Y-%m-%d %H:%M:%S"),
  332. end_time=(datetime.datetime.now() + datetime.timedelta(days=-1)).
  333. strftime("%Y-%m-%d %H:%M:%S"),
  334. url=get_high_quality_video_url)
  335. # 单独处理返回的时候中,有通用视频,需要单独处理
  336. # "photo_name": "all",
  337. # "photo_name": "ksjytdrca-糖豆人冲啊",
  338. if video_list['code'] == 0:
  339. video_df = pd.DataFrame(video_list['data'])
  340. # 1-特定视频的创建
  341. special_video_df = video_df[video_df.photo_name != 'all']
  342. for photo_name in special_video_df['photo_name'].unique():
  343. if photo_name in app_dict.keys():
  344. campaign_id = None
  345. app_id = app_dict[photo_name].get('appId', 'error')
  346. app_version = app_dict[photo_name].get('appVersion', 'error')
  347. track_url = app_dict[photo_name].get('trackUrl', 'error')
  348. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  349. campaign_df = pd.read_sql(sql, engine)
  350. for row in campaign_df.itertuples():
  351. if (app_version + '--优选广告位-' + '高质量素材') == getattr(row, 'campaign_name'):
  352. campaign_id = getattr(row, 'campaign_id')
  353. break
  354. app_id_video_df = special_video_df[special_video_df.photo_name == photo_name]
  355. app_id_video_list = []
  356. for k, v in app_id_video_df.T.to_dict().items():
  357. app_id_video_list.append(v)
  358. request_data = get_request_data(account_id=account_id,
  359. campaign_id=campaign_id,
  360. video_info=app_id_video_list,
  361. campaign_name=app_version + '--优选广告位-' + '高质量素材',
  362. group_name=app_version + '-优选广告位-不限-自定义-' + '高质量素材',
  363. ai_strategy_remark="高质量素材复建",
  364. unit_type=4,
  365. app_id=app_id,
  366. click_track_url=track_url)
  367. request = ai_strategy_request_parse(request_data)
  368. logger.info("account_id=%s, app_id=%s, 高质量素材复建-特定视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  369. # 2-通用视频的创建,random.shuffle 选择 app_id
  370. general_video_df = video_df[video_df.photo_name == 'all']
  371. if not general_video_df.empty:
  372. general_video_cnt = len(general_video_df)
  373. app_version_list = list(app_dict)
  374. random.shuffle(app_version_list)
  375. video_cnt = 0
  376. for app_version in app_version_list[:general_video_cnt]:
  377. campaign_id = None
  378. app_id = app_dict[app_version].get('appId', 'error')
  379. track_url = app_dict[app_version].get('trackUrl', 'error')
  380. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  381. campaign_df = pd.read_sql(sql, engine)
  382. for row in campaign_df.itertuples():
  383. if (app_version + '--优选广告位-' + '高质量素材') == getattr(row, 'campaign_name'):
  384. campaign_id = getattr(row, 'campaign_id')
  385. break
  386. single_video = [general_video_df.iloc[video_cnt, :].T.to_dict()]
  387. request_data = get_request_data(account_id=account_id,
  388. campaign_id=campaign_id,
  389. video_info=single_video,
  390. campaign_name=app_version + '--优选广告位-' + '高质量素材',
  391. group_name=app_version + '-优选广告位-不限-自定义-' + '高质量素材',
  392. ai_strategy_remark="高质量素材复建",
  393. unit_type=4,
  394. app_id=app_id,
  395. click_track_url=track_url)
  396. request = ai_strategy_request_parse(request_data)
  397. video_cnt += 1
  398. logger.info("account_id=%s, app_id=%s, 高质量素材复建-通用视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  399. else:
  400. logger.info("account_id=%s, 高质量素材复建: 返回的视频中没有通用视频" % account_id)
  401. else:
  402. logger.info("account_id=%s, 高质量素材复建: 没有获取到视频" % account_id)
  403. self.write(json.dumps({"message": "account_id=%s, 多应用的高质量素材复建请求已走完!" % account_id}))
  404. self.flush()
  405. else:
  406. video_info = get_top_video_info(account_id=account_id,
  407. cnt=high_quality_video_cnt,
  408. start_time=(datetime.datetime.now() +
  409. datetime.timedelta(days=-high_quality_video_days)).
  410. strftime("%Y-%m-%d %H:%M:%S"),
  411. end_time=(datetime.datetime.now() + datetime.timedelta(days=-1)).
  412. strftime("%Y-%m-%d %H:%M:%S"),
  413. url=get_high_quality_video_url)
  414. if video_info['code'] != 0:
  415. logger.info("account_id = %s, 高质量素材复建,没有获取到视频,不发送ai策略请求!" % account_id)
  416. self.write(json.dumps({"account_id": account_id,
  417. "message": "高质量素材复建,没有获取到视频,不发送ai策略请求!"}))
  418. self.flush()
  419. else:
  420. campaign_name, group_name = get_campaign_and_group_name_rule(account_id)
  421. if (campaign_name is None) or (group_name is None):
  422. logger.error("account_id = %s, 没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!" % account_id)
  423. self.write(json.dumps({"account_id": account_id,
  424. "message": "没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!"}))
  425. self.flush()
  426. else:
  427. request_data = get_request_data(account_id=account_id,
  428. campaign_id=campaign_id,
  429. video_info=video_info['data'],
  430. campaign_name=campaign_name,
  431. group_name=group_name,
  432. ai_strategy_remark="高质量素材复建",
  433. name_replace="高质量素材")
  434. request = ai_strategy_request_parse(request_data)
  435. logger.info("account_id = %s, 高质量素材复建,ai策略的返回信息:%s" % (account_id, request))
  436. self.write(json.dumps(request))
  437. self.flush()
  438. except Exception:
  439. logger.error("account_id = %s, traceback is %s" % (account_id, traceback.format_exc()))
  440. self.write(json.dumps({"account_id": account_id, "message": traceback.format_exc(), "code": -1}))
  441. self.flush()
  442. class AiCheckAndUpTOFullCreative(tornado.web.RequestHandler):
  443. """
  444. 每天22:00 调用该任务,检查当天创意是否创建达到上限,否则使用历史高质量素材填满
  445. """
  446. def post(self):
  447. data = self.request.body
  448. data = str(data, 'utf8')
  449. data = json.loads(data, encoding='utf8')
  450. logger.info("*************************************** NEW REQUEST ***************************************")
  451. account_id = data.get('account_id')
  452. campaign_id = data.get('campaign_id')
  453. logger.info("账户信息=%s, 当前进程=%s, 当前进程的主进程=%s, raw data from request is %s" %
  454. (account_id, os.getpid(), os.getppid(), data))
  455. try:
  456. start_time = (datetime.date.today()).strftime('%Y-%m-%d %H:%M:%S')
  457. end_time = (datetime.datetime.now()).strftime('%Y-%m-%d %H:%M:%S')
  458. now = datetime.datetime.now()
  459. # 1-1 从客户策略表中获取该账户下 每个素材搭配的封面个数, 来计算需要补充的素材个数
  460. sql = """
  461. select image_cnt from ctop_ai_kuaishou_advertiser_strategy
  462. where account_id = %s
  463. limit 1
  464. """ % account_id
  465. df = pd.read_sql(sql, engine)
  466. image_cnt = int(df['image_cnt'].values[0])
  467. # 2-1 从 ctop_kuaishou_creative 获取当天该账户到此刻 已经创建的创意个数
  468. video_cnt = 0
  469. sql = """
  470. select count(1) creative_cnt from ctop_kuaishou_creative
  471. where account_id = %s
  472. and creative_id is not NULL
  473. and creative_create_time <= '%s'
  474. and creative_create_time >= '%s'
  475. """ % (account_id, end_time, start_time)
  476. df = pd.read_sql(sql, engine)
  477. creative_cnt = int(df['creative_cnt'].values[0])
  478. if creative_cnt >= 2000:
  479. video_cnt = 0
  480. else:
  481. video_cnt = (2000 - creative_cnt) // image_cnt
  482. # 3-1 获取视频信息
  483. if video_cnt == 0:
  484. logger.info("account_id = %s, 创意已经建满,不需要补充素材!" % account_id)
  485. self.write(json.dumps({"account_id": account_id, "message": "创意已经建满,不需要补充素材!"}))
  486. self.flush()
  487. else:
  488. logger.info("account_id = %s, 需要补充的视频数量 = %s" % (account_id, video_cnt))
  489. sql = """select account_id, single_appid, app_id_array, general_track from ctop_ai_kuaishou_advertiser_strategy
  490. where account_id=%s order by create_time desc limit 1
  491. """ % account_id
  492. df = pd.read_sql(sql, engine)
  493. if df['general_track'].values[0] == 0:
  494. app_id_array = eval(df['app_id_array'].values[0])
  495. app_list = get_app_list(account_id=account_id, url=get_app_list_url)
  496. # app_dict key = ("appVersion": "ksjyrlyn-人类一脑涂地大败") , value = 完整的app_id信息
  497. app_dict = {}
  498. for app_info in app_list['data']:
  499. if app_info['appId'] in app_id_array:
  500. app_dict[app_info['appVersion']] = app_info
  501. video_list = get_top_video_info(account_id=account_id,
  502. url=get_high_quality_video_url,
  503. start_time=(now + datetime.timedelta(days=-2 * high_quality_video_days)).
  504. strftime("%Y-%m-%d %H:%M:%S"),
  505. end_time=(now + datetime.timedelta(days=-high_quality_video_days)).
  506. strftime("%Y-%m-%d %H:%M:%S"),
  507. cnt=video_cnt,
  508. app_version=None)
  509. # 单独处理返回的时候中,有通用视频,需要单独处理
  510. # "photo_name": "all",
  511. # "photo_name": "ksjytdrca-糖豆人冲啊",
  512. if video_list['code'] == 0:
  513. video_df = pd.DataFrame(video_list['data'])
  514. # 1-特定视频的创建
  515. special_video_df = video_df[video_df.photo_name != 'all']
  516. for photo_name in special_video_df['photo_name'].unique():
  517. if photo_name in app_dict.keys():
  518. campaign_id = None
  519. app_id = app_dict[photo_name].get('appId', 'error')
  520. app_version = app_dict[photo_name].get('appVersion', 'error')
  521. track_url = app_dict[photo_name].get('trackUrl', 'error')
  522. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  523. campaign_df = pd.read_sql(sql, engine)
  524. for row in campaign_df.itertuples():
  525. if (app_version + '--优选广告位-' + '高质量素材') == getattr(row, 'campaign_name'):
  526. campaign_id = getattr(row, 'campaign_id')
  527. break
  528. app_id_video_df = special_video_df[special_video_df.photo_name == photo_name]
  529. app_id_video_list = []
  530. for k, v in app_id_video_df.T.to_dict().items():
  531. app_id_video_list.append(v)
  532. request_data = get_request_data(account_id=account_id,
  533. campaign_id=campaign_id,
  534. video_info=app_id_video_list,
  535. campaign_name=app_version + '--优选广告位-' + '高质量素材',
  536. group_name=app_version + '-优选广告位-不限-自定义-' + '高质量素材',
  537. ai_strategy_remark="用高质量素材补满创意",
  538. unit_type=4,
  539. app_id=app_id,
  540. click_track_url=track_url)
  541. request = ai_strategy_request_parse(request_data)
  542. logger.info("account_id=%s, app_id=%s, 用高质量素材补满创意-特定视频,ai策略的返回信息:%s" %
  543. (account_id, app_id, request))
  544. # 2-通用视频的创建,random.shuffle 选择 app_id
  545. general_video_df = video_df[video_df.photo_name == 'all']
  546. if not general_video_df.empty:
  547. general_video_cnt = len(general_video_df)
  548. app_version_list = list(app_dict)
  549. random.shuffle(app_version_list)
  550. video_cnt = 0
  551. for app_version in app_version_list[:general_video_cnt]:
  552. campaign_id = None
  553. app_id = app_dict[app_version].get('appId', 'error')
  554. track_url = app_dict[app_version].get('trackUrl', 'error')
  555. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  556. campaign_df = pd.read_sql(sql, engine)
  557. for row in campaign_df.itertuples():
  558. if (app_version + '--优选广告位-' + '高质量素材') == getattr(row, 'campaign_name'):
  559. campaign_id = getattr(row, 'campaign_id')
  560. break
  561. single_video = [general_video_df.iloc[video_cnt, :].T.to_dict()]
  562. request_data = get_request_data(account_id=account_id,
  563. campaign_id=campaign_id,
  564. video_info=single_video,
  565. campaign_name=app_version + '--优选广告位-' + '高质量素材',
  566. group_name=app_version + '-优选广告位-不限-自定义-' + '高质量素材',
  567. ai_strategy_remark="用高质量素材补满创意",
  568. unit_type=4,
  569. app_id=app_id,
  570. click_track_url=track_url)
  571. request = ai_strategy_request_parse(request_data)
  572. video_cnt += 1
  573. logger.info("account_id=%s, app_id=%s, 用高质量素材补满创意-通用视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  574. else:
  575. logger.info("account_id=%s, 用高质量素材补满创意: 返回的视频中没有通用视频" % account_id)
  576. self.write(json.dumps({"message": "account_id=%s, 用高质量素材补满创意请求已走完!" % account_id}))
  577. self.flush()
  578. else:
  579. # 1-1 获取当天计划中包含“高质量素材”计划的,计划id
  580. sql = """
  581. select campaign_id, campaign_name from ctop_kuaishou_campaign
  582. where account_id = %s
  583. and put_create_time >= '%s'
  584. and put_create_time <= '%s'
  585. """ % (account_id, start_time, end_time)
  586. df = pd.read_sql(sql, engine)
  587. for row in df.itertuples():
  588. if '高质量素材' in getattr(row, 'campaign_name'):
  589. campaign_id = getattr(row, 'campaign_id')
  590. break
  591. video_info = get_top_video_info(account_id=account_id,
  592. cnt=video_cnt,
  593. start_time=(now + datetime.timedelta(days=-2 * high_quality_video_days)).
  594. strftime("%Y-%m-%d %H:%M:%S"),
  595. end_time=(now + datetime.timedelta(days=-high_quality_video_days)).
  596. strftime("%Y-%m-%d %H:%M:%S"),
  597. url=get_high_quality_video_url)
  598. if video_info['code'] != 0:
  599. logger.info("account_id = %s, 历史高质量素材填满, 没有获取到视频,不发送ai策略请求!" % account_id)
  600. self.write(json.dumps({"account_id": account_id,
  601. "message": "历史高质量素材填满, 没有获取到视频,不发送ai策略请求!"}))
  602. self.flush()
  603. else:
  604. campaign_name, group_name = get_campaign_and_group_name_rule(account_id)
  605. if (campaign_name is None) or (group_name is None):
  606. logger.info("account_id = %s, 没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!" % account_id)
  607. self.write(json.dumps({"account_id": account_id,
  608. "message": "没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!"}))
  609. self.flush()
  610. else:
  611. request_data = get_request_data(account_id=account_id,
  612. campaign_id=campaign_id,
  613. video_info=video_info['data'],
  614. campaign_name=campaign_name,
  615. group_name=group_name,
  616. ai_strategy_remark="用高质量素材补满创意",
  617. name_replace="高质量素材")
  618. request = ai_strategy_request_parse(request_data)
  619. logger.info("account_id = %s, 用高质量素材补满创意,ai策略的返回信息:%s" % (account_id, request))
  620. self.write(json.dumps(request))
  621. self.flush()
  622. except Exception:
  623. logger.error("account_id = %s, traceback is %s" % (account_id, traceback.format_exc()))
  624. self.write(json.dumps({"account_id": account_id, "message": traceback.format_exc(), "code": -1}))
  625. self.flush()
  626. class AiProgramCreativeHighQualityMaterial(tornado.web.RequestHandler):
  627. """
  628. 使用历史跑量素材创建程序化创意
  629. 跑量素材150个(近14天的素材)
  630. 计划名称--跑量素材程序化
  631. timeTask: 每天上午10点执行 --(0 0 10 * * ?)
  632. ----------------------------------------
  633. 拼装参数和写入数据库时,需要修改名称(程序化与非程序化不一致):
  634. creative_name --> package_name(程序化创意名称)
  635. action_bar_text --> action_bar(行动号召按钮)
  636. description --> captions(作品广告语)
  637. click_track_url --> click_url
  638. 写入数据库时:
  639. image_md5s --> cover_image_tokens
  640. 程序化与非程序化的逻辑不一样:
  641. 需要5个视频4张封面一组,拼装程序化创意参数需要单独抽取一个方法出来
  642. 所有操作记录表中,添加status信息(已提交,成功,失败),和回调时的 message信息
  643. """
  644. def post(self):
  645. data = self.request.body
  646. data = str(data, 'utf8')
  647. data = json.loads(data, encoding='utf8')
  648. logger.info("*************************************** NEW REQUEST ***************************************")
  649. account_id = data.get('account_id')
  650. campaign_id = data.get('campaign_id')
  651. logger.info("账户信息=%s, 当前进程=%s, 当前进程的主进程=%s, raw data from request is %s" %
  652. (account_id, os.getpid(), os.getppid(), data))
  653. try:
  654. sql = """select account_id, single_appid, app_id_array, general_track from ctop_ai_kuaishou_advertiser_strategy
  655. where account_id=%s order by create_time desc limit 1
  656. """ % account_id
  657. df = pd.read_sql(sql, engine)
  658. if df['general_track'].values[0] == 0:
  659. app_id_array = eval(df['app_id_array'].values[0])
  660. app_list = get_app_list(account_id=account_id, url=get_app_list_url)
  661. # app_dict key = ("appVersion": "ksjyrlyn-人类一脑涂地大败") , value = 完整的app_id信息
  662. app_dict = {}
  663. for app_info in app_list['data']:
  664. if app_info['appId'] in app_id_array:
  665. app_dict[app_info['appVersion']] = app_info
  666. video_list = get_top_video_info(account_id=account_id,
  667. cnt=multi_app_id_programme_high_quality_video_cnt,
  668. start_time=(datetime.datetime.now() + datetime.timedelta(
  669. days=-high_quality_video_days)).strftime("%Y-%m-%d %H:%M:%S"),
  670. end_time=(datetime.datetime.now() + datetime.timedelta(days=-1)).
  671. strftime("%Y-%m-%d %H:%M:%S"),
  672. url=get_high_quality_video_url)
  673. # 单独处理返回的时候中,有通用视频,需要单独处理
  674. # "photo_name": "all",
  675. # "photo_name": "ksjytdrca-糖豆人冲啊",
  676. if video_list['code'] == 0:
  677. video_df = pd.DataFrame(video_list['data'])
  678. # 1-特定视频的创建
  679. special_video_df = video_df[video_df.photo_name != 'all']
  680. for photo_name in special_video_df['photo_name'].unique():
  681. if photo_name in app_dict.keys():
  682. campaign_id = None
  683. app_id = app_dict[photo_name].get('appId', 'error')
  684. app_version = app_dict[photo_name].get('appVersion', 'error')
  685. track_url = app_dict[photo_name].get('trackUrl', 'error')
  686. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  687. campaign_df = pd.read_sql(sql, engine)
  688. for row in campaign_df.itertuples():
  689. if (app_version + '--优选广告位-' + '程序化高质量素材') == getattr(row, 'campaign_name'):
  690. campaign_id = getattr(row, 'campaign_id')
  691. break
  692. app_id_video_df = special_video_df[special_video_df.photo_name == photo_name]
  693. app_id_video_list = []
  694. for k, v in app_id_video_df.T.to_dict().items():
  695. app_id_video_list.append(v)
  696. request_data = get_request_data(account_id=account_id,
  697. campaign_id=campaign_id,
  698. video_info=app_id_video_list,
  699. campaign_name=app_version + '--优选广告位-' + '程序化高质量素材',
  700. group_name=app_version + '-优选广告位-不限-程序化-' + '高质量素材',
  701. ai_strategy_remark="程序化高质量素材",
  702. unit_type=7,
  703. app_id=app_id,
  704. click_track_url=track_url)
  705. request = ai_strategy_request_parse(request_data)
  706. logger.info("account_id=%s, app_id=%s, 程序化高质量素材-特定视频,ai策略的返回信息:%s" %
  707. (account_id, app_id, request))
  708. # 2-通用视频的创建,random.shuffle 选择 app_id
  709. general_video_df = video_df[video_df.photo_name == 'all']
  710. general_video_list = []
  711. for k, v in general_video_df.T.to_dict().items():
  712. general_video_list.append(v)
  713. if general_video_list:
  714. app_version_list = list(app_dict)
  715. random.shuffle(app_version_list)
  716. # 每5个通用视频创建一个程序化广告组
  717. batch_num = 5
  718. app_id_cnt = 0
  719. for i in range(0, len(general_video_list), 5):
  720. if i + 5 < len(general_video_list):
  721. batch_general_video = general_video_list[i: i + batch_num]
  722. app_version = app_version_list[app_id_cnt]
  723. app_id = app_dict[app_version].get('appId', 'error')
  724. track_url = app_dict[app_version].get('trackUrl', 'error')
  725. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  726. campaign_df = pd.read_sql(sql, engine)
  727. for row in campaign_df.itertuples():
  728. if (app_version + '--优选广告位-' + '程序化高质量素材') == getattr(row, 'campaign_name'):
  729. campaign_id = getattr(row, 'campaign_id')
  730. break
  731. request_data = get_request_data(account_id=account_id,
  732. campaign_id=campaign_id,
  733. video_info=batch_general_video,
  734. campaign_name=app_version + '--优选广告位-' + '程序化高质量素材',
  735. group_name=app_version + '-优选广告位-不限-程序化-' + '高质量素材',
  736. ai_strategy_remark="程序化高质量素材",
  737. unit_type=7,
  738. app_id=app_id,
  739. click_track_url=track_url)
  740. request = ai_strategy_request_parse(request_data)
  741. app_id_cnt += 1
  742. logger.info("account_id=%s, app_id=%s, 程序化高质量素材-通用视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  743. else:
  744. batch_general_video = general_video_list[i: len(general_video_list)]
  745. app_version = app_version_list[app_id_cnt]
  746. app_id = app_dict[app_version].get('appId', 'error')
  747. track_url = app_dict[app_version].get('trackUrl', 'error')
  748. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  749. campaign_df = pd.read_sql(sql, engine)
  750. for row in campaign_df.itertuples():
  751. if (app_version + '--优选广告位-' + '程序化高质量素材') == getattr(row, 'campaign_name'):
  752. campaign_id = getattr(row, 'campaign_id')
  753. break
  754. request_data = get_request_data(account_id=account_id,
  755. campaign_id=campaign_id,
  756. video_info=batch_general_video,
  757. campaign_name=app_version + '--优选广告位-' + '程序化高质量素材',
  758. group_name=app_version + '-优选广告位-不限-程序化-' + '高质量素材',
  759. ai_strategy_remark="程序化高质量素材",
  760. unit_type=7,
  761. app_id=app_id,
  762. click_track_url=track_url)
  763. request = ai_strategy_request_parse(request_data)
  764. logger.info("account_id=%s, app_id=%s, 程序化高质量素材-通用视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  765. else:
  766. logger.info("account_id=%s, 程序化高质量素材: 返回的视频中没有通用视频" % account_id)
  767. self.write(json.dumps({"message": "account_id=%s, 程序化高质量素材请求已走完!" % account_id}))
  768. self.flush()
  769. else:
  770. video_info = get_top_video_info(account_id=account_id,
  771. cnt=programme_high_quality_video_cnt,
  772. start_time=(datetime.datetime.now() + datetime.timedelta(
  773. days=-high_quality_video_days)).strftime("%Y-%m-%d %H:%M:%S"),
  774. end_time=(datetime.datetime.now() + datetime.timedelta(days=-1)).
  775. strftime("%Y-%m-%d %H:%M:%S"),
  776. url=get_high_quality_video_url)
  777. if video_info['code'] != 0:
  778. logger.info("account_id = %s, 程序化高质量素材,没有获取到视频,不发送ai策略请求!" % account_id)
  779. self.write(json.dumps({"account_id": account_id,
  780. "message": "没有获取到视频,不发送ai策略请求!"}))
  781. self.flush()
  782. else:
  783. campaign_name, group_name = get_campaign_and_group_name_rule(account_id)
  784. if (campaign_name is None) or (group_name is None):
  785. logger.info("account_id = %s, 没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!" % account_id)
  786. self.write(json.dumps({"account_id": account_id,
  787. "message": "没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!"}))
  788. self.flush()
  789. else:
  790. request_data = get_request_data(account_id=account_id,
  791. campaign_id=campaign_id,
  792. video_info=video_info['data'],
  793. campaign_name=campaign_name,
  794. group_name=group_name,
  795. ai_strategy_remark="程序化高质量素材",
  796. name_replace="程序化高质量素材",
  797. unit_type=7)
  798. request = ai_strategy_request_parse(request_data)
  799. logger.info("account_id = %s, 程序化高质量素材, ai策略的返回信息:%s" % (account_id, request))
  800. self.write(json.dumps(request))
  801. self.flush()
  802. except Exception:
  803. logger.error("account_id = %s, traceback is %s" % (account_id, traceback.format_exc()))
  804. self.write(json.dumps({"account_id": account_id, "message": traceback.format_exc(), "code": -1}))
  805. self.flush()
  806. class AiProgramCreativeNewMaterial(tornado.web.RequestHandler):
  807. """
  808. 使用N天内 创意数关联小于M个(如当天创意关联数小于10的,150个素材)的素材创建程序化创意
  809. 计划名称--新素材程序化
  810. timeTask: 每天上午10点执行 --(0 0 10 * * ?)
  811. """
  812. def post(self):
  813. data = self.request.body
  814. data = str(data, 'utf8')
  815. data = json.loads(data, encoding='utf8')
  816. logger.info("*************************************** NEW REQUEST ***************************************")
  817. account_id = data.get('account_id')
  818. campaign_id = data.get('campaign_id')
  819. logger.info("账户信息=%s, 当前进程=%s, 当前进程的主进程=%s, raw data from request is %s" %
  820. (account_id, os.getpid(), os.getppid(), data))
  821. try:
  822. sql = """select account_id, single_appid, app_id_array, general_track from ctop_ai_kuaishou_advertiser_strategy
  823. where account_id=%s order by create_time desc limit 1
  824. """ % account_id
  825. df = pd.read_sql(sql, engine)
  826. if df['general_track'].values[0] == 0:
  827. app_id_array = eval(df['app_id_array'].values[0])
  828. app_list = get_app_list(account_id=account_id, url=get_app_list_url)
  829. # app_dict key = ("appVersion": "ksjyrlyn-人类一脑涂地大败") , value = 完整的app_id信息
  830. app_dict = {}
  831. for app_info in app_list['data']:
  832. if app_info['appId'] in app_id_array:
  833. app_dict[app_info['appVersion']] = app_info
  834. video_list = get_history_video_info(account_id=account_id,
  835. url=get_history_video_url,
  836. start_time=(datetime.datetime.now() + datetime.timedelta(days=-7)).
  837. strftime("%Y-%m-%d %H:%M:%S"),
  838. end_time=(datetime.datetime.now() + datetime.timedelta(days=-1)).
  839. strftime("%Y-%m-%d %H:%M:%S"),
  840. video_cnt=multi_app_id_programme_new_video_cnt,
  841. related_creative_max_cnt=related_creative_max_cnt)
  842. # 单独处理返回的时候中,有通用视频,需要单独处理
  843. # "photo_name": "all",
  844. # "photo_name": "ksjytdrca-糖豆人冲啊",
  845. if video_list['code'] == 0:
  846. video_df = pd.DataFrame(video_list['data'])
  847. # 1-特定视频的创建
  848. special_video_df = video_df[video_df.photo_name != 'all']
  849. for photo_name in special_video_df['photo_name'].unique():
  850. if photo_name in app_dict.keys():
  851. campaign_id = None
  852. app_id = app_dict[photo_name].get('appId', 'error')
  853. app_version = app_dict[photo_name].get('appVersion', 'error')
  854. track_url = app_dict[photo_name].get('trackUrl', 'error')
  855. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  856. campaign_df = pd.read_sql(sql, engine)
  857. for row in campaign_df.itertuples():
  858. if (app_version + '--优选广告位-' + '程序化上新素材') == getattr(row, 'campaign_name'):
  859. campaign_id = getattr(row, 'campaign_id')
  860. break
  861. app_id_video_df = special_video_df[special_video_df.photo_name == photo_name]
  862. app_id_video_list = []
  863. for k, v in app_id_video_df.T.to_dict().items():
  864. app_id_video_list.append(v)
  865. request_data = get_request_data(account_id=account_id,
  866. campaign_id=campaign_id,
  867. video_info=app_id_video_list,
  868. campaign_name=app_version + '--优选广告位-' + '程序化上新素材',
  869. group_name=app_version + '-优选广告位-不限-程序化-' + '上新素材',
  870. ai_strategy_remark="程序化上新素材",
  871. unit_type=7,
  872. app_id=app_id,
  873. click_track_url=track_url)
  874. request = ai_strategy_request_parse(request_data)
  875. logger.info("account_id=%s, app_id=%s, 程序化上新素材-特定视频,ai策略的返回信息:%s" %
  876. (account_id, app_id, request))
  877. # 2-通用视频的创建,random.shuffle 选择 app_id
  878. general_video_df = video_df[video_df.photo_name == 'all']
  879. general_video_list = []
  880. for k, v in general_video_df.T.to_dict().items():
  881. general_video_list.append(v)
  882. if general_video_list:
  883. app_version_list = list(app_dict)
  884. random.shuffle(app_version_list)
  885. # 每5个通用视频创建一个程序化广告组
  886. batch_num = 5
  887. app_id_cnt = 0
  888. for i in range(0, len(general_video_list), 5):
  889. if i + 5 < len(general_video_list):
  890. batch_general_video = general_video_list[i: i + batch_num]
  891. app_version = app_version_list[app_id_cnt]
  892. app_id = app_dict[app_version].get('appId', 'error')
  893. track_url = app_dict[app_version].get('trackUrl', 'error')
  894. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  895. campaign_df = pd.read_sql(sql, engine)
  896. for row in campaign_df.itertuples():
  897. if (app_version + '--优选广告位-' + '程序化上新素材') == getattr(row, 'campaign_name'):
  898. campaign_id = getattr(row, 'campaign_id')
  899. break
  900. request_data = get_request_data(account_id=account_id,
  901. campaign_id=campaign_id,
  902. video_info=batch_general_video,
  903. campaign_name=app_version + '--优选广告位-' + '程序化上新素材',
  904. group_name=app_version + '-优选广告位-不限-程序化-' + '上新素材',
  905. ai_strategy_remark="程序化上新素材",
  906. unit_type=7,
  907. app_id=app_id,
  908. click_track_url=track_url)
  909. request = ai_strategy_request_parse(request_data)
  910. app_id_cnt += 1
  911. logger.info("account_id=%s, app_id=%s, 程序化上新素材-通用视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  912. else:
  913. batch_general_video = general_video_list[i: len(general_video_list)]
  914. app_version = app_version_list[app_id_cnt]
  915. app_id = app_dict[app_version].get('appId', 'error')
  916. track_url = app_dict[app_version].get('trackUrl', 'error')
  917. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  918. campaign_df = pd.read_sql(sql, engine)
  919. for row in campaign_df.itertuples():
  920. if (app_version + '--优选广告位-' + '程序化上新素材') == getattr(row, 'campaign_name'):
  921. campaign_id = getattr(row, 'campaign_id')
  922. break
  923. request_data = get_request_data(account_id=account_id,
  924. campaign_id=campaign_id,
  925. video_info=batch_general_video,
  926. campaign_name=app_version + '--优选广告位-' + '程序化上新素材',
  927. group_name=app_version + '-优选广告位-不限-程序化-' + '上新素材',
  928. ai_strategy_remark="程序化上新素材",
  929. unit_type=7,
  930. app_id=app_id,
  931. click_track_url=track_url)
  932. request = ai_strategy_request_parse(request_data)
  933. logger.info("account_id=%s, app_id=%s, 程序化上新素材-通用视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  934. else:
  935. logger.info("account_id=%s, 程序化上新素材: 返回的视频中没有通用视频" % account_id)
  936. self.write(json.dumps({"message": "account_id=%s, 程序化上新素材请求已走完!" % account_id}))
  937. self.flush()
  938. else:
  939. video_info = get_history_video_info(account_id=account_id,
  940. url=get_history_video_url,
  941. start_time=(datetime.datetime.now() + datetime.timedelta(days=-7)).
  942. strftime("%Y-%m-%d %H:%M:%S"),
  943. end_time=(datetime.datetime.now() + datetime.timedelta(days=-1)).
  944. strftime("%Y-%m-%d %H:%M:%S"),
  945. video_cnt=programme_new_video_cnt,
  946. related_creative_max_cnt=related_creative_max_cnt)
  947. if video_info['code'] != 0:
  948. self.write(json.dumps({"account_id": account_id,
  949. "message": "程序化上新素材,没有获取到视频,不发送ai策略请求!"}))
  950. self.flush()
  951. else:
  952. campaign_name, group_name = get_campaign_and_group_name_rule(account_id)
  953. if (campaign_name is None) or (group_name is None):
  954. logger.info("没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!")
  955. self.write(json.dumps({"message": "没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!"}))
  956. self.flush()
  957. else:
  958. request_data = get_request_data(account_id=account_id,
  959. campaign_id=campaign_id,
  960. video_info=video_info['data'],
  961. campaign_name=campaign_name,
  962. group_name=group_name,
  963. ai_strategy_remark="程序化上新素材",
  964. name_replace="程序化上新素材",
  965. unit_type=7)
  966. request = ai_strategy_request_parse(request_data)
  967. logger.info("account_id = %s, 程序化上新素材,ai策略的返回信息:%s" % (account_id, request))
  968. self.write(json.dumps(request))
  969. self.flush()
  970. except Exception:
  971. logger.error("account_id = %s, traceback is %s" % (account_id, traceback.format_exc()))
  972. self.write(json.dumps({"account_id": account_id, "message": traceback.format_exc(), "code": -1}))
  973. self.flush()