ai_time_task_creative_handler.py 71 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016
  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(traceback.format_exc())
  154. self.write(json.dumps(traceback.format_exc()))
  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(traceback.format_exc())
  299. self.write(json.dumps(traceback.format_exc()))
  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.date.today().strftime("%Y-%m-%d %H:%M:%S"),
  333. url=get_high_quality_video_url)
  334. # 单独处理返回的时候中,有通用视频,需要单独处理
  335. # "photo_name": "all",
  336. # "photo_name": "ksjytdrca-糖豆人冲啊",
  337. if video_list['code'] == 0:
  338. video_df = pd.DataFrame(video_list['data'])
  339. # 1-特定视频的创建
  340. special_video_df = video_df[video_df.photo_name != 'all']
  341. for photo_name in special_video_df['photo_name'].unique():
  342. if photo_name in app_dict.keys():
  343. campaign_id = None
  344. app_id = app_dict[photo_name].get('appId', 'error')
  345. app_version = app_dict[photo_name].get('appVersion', 'error')
  346. track_url = app_dict[photo_name].get('trackUrl', 'error')
  347. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  348. campaign_df = pd.read_sql(sql, engine)
  349. for row in campaign_df.itertuples():
  350. if (app_version + '--优选广告位-' + '高质量素材') == getattr(row, 'campaign_name'):
  351. campaign_id = getattr(row, 'campaign_id')
  352. break
  353. app_id_video_df = special_video_df[special_video_df.photo_name == photo_name]
  354. app_id_video_list = []
  355. for k, v in app_id_video_df.T.to_dict().items():
  356. app_id_video_list.append(v)
  357. request_data = get_request_data(account_id=account_id,
  358. campaign_id=campaign_id,
  359. video_info=app_id_video_list,
  360. campaign_name=app_version + '--优选广告位-' + '高质量素材',
  361. group_name=app_version + '-优选广告位-不限-自定义-' + '高质量素材',
  362. ai_strategy_remark="高质量素材复建",
  363. unit_type=4,
  364. app_id=app_id,
  365. click_track_url=track_url)
  366. request = ai_strategy_request_parse(request_data)
  367. logger.info("account_id=%s, app_id=%s, 高质量素材复建-特定视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  368. # 2-通用视频的创建,random.shuffle 选择 app_id
  369. general_video_df = video_df[video_df.photo_name == 'all']
  370. if not general_video_df.empty:
  371. general_video_cnt = len(general_video_df)
  372. app_version_list = list(app_dict)
  373. random.shuffle(app_version_list)
  374. video_cnt = 0
  375. for app_version in app_version_list[:general_video_cnt]:
  376. campaign_id = None
  377. app_id = app_dict[app_version].get('appId', 'error')
  378. track_url = app_dict[app_version].get('trackUrl', 'error')
  379. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  380. campaign_df = pd.read_sql(sql, engine)
  381. for row in campaign_df.itertuples():
  382. if (app_version + '--优选广告位-' + '高质量素材') == getattr(row, 'campaign_name'):
  383. campaign_id = getattr(row, 'campaign_id')
  384. break
  385. single_video = [general_video_df.iloc[video_cnt, :].T.to_dict()]
  386. request_data = get_request_data(account_id=account_id,
  387. campaign_id=campaign_id,
  388. video_info=single_video,
  389. campaign_name=app_version + '--优选广告位-' + '高质量素材',
  390. group_name=app_version + '-优选广告位-不限-自定义-' + '高质量素材',
  391. ai_strategy_remark="高质量素材复建",
  392. unit_type=4,
  393. app_id=app_id,
  394. click_track_url=track_url)
  395. request = ai_strategy_request_parse(request_data)
  396. video_cnt += 1
  397. logger.info("account_id=%s, app_id=%s, 高质量素材复建-通用视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  398. else:
  399. logger.info("account_id=%s, 高质量素材复建: 返回的视频中没有通用视频" % account_id)
  400. else:
  401. logger.info("account_id=%s, 高质量素材复建: 没有获取到视频" % account_id)
  402. self.write(json.dumps({"message": "account_id=%s, 多应用的高质量素材复建请求已走完!" % account_id}))
  403. self.flush()
  404. else:
  405. video_info = get_top_video_info(account_id=account_id,
  406. cnt=high_quality_video_cnt,
  407. start_time=(datetime.datetime.now() +
  408. datetime.timedelta(days=-high_quality_video_days)).
  409. strftime("%Y-%m-%d %H:%M:%S"),
  410. end_time=datetime.date.today().strftime("%Y-%m-%d %H:%M:%S"),
  411. url=get_high_quality_video_url)
  412. if video_info['code'] != 0:
  413. logger.info("account_id = %s, 高质量素材复建,没有获取到视频,不发送ai策略请求!" % account_id)
  414. self.write(json.dumps({"account_id": account_id,
  415. "message": "高质量素材复建,没有获取到视频,不发送ai策略请求!"}))
  416. self.flush()
  417. else:
  418. campaign_name, group_name = get_campaign_and_group_name_rule(account_id)
  419. if (campaign_name is None) or (group_name is None):
  420. logger.error("account_id = %s, 没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!" % account_id)
  421. self.write(json.dumps({"account_id": account_id,
  422. "message": "没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!"}))
  423. self.flush()
  424. else:
  425. request_data = get_request_data(account_id=account_id,
  426. campaign_id=campaign_id,
  427. video_info=video_info['data'],
  428. campaign_name=campaign_name,
  429. group_name=group_name,
  430. ai_strategy_remark="高质量素材复建",
  431. name_replace="高质量素材")
  432. request = ai_strategy_request_parse(request_data)
  433. logger.info("account_id = %s, 高质量素材复建,ai策略的返回信息:%s" % (account_id, request))
  434. self.write(json.dumps(request))
  435. self.flush()
  436. except Exception:
  437. logger.error(traceback.format_exc())
  438. self.write(json.dumps(traceback.format_exc()))
  439. self.flush()
  440. class AiCheckAndUpTOFullCreative(tornado.web.RequestHandler):
  441. """
  442. 每天22:00 调用该任务,检查当天创意是否创建达到上限,否则使用历史高质量素材填满
  443. """
  444. def post(self):
  445. data = self.request.body
  446. data = str(data, 'utf8')
  447. data = json.loads(data, encoding='utf8')
  448. logger.info("*************************************** NEW REQUEST ***************************************")
  449. account_id = data.get('account_id')
  450. campaign_id = data.get('campaign_id')
  451. logger.info("账户信息=%s, 当前进程=%s, 当前进程的主进程=%s, raw data from request is %s" %
  452. (account_id, os.getpid(), os.getppid(), data))
  453. try:
  454. start_time = (datetime.date.today()).strftime('%Y-%m-%d %H:%M:%S')
  455. end_time = (datetime.datetime.now()).strftime('%Y-%m-%d %H:%M:%S')
  456. now = datetime.datetime.now()
  457. # 1-1 从客户策略表中获取该账户下 每个素材搭配的封面个数, 来计算需要补充的素材个数
  458. sql = """
  459. select image_cnt from ctop_ai_kuaishou_advertiser_strategy
  460. where account_id = %s
  461. limit 1
  462. """ % account_id
  463. df = pd.read_sql(sql, engine)
  464. image_cnt = int(df['image_cnt'].values[0])
  465. # 2-1 从 ctop_kuaishou_creative 获取当天该账户到此刻 已经创建的创意个数
  466. video_cnt = 0
  467. sql = """
  468. select count(1) creative_cnt from ctop_kuaishou_creative
  469. where account_id = %s
  470. and creative_id is not NULL
  471. and creative_create_time <= '%s'
  472. and creative_create_time >= '%s'
  473. """ % (account_id, end_time, start_time)
  474. df = pd.read_sql(sql, engine)
  475. creative_cnt = int(df['creative_cnt'].values[0])
  476. if creative_cnt >= 2000:
  477. video_cnt = 0
  478. else:
  479. video_cnt = (2000 - creative_cnt) // image_cnt
  480. # 3-1 获取视频信息
  481. if video_cnt == 0:
  482. logger.info("account_id = %s, 创意已经建满,不需要补充素材!" % account_id)
  483. self.write(json.dumps({"account_id": account_id, "message": "创意已经建满,不需要补充素材!"}))
  484. self.flush()
  485. else:
  486. logger.info("account_id = %s, 需要补充的视频数量 = %s" % (account_id, video_cnt))
  487. sql = """select account_id, single_appid, app_id_array, general_track from ctop_ai_kuaishou_advertiser_strategy
  488. where account_id=%s order by create_time desc limit 1
  489. """ % account_id
  490. df = pd.read_sql(sql, engine)
  491. if df['general_track'].values[0] == 0:
  492. app_id_array = eval(df['app_id_array'].values[0])
  493. app_list = get_app_list(account_id=account_id, url=get_app_list_url)
  494. # app_dict key = ("appVersion": "ksjyrlyn-人类一脑涂地大败") , value = 完整的app_id信息
  495. app_dict = {}
  496. for app_info in app_list['data']:
  497. if app_info['appId'] in app_id_array:
  498. app_dict[app_info['appVersion']] = app_info
  499. video_list = get_top_video_info(account_id=account_id,
  500. url=get_high_quality_video_url,
  501. start_time=(now + datetime.timedelta(days=-2*high_quality_video_days)).
  502. strftime("%Y-%m-%d %H:%M:%S"),
  503. end_time=(now + datetime.timedelta(days=-high_quality_video_days)).
  504. strftime("%Y-%m-%d %H:%M:%S"),
  505. cnt=video_cnt,
  506. app_version=None)
  507. # 单独处理返回的时候中,有通用视频,需要单独处理
  508. # "photo_name": "all",
  509. # "photo_name": "ksjytdrca-糖豆人冲啊",
  510. if video_list['code'] == 0:
  511. video_df = pd.DataFrame(video_list['data'])
  512. # 1-特定视频的创建
  513. special_video_df = video_df[video_df.photo_name != 'all']
  514. for photo_name in special_video_df['photo_name'].unique():
  515. if photo_name in app_dict.keys():
  516. campaign_id = None
  517. app_id = app_dict[photo_name].get('appId', 'error')
  518. app_version = app_dict[photo_name].get('appVersion', 'error')
  519. track_url = app_dict[photo_name].get('trackUrl', 'error')
  520. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  521. campaign_df = pd.read_sql(sql, engine)
  522. for row in campaign_df.itertuples():
  523. if (app_version + '--优选广告位-' + '高质量素材') == getattr(row, 'campaign_name'):
  524. campaign_id = getattr(row, 'campaign_id')
  525. break
  526. app_id_video_df = special_video_df[special_video_df.photo_name == photo_name]
  527. app_id_video_list = []
  528. for k, v in app_id_video_df.T.to_dict().items():
  529. app_id_video_list.append(v)
  530. request_data = get_request_data(account_id=account_id,
  531. campaign_id=campaign_id,
  532. video_info=app_id_video_list,
  533. campaign_name=app_version + '--优选广告位-' + '高质量素材',
  534. group_name=app_version + '-优选广告位-不限-自定义-' + '高质量素材',
  535. ai_strategy_remark="用高质量素材补满创意",
  536. unit_type=4,
  537. app_id=app_id,
  538. click_track_url=track_url)
  539. request = ai_strategy_request_parse(request_data)
  540. logger.info("account_id=%s, app_id=%s, 用高质量素材补满创意-特定视频,ai策略的返回信息:%s" %
  541. (account_id, app_id, request))
  542. # 2-通用视频的创建,random.shuffle 选择 app_id
  543. general_video_df = video_df[video_df.photo_name == 'all']
  544. if not general_video_df.empty:
  545. general_video_cnt = len(general_video_df)
  546. app_version_list = list(app_dict)
  547. random.shuffle(app_version_list)
  548. video_cnt = 0
  549. for app_version in app_version_list[:general_video_cnt]:
  550. campaign_id = None
  551. app_id = app_dict[app_version].get('appId', 'error')
  552. track_url = app_dict[app_version].get('trackUrl', 'error')
  553. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  554. campaign_df = pd.read_sql(sql, engine)
  555. for row in campaign_df.itertuples():
  556. if (app_version + '--优选广告位-' + '高质量素材') == getattr(row, 'campaign_name'):
  557. campaign_id = getattr(row, 'campaign_id')
  558. break
  559. single_video = [general_video_df.iloc[video_cnt, :].T.to_dict()]
  560. request_data = get_request_data(account_id=account_id,
  561. campaign_id=campaign_id,
  562. video_info=single_video,
  563. campaign_name=app_version + '--优选广告位-' + '高质量素材',
  564. group_name=app_version + '-优选广告位-不限-自定义-' + '高质量素材',
  565. ai_strategy_remark="用高质量素材补满创意",
  566. unit_type=4,
  567. app_id=app_id,
  568. click_track_url=track_url)
  569. request = ai_strategy_request_parse(request_data)
  570. video_cnt += 1
  571. logger.info("account_id=%s, app_id=%s, 用高质量素材补满创意-通用视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  572. else:
  573. logger.info("account_id=%s, 用高质量素材补满创意: 返回的视频中没有通用视频" % account_id)
  574. self.write(json.dumps({"message": "account_id=%s, 用高质量素材补满创意请求已走完!" % account_id}))
  575. self.flush()
  576. else:
  577. # 1-1 获取当天计划中包含“高质量素材”计划的,计划id
  578. sql = """
  579. select campaign_id, campaign_name from ctop_kuaishou_campaign
  580. where account_id = %s
  581. and put_create_time >= '%s'
  582. and put_create_time <= '%s'
  583. """ % (account_id, start_time, end_time)
  584. df = pd.read_sql(sql, engine)
  585. for row in df.itertuples():
  586. if '高质量素材' in getattr(row, 'campaign_name'):
  587. campaign_id = getattr(row, 'campaign_id')
  588. break
  589. video_info = get_top_video_info(account_id=account_id,
  590. cnt=video_cnt,
  591. start_time=(now + datetime.timedelta(days=-2*high_quality_video_days)).
  592. strftime("%Y-%m-%d %H:%M:%S"),
  593. end_time=(now + datetime.timedelta(days=-high_quality_video_days)).
  594. strftime("%Y-%m-%d %H:%M:%S"),
  595. url=get_high_quality_video_url)
  596. if video_info['code'] != 0:
  597. logger.info("account_id = %s, 历史高质量素材填满, 没有获取到视频,不发送ai策略请求!" % account_id)
  598. self.write(json.dumps({"account_id": account_id,
  599. "message": "历史高质量素材填满, 没有获取到视频,不发送ai策略请求!"}))
  600. self.flush()
  601. else:
  602. campaign_name, group_name = get_campaign_and_group_name_rule(account_id)
  603. if (campaign_name is None) or (group_name is None):
  604. logger.info("account_id = %s, 没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!" % account_id)
  605. self.write(json.dumps({"account_id": account_id,
  606. "message": "没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!"}))
  607. self.flush()
  608. else:
  609. request_data = get_request_data(account_id=account_id,
  610. campaign_id=campaign_id,
  611. video_info=video_info['data'],
  612. campaign_name=campaign_name,
  613. group_name=group_name,
  614. ai_strategy_remark="用高质量素材补满创意",
  615. name_replace="高质量素材")
  616. request = ai_strategy_request_parse(request_data)
  617. logger.info("account_id = %s, 用高质量素材补满创意,ai策略的返回信息:%s" % (account_id, request))
  618. self.write(json.dumps(request))
  619. self.flush()
  620. except Exception:
  621. logger.error(traceback.format_exc())
  622. self.write(json.dumps(traceback.format_exc()))
  623. self.flush()
  624. class AiProgramCreativeHighQualityMaterial(tornado.web.RequestHandler):
  625. """
  626. 使用历史跑量素材创建程序化创意
  627. 跑量素材150个(近14天的素材)
  628. 计划名称--跑量素材程序化
  629. timeTask: 每天上午10点执行 --(0 0 10 * * ?)
  630. ----------------------------------------
  631. 拼装参数和写入数据库时,需要修改名称(程序化与非程序化不一致):
  632. creative_name --> package_name(程序化创意名称)
  633. action_bar_text --> action_bar(行动号召按钮)
  634. description --> captions(作品广告语)
  635. click_track_url --> click_url
  636. 写入数据库时:
  637. image_md5s --> cover_image_tokens
  638. 程序化与非程序化的逻辑不一样:
  639. 需要5个视频4张封面一组,拼装程序化创意参数需要单独抽取一个方法出来
  640. 所有操作记录表中,添加status信息(已提交,成功,失败),和回调时的 message信息
  641. """
  642. def post(self):
  643. data = self.request.body
  644. data = str(data, 'utf8')
  645. data = json.loads(data, encoding='utf8')
  646. logger.info("*************************************** NEW REQUEST ***************************************")
  647. account_id = data.get('account_id')
  648. campaign_id = data.get('campaign_id')
  649. logger.info("账户信息=%s, 当前进程=%s, 当前进程的主进程=%s, raw data from request is %s" %
  650. (account_id, os.getpid(), os.getppid(), data))
  651. try:
  652. sql = """select account_id, single_appid, app_id_array, general_track from ctop_ai_kuaishou_advertiser_strategy
  653. where account_id=%s order by create_time desc limit 1
  654. """ % account_id
  655. df = pd.read_sql(sql, engine)
  656. if df['general_track'].values[0] == 0:
  657. app_id_array = eval(df['app_id_array'].values[0])
  658. app_list = get_app_list(account_id=account_id, url=get_app_list_url)
  659. # app_dict key = ("appVersion": "ksjyrlyn-人类一脑涂地大败") , value = 完整的app_id信息
  660. app_dict = {}
  661. for app_info in app_list['data']:
  662. if app_info['appId'] in app_id_array:
  663. app_dict[app_info['appVersion']] = app_info
  664. video_list = get_top_video_info(account_id=account_id,
  665. cnt=multi_app_id_programme_high_quality_video_cnt,
  666. start_time=(datetime.datetime.now() + datetime.timedelta(
  667. days=-high_quality_video_days)).strftime("%Y-%m-%d %H:%M:%S"),
  668. end_time=datetime.date.today().strftime("%Y-%m-%d %H:%M:%S"),
  669. url=get_high_quality_video_url)
  670. # 单独处理返回的时候中,有通用视频,需要单独处理
  671. # "photo_name": "all",
  672. # "photo_name": "ksjytdrca-糖豆人冲啊",
  673. if video_list['code'] == 0:
  674. video_df = pd.DataFrame(video_list['data'])
  675. # 1-特定视频的创建
  676. special_video_df = video_df[video_df.photo_name != 'all']
  677. for photo_name in special_video_df['photo_name'].unique():
  678. if photo_name in app_dict.keys():
  679. campaign_id = None
  680. app_id = app_dict[photo_name].get('appId', 'error')
  681. app_version = app_dict[photo_name].get('appVersion', 'error')
  682. track_url = app_dict[photo_name].get('trackUrl', 'error')
  683. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  684. campaign_df = pd.read_sql(sql, engine)
  685. for row in campaign_df.itertuples():
  686. if (app_version + '--优选广告位-' + '程序化高质量素材') == getattr(row, 'campaign_name'):
  687. campaign_id = getattr(row, 'campaign_id')
  688. break
  689. app_id_video_df = special_video_df[special_video_df.photo_name == photo_name]
  690. app_id_video_list = []
  691. for k, v in app_id_video_df.T.to_dict().items():
  692. app_id_video_list.append(v)
  693. request_data = get_request_data(account_id=account_id,
  694. campaign_id=campaign_id,
  695. video_info=app_id_video_list,
  696. campaign_name=app_version + '--优选广告位-' + '程序化高质量素材',
  697. group_name=app_version + '-优选广告位-不限-程序化-' + '高质量素材',
  698. ai_strategy_remark="程序化高质量素材",
  699. unit_type=7,
  700. app_id=app_id,
  701. click_track_url=track_url)
  702. request = ai_strategy_request_parse(request_data)
  703. logger.info("account_id=%s, app_id=%s, 程序化高质量素材-特定视频,ai策略的返回信息:%s" %
  704. (account_id, app_id, request))
  705. # 2-通用视频的创建,random.shuffle 选择 app_id
  706. general_video_df = video_df[video_df.photo_name == 'all']
  707. general_video_list = []
  708. for k, v in general_video_df.T.to_dict().items():
  709. general_video_list.append(v)
  710. if general_video_list:
  711. app_version_list = list(app_dict)
  712. random.shuffle(app_version_list)
  713. # 每5个通用视频创建一个程序化广告组
  714. batch_num = 5
  715. app_id_cnt = 0
  716. for i in range(0, len(general_video_list), 5):
  717. if i + 5 < len(general_video_list):
  718. batch_general_video = general_video_list[i: i+batch_num]
  719. app_version = app_version_list[app_id_cnt]
  720. app_id = app_dict[app_version].get('appId', 'error')
  721. track_url = app_dict[app_version].get('trackUrl', 'error')
  722. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  723. campaign_df = pd.read_sql(sql, engine)
  724. for row in campaign_df.itertuples():
  725. if (app_version + '--优选广告位-' + '程序化高质量素材') == getattr(row, 'campaign_name'):
  726. campaign_id = getattr(row, 'campaign_id')
  727. break
  728. request_data = get_request_data(account_id=account_id,
  729. campaign_id=campaign_id,
  730. video_info=batch_general_video,
  731. campaign_name=app_version + '--优选广告位-' + '程序化高质量素材',
  732. group_name=app_version + '-优选广告位-不限-程序化-' + '高质量素材',
  733. ai_strategy_remark="程序化高质量素材",
  734. unit_type=7,
  735. app_id=app_id,
  736. click_track_url=track_url)
  737. request = ai_strategy_request_parse(request_data)
  738. app_id_cnt += 1
  739. logger.info("account_id=%s, app_id=%s, 程序化高质量素材-通用视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  740. else:
  741. batch_general_video = general_video_list[i: len(general_video_list)]
  742. app_version = app_version_list[app_id_cnt]
  743. app_id = app_dict[app_version].get('appId', 'error')
  744. track_url = app_dict[app_version].get('trackUrl', 'error')
  745. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  746. campaign_df = pd.read_sql(sql, engine)
  747. for row in campaign_df.itertuples():
  748. if (app_version + '--优选广告位-' + '程序化高质量素材') == getattr(row, 'campaign_name'):
  749. campaign_id = getattr(row, 'campaign_id')
  750. break
  751. request_data = get_request_data(account_id=account_id,
  752. campaign_id=campaign_id,
  753. video_info=batch_general_video,
  754. campaign_name=app_version + '--优选广告位-' + '程序化高质量素材',
  755. group_name=app_version + '-优选广告位-不限-程序化-' + '高质量素材',
  756. ai_strategy_remark="程序化高质量素材",
  757. unit_type=7,
  758. app_id=app_id,
  759. click_track_url=track_url)
  760. request = ai_strategy_request_parse(request_data)
  761. logger.info("account_id=%s, app_id=%s, 程序化高质量素材-通用视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  762. else:
  763. logger.info("account_id=%s, 程序化高质量素材: 返回的视频中没有通用视频" % account_id)
  764. self.write(json.dumps({"message": "account_id=%s, 程序化高质量素材请求已走完!" % account_id}))
  765. self.flush()
  766. else:
  767. video_info = get_top_video_info(account_id=account_id,
  768. cnt=programme_high_quality_video_cnt,
  769. start_time=(datetime.datetime.now() + datetime.timedelta(
  770. days=-high_quality_video_days)).strftime("%Y-%m-%d %H:%M:%S"),
  771. end_time=datetime.date.today().strftime("%Y-%m-%d %H:%M:%S"),
  772. url=get_high_quality_video_url)
  773. if video_info['code'] != 0:
  774. logger.info("account_id = %s, 程序化高质量素材,没有获取到视频,不发送ai策略请求!" % account_id)
  775. self.write(json.dumps({"account_id": account_id,
  776. "message": "没有获取到视频,不发送ai策略请求!"}))
  777. self.flush()
  778. else:
  779. campaign_name, group_name = get_campaign_and_group_name_rule(account_id)
  780. if (campaign_name is None) or (group_name is None):
  781. logger.info("account_id = %s, 没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!" % account_id)
  782. self.write(json.dumps({"account_id": account_id,
  783. "message": "没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!"}))
  784. self.flush()
  785. else:
  786. request_data = get_request_data(account_id=account_id,
  787. campaign_id=campaign_id,
  788. video_info=video_info['data'],
  789. campaign_name=campaign_name,
  790. group_name=group_name,
  791. ai_strategy_remark="程序化高质量素材",
  792. name_replace="程序化高质量素材",
  793. unit_type=7)
  794. request = ai_strategy_request_parse(request_data)
  795. logger.info("account_id = %s, 程序化高质量素材, ai策略的返回信息:%s" % (account_id, request))
  796. self.write(json.dumps(request))
  797. self.flush()
  798. except Exception:
  799. logger.error(traceback.format_exc())
  800. self.write(json.dumps(traceback.format_exc()))
  801. self.flush()
  802. class AiProgramCreativeNewMaterial(tornado.web.RequestHandler):
  803. """
  804. 使用N天内 创意数关联小于M个(如当天创意关联数小于10的,150个素材)的素材创建程序化创意
  805. 计划名称--新素材程序化
  806. timeTask: 每天上午10点执行 --(0 0 10 * * ?)
  807. """
  808. def post(self):
  809. data = self.request.body
  810. data = str(data, 'utf8')
  811. data = json.loads(data, encoding='utf8')
  812. logger.info("*************************************** NEW REQUEST ***************************************")
  813. account_id = data.get('account_id')
  814. campaign_id = data.get('campaign_id')
  815. logger.info("账户信息=%s, 当前进程=%s, 当前进程的主进程=%s, raw data from request is %s" %
  816. (account_id, os.getpid(), os.getppid(), data))
  817. try:
  818. sql = """select account_id, single_appid, app_id_array, general_track from ctop_ai_kuaishou_advertiser_strategy
  819. where account_id=%s order by create_time desc limit 1
  820. """ % account_id
  821. df = pd.read_sql(sql, engine)
  822. if df['general_track'].values[0] == 0:
  823. app_id_array = eval(df['app_id_array'].values[0])
  824. app_list = get_app_list(account_id=account_id, url=get_app_list_url)
  825. # app_dict key = ("appVersion": "ksjyrlyn-人类一脑涂地大败") , value = 完整的app_id信息
  826. app_dict = {}
  827. for app_info in app_list['data']:
  828. if app_info['appId'] in app_id_array:
  829. app_dict[app_info['appVersion']] = app_info
  830. video_list = get_history_video_info(account_id=account_id,
  831. url=get_history_video_url,
  832. start_time=(datetime.datetime.now() + datetime.timedelta(days=-7)).
  833. strftime("%Y-%m-%d %H:%M:%S"),
  834. end_time=datetime.date.today().strftime("%Y-%m-%d %H:%M:%S"),
  835. video_cnt=multi_app_id_programme_new_video_cnt,
  836. related_creative_max_cnt=related_creative_max_cnt)
  837. # 单独处理返回的时候中,有通用视频,需要单独处理
  838. # "photo_name": "all",
  839. # "photo_name": "ksjytdrca-糖豆人冲啊",
  840. if video_list['code'] == 0:
  841. video_df = pd.DataFrame(video_list['data'])
  842. # 1-特定视频的创建
  843. special_video_df = video_df[video_df.photo_name != 'all']
  844. for photo_name in special_video_df['photo_name'].unique():
  845. if photo_name in app_dict.keys():
  846. campaign_id = None
  847. app_id = app_dict[photo_name].get('appId', 'error')
  848. app_version = app_dict[photo_name].get('appVersion', 'error')
  849. track_url = app_dict[photo_name].get('trackUrl', 'error')
  850. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  851. campaign_df = pd.read_sql(sql, engine)
  852. for row in campaign_df.itertuples():
  853. if (app_version + '--优选广告位-' + '程序化上新素材') == getattr(row, 'campaign_name'):
  854. campaign_id = getattr(row, 'campaign_id')
  855. break
  856. app_id_video_df = special_video_df[special_video_df.photo_name == photo_name]
  857. app_id_video_list = []
  858. for k, v in app_id_video_df.T.to_dict().items():
  859. app_id_video_list.append(v)
  860. request_data = get_request_data(account_id=account_id,
  861. campaign_id=campaign_id,
  862. video_info=app_id_video_list,
  863. campaign_name=app_version + '--优选广告位-' + '程序化上新素材',
  864. group_name=app_version + '-优选广告位-不限-程序化-' + '上新素材',
  865. ai_strategy_remark="程序化上新素材",
  866. unit_type=7,
  867. app_id=app_id,
  868. click_track_url=track_url)
  869. request = ai_strategy_request_parse(request_data)
  870. logger.info("account_id=%s, app_id=%s, 程序化上新素材-特定视频,ai策略的返回信息:%s" %
  871. (account_id, app_id, request))
  872. # 2-通用视频的创建,random.shuffle 选择 app_id
  873. general_video_df = video_df[video_df.photo_name == 'all']
  874. general_video_list = []
  875. for k, v in general_video_df.T.to_dict().items():
  876. general_video_list.append(v)
  877. if general_video_list:
  878. app_version_list = list(app_dict)
  879. random.shuffle(app_version_list)
  880. # 每5个通用视频创建一个程序化广告组
  881. batch_num = 5
  882. app_id_cnt = 0
  883. for i in range(0, len(general_video_list), 5):
  884. if i + 5 < len(general_video_list):
  885. batch_general_video = general_video_list[i: i + batch_num]
  886. app_version = app_version_list[app_id_cnt]
  887. app_id = app_dict[app_version].get('appId', 'error')
  888. track_url = app_dict[app_version].get('trackUrl', 'error')
  889. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  890. campaign_df = pd.read_sql(sql, engine)
  891. for row in campaign_df.itertuples():
  892. if (app_version + '--优选广告位-' + '程序化上新素材') == getattr(row, 'campaign_name'):
  893. campaign_id = getattr(row, 'campaign_id')
  894. break
  895. request_data = get_request_data(account_id=account_id,
  896. campaign_id=campaign_id,
  897. video_info=batch_general_video,
  898. campaign_name=app_version + '--优选广告位-' + '程序化上新素材',
  899. group_name=app_version + '-优选广告位-不限-程序化-' + '上新素材',
  900. ai_strategy_remark="程序化上新素材",
  901. unit_type=7,
  902. app_id=app_id,
  903. click_track_url=track_url)
  904. request = ai_strategy_request_parse(request_data)
  905. app_id_cnt += 1
  906. logger.info("account_id=%s, app_id=%s, 程序化上新素材-通用视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  907. else:
  908. batch_general_video = general_video_list[i: len(general_video_list)]
  909. app_version = app_version_list[app_id_cnt]
  910. app_id = app_dict[app_version].get('appId', 'error')
  911. track_url = app_dict[app_version].get('trackUrl', 'error')
  912. sql = """ select campaign_id, campaign_name from ctop_kuaishou_campaign where account_id = %s """ % account_id
  913. campaign_df = pd.read_sql(sql, engine)
  914. for row in campaign_df.itertuples():
  915. if (app_version + '--优选广告位-' + '程序化上新素材') == getattr(row, 'campaign_name'):
  916. campaign_id = getattr(row, 'campaign_id')
  917. break
  918. request_data = get_request_data(account_id=account_id,
  919. campaign_id=campaign_id,
  920. video_info=batch_general_video,
  921. campaign_name=app_version + '--优选广告位-' + '程序化上新素材',
  922. group_name=app_version + '-优选广告位-不限-程序化-' + '上新素材',
  923. ai_strategy_remark="程序化上新素材",
  924. unit_type=7,
  925. app_id=app_id,
  926. click_track_url=track_url)
  927. request = ai_strategy_request_parse(request_data)
  928. logger.info("account_id=%s, app_id=%s, 程序化上新素材-通用视频,ai策略的返回信息:%s" % (account_id, app_id, request))
  929. else:
  930. logger.info("account_id=%s, 程序化上新素材: 返回的视频中没有通用视频" % account_id)
  931. self.write(json.dumps({"message": "account_id=%s, 程序化上新素材请求已走完!" % account_id}))
  932. self.flush()
  933. else:
  934. video_info = get_history_video_info(account_id=account_id,
  935. url=get_history_video_url,
  936. start_time=(datetime.datetime.now() + datetime.timedelta(days=-7)).
  937. strftime("%Y-%m-%d %H:%M:%S"),
  938. end_time=datetime.date.today().strftime("%Y-%m-%d %H:%M:%S"),
  939. video_cnt=programme_new_video_cnt,
  940. related_creative_max_cnt=related_creative_max_cnt)
  941. if video_info['code'] != 0:
  942. self.write(json.dumps({"account_id": account_id,
  943. "message": "程序化上新素材,没有获取到视频,不发送ai策略请求!"}))
  944. self.flush()
  945. else:
  946. campaign_name, group_name = get_campaign_and_group_name_rule(account_id)
  947. if (campaign_name is None) or (group_name is None):
  948. logger.info("没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!")
  949. self.write(json.dumps({"message": "没有获取到广告计划命名规则 或 广告组命名规则,不发送ai策略请求!"}))
  950. self.flush()
  951. else:
  952. request_data = get_request_data(account_id=account_id,
  953. campaign_id=campaign_id,
  954. video_info=video_info['data'],
  955. campaign_name=campaign_name,
  956. group_name=group_name,
  957. ai_strategy_remark="程序化上新素材",
  958. name_replace="程序化上新素材",
  959. unit_type=7)
  960. request = ai_strategy_request_parse(request_data)
  961. logger.info("account_id = %s, 程序化上新素材,ai策略的返回信息:%s" % (account_id, request))
  962. self.write(json.dumps(request))
  963. self.flush()
  964. except Exception:
  965. logger.error(traceback.format_exc())
  966. self.write(json.dumps(traceback.format_exc()))
  967. self.flush()