import requests from utils.UrlConfig import headers import json import pandas as pd import datetime from utils.DataBaseConfig import * import traceback from concurrent_log import ConcurrentTimedRotatingFileHandler import logging log_formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s', '%m/%d/%Y %I:%M:%S %p') log_handler = ConcurrentTimedRotatingFileHandler("logs/commonfunction.log", when="midnight", backupCount=100) log_handler.setFormatter(log_formatter) logger = logging.getLogger('common_function_logger') logger.addHandler(log_handler) logger.setLevel(logging.DEBUG) print('id of common_function_logger %s' % id(logger)) logger.info("common_function_logger started!") def get_lower_case_name(name): lst = [] for index, char in enumerate(name): if char.isupper() and index != 0: lst.append("_") lst.append(char) return "".join(lst).lower() def get_app_list(account_id,url): """ 获取应用详情 url:http://192.168.1.8:8080/jeecg-boot/ai/aiKuaiShouAppInfo/list 请求方式:post 入参:accountId 账户id appId 应用id 返回参数: { "code": 0, "data": [{ "id": 413, "accountId": 9864909, "appVersion": "ksjyrlyn-人类一脑涂地大败", "appName": "233乐园", "packageName": "com.meta.box", "platform": 1, "url": "https://www.233leyuan.com/apiserv/api/deliveryTest/ABTest?id=ksjyrlyn", "useSdk": 0, "appPrivacyUrl": "https://webcdn.233leyuan.com/app/useragreement/metax/privacyagreement.html", "trackUrl": "https://lnk0.com/kYZxds?chn=451&imei_md5=__IMEI2__&androidid_md5_1=__ANDROIDID2__&oaid=__OAID__&adcampaign=__DNAME__&adcreative=__CID__&adgroup=__AID__&did=__DID__&accountid=__ACCOUNTID__&platform=__OS__&clicktime=__TS__&ip=__IP__&useragent=__UA__&channelapp=__CSITE__&callback_url=__CALLBACK__&action=none", "appMd5": "0b2314c738956dc159ed38dc584ef214", "imageToken": "marketb3e98f5f68a74870b8d8d814499d6189.jpg", "status": 2, "remark": "创建应用成功", "appId": 3543665, "createTime": "2021-02-03 16:40:53", "updateTime": "2021-02-03 16:42:52"}], "message": "success" } """ request_data = {"accountId": account_id} try: request = requests.post(url=url, headers=headers, data=json.JSONEncoder().encode(request_data)).text request_json = json.loads(request) if request_json["code"] != 0: logger.info("account_id=%s, the res of list is %s" % (account_id, request_json['message'])) except: logger.error('account_id=%s, the res of list is %s, the traceback is %s ' % (account_id, request, traceback.format_exc())) return {"code": -1} return request_json def get_app_detail(account_id, url, app_id): """ 获取应用详情 url:http://192.168.1.8:8080/jeecg-boot/ai/aiKuaiShouAppInfo/getAppDetail 请求方式:post 入参:accountId 账户id appId 应用id 返回参数: { "code": 0, "data": { "id": 413, "accountId": 9864909, "appVersion": "ksjyrlyn-人类一脑涂地大败", "appName": "233乐园", "packageName": "com.meta.box", "platform": 1, "url": "https://www.233leyuan.com/apiserv/api/deliveryTest/ABTest?id=ksjyrlyn", "useSdk": 0, "appPrivacyUrl": "https://webcdn.233leyuan.com/app/useragreement/metax/privacyagreement.html", "trackUrl": "https://lnk0.com/kYZxds?chn=451&imei_md5=__IMEI2__&androidid_md5_1=__ANDROIDID2__&oaid=__OAID__&adcampaign=__DNAME__&adcreative=__CID__&adgroup=__AID__&did=__DID__&accountid=__ACCOUNTID__&platform=__OS__&clicktime=__TS__&ip=__IP__&useragent=__UA__&channelapp=__CSITE__&callback_url=__CALLBACK__&action=none", "appMd5": "0b2314c738956dc159ed38dc584ef214", "imageToken": "marketb3e98f5f68a74870b8d8d814499d6189.jpg", "status": 2, "remark": "创建应用成功", "appId": 3543665, "createTime": "2021-02-03 16:40:53", "updateTime": "2021-02-03 16:42:52"}, "message": "success" } """ request_data = {"accountId": account_id, "appId": app_id} try: request = requests.post(url=url, headers=headers, data=json.JSONEncoder().encode(request_data)).text request_json = json.loads(request) if request_json["code"] != 0: logger.info("account_id=%s, appId=%s, the res of getAppDetail is %s" % (account_id, app_id, request_json['message'])) except: logger.error('account_id=%s, appId=%s, the res of getAppDetail is %s, the traceback is %s ' % (account_id, app_id, request, traceback.format_exc())) return {"code": -1} return request_json def get_history_video_info(account_id, url, start_time, end_time, video_cnt, related_creative_max_cnt, app_version=None): """ url:http://192.168.1.8:8080/jeecg-boot/kuaishou/material/getHistoryVideoList 请求方式:POST remark: 见入参 入参:accountId 账户id startDate 开始时间 --(视频的upload_time) endDate 结束时间 --(视频的upload_time) createCount 关联创意数 (小于该值) num 获取数量 (随机num个) """ if not app_version: request_data = {"accountId": account_id, "startDate": start_time, "endDate": end_time, "num": video_cnt, "createCount": related_creative_max_cnt} else: request_data = {"accountId": account_id, "startDate": start_time, "endDate": end_time, "num": video_cnt, "createCount": related_creative_max_cnt, "appVersion": app_version} try: request = requests.post(url, headers=headers, data=json.JSONEncoder().encode(request_data)).text request_json = json.loads(request) if request_json["code"] != 0: logger.info("account_id=%s, app_version=%s, the res of getHistoryVideoList is %s" % (account_id, app_version, request_json['message'])) except Exception: logger.error('account_id=%s, app_version=%s, the res of getHistoryVideoList is %s, the traceback is %s ' % (account_id, app_version, request, traceback.format_exc())) return {"code": -1} return request_json def refresh_video(account_id, url): """ 需要调用刷新快手素材的接口 http://192.168.1.8:8080/jeecg-boot/kuaishou/material/getKuaiShouVideoList (请求方式 POST 入参:accountId 返回结果:成功或失败) remark: 自动上新之前,需要调用该接口,注意是账户层级的调用,不是app_id层级的调用 """ try: request = requests.post(url=url, headers=headers, data=json.JSONEncoder().encode({"accountId": account_id})).text request_json = json.loads(request) logger.info('account_id=%s, the res of getKuaiShouVideoList is %s' % (account_id, request_json)) except Exception: logger.error('account_id=%s, the res of getKuaiShouVideoList is %s, traceback is %s ' % (account_id, request, traceback.format_exc())) def get_new_video_info(account_id, url, app_version=None): """ url:http://192.168.1.8:8080/jeecg-boot/kuaishou/material/getNewVideoList 请求方式:POST remark: 1、返回 upload_time 在上次调用时间到本次调用时间内的素材(第一次调用返回5分钟前到本次调用时间的素材) 入参:accountId """ if not app_version: request_data = {"accountId": account_id} else: request_data = {"accountId": account_id, 'appVersion': app_version} try: request = requests.post(url, headers=headers, data=json.JSONEncoder().encode(request_data)).text request_json = json.loads(request) if request_json["code"] != 0: logger.info("account_id=%s, app_version=%s, the res of getNewVideoList is %s" % (account_id, app_version, request_json['message'])) except Exception: logger.error('account_id=%s, app_version=%s, the res of getNewVideoList is %s, the traceback is %s ' % (account_id, app_version, request, traceback.format_exc())) return {"code": -1} return request_json def get_missing_video_info(account_id, cnt, url, start_time, end_time, app_version=None): """ url:"http://192.168.1.8:8080/jeecg-boot/kuaishou/material/getCreateZeroVideoList" 请求方式:POST remark: 视频的upload_time 在startTime 和 endTime 之间,创意关联个数为0,order by upload_time asc limit videoCnt 入参: accountId: 账户id videoCnt: 查询数量 startTime: 开始时间 endTime: 结束时间 """ if not app_version: request_data = {"accountId": account_id, "videoCnt": cnt, "startTime": start_time, "endTime": end_time} else: request_data = {"accountId": account_id, "videoCnt": cnt, "startTime": start_time, "endTime": end_time, 'appVersion': app_version} try: request = requests.post(url, headers=headers, data=json.JSONEncoder().encode(request_data)).text request_json = json.loads(request) if request_json["code"] != 0: logger.info("account_id=%s, app_version=%s, the res of getCreateZeroVideoList is %s" % (account_id, app_version, request_json['message'])) except Exception: logger.error('account_id=%s, app_version=%s, the res of getCreateZeroVideoList is %s, the traceback is %s ' % (account_id, app_version, request, traceback.format_exc())) return {"code": -1} return request_json def get_top_video_info(account_id, cnt, start_time, end_time, url, app_version=None): """ url:http://192.168.1.8:8080/jeecg-boot/kuaishou/material/getHistoryTopVideoList 请求方式:POST remark: ctop_kuaishou_report_daily_material 整个项目维度 stat_date 在 startTime 和 endTime, order by sum(charge) desc limit num 入参: accountId: 账户id startTime: 开始时间 endTime: 结束时间 num: 查询数量 remark: 返回结果中 "photo_name" == "all",表示为通用视频,反之为app_id对应的特定视频("photo_name": "ksjytdrca-糖豆人冲啊") 返回: { "code": 0, "data": [ { "material_type": 1, "charge": 154229.670, "video_url": "http://alimov2.a.yximgs.com/upic/2021/02/03/18/BMjAyMTAyMDMxODU3MjlfMjI0NTY2OTI5MF80MzUxMjc4MTgzNV8wXzM=_b_B142e1ddc44705f978fe2a7fa4f4e9eb1.mp4?tag=1-1613958443-unknown-0-nbzw9am7cu-465420c6c3fe0f27&clientCacheKey=3xeh2gxd84qg462_b.mp4&tt=b&di=8bba1b60&bp=13890", "photo_id": "5249789835088957477", "photo_name": "ksjytdrca-糖豆人冲啊", "signature": "e160cc10d73031a48895a32834b54c46", "channel_type": 0, "imageList": [ "3267a05ef40ca8180b87428bcc324628", "1e5cb59e588a6dd489a9c0c36b7e52cd", "c0a199395614c5204a2f9a5aa9457fdf", "659c1865be2e9b561475d204ebf363b4", "7b85a1262a59e22ff2e82a3374d8beb0", "2e5542b2b39191219c33e278ccae0bdf", "45d2d11e052aca20c2a5e546e2ffda30", "8902152d887dfc119a2ba32d970683d9", "7becab0d75b2cbec66ea18fbabd33b59", "e1ba0f57d3abe2822ab3fc02d9ea7ba3", "9676c587837df85df4aba76a5ce3b8c1", "1b42543b0b31613740dfaa8fd861136c", "8a1c95ecf4af672d2f7a1acef36bce15", "5e6d8d8f0339ab7d2b3e1de533111606", "8b5b6c6d63e62e04a92d84fe175c05fd" ] }, { "material_type": 1, "charge": 92135.125, "video_url": "http://txmov2.a.yximgs.com/upic/2021/02/03/18/BMjAyMTAyMDMxODU3MzhfMjI0NTY2OTI5MF80MzUxMjc5MzU0MV8wXzM=_b_Bd0dab20fe03c02e76080340c66341573.mp4?tag=1-1613958443-unknown-0-9romi5xmpo-d5161ea63e200cde&clientCacheKey=3xu33qupdka3h5y_b.mp4&tt=b&di=8bba1b60&bp=13890", "photo_id": "5192368941898812785", "photo_name": "all", "signature": "fc4004dc82f44f765aa7a0150e3aad8a", "channel_type": 0, "imageList": [ "8cc3de1612ced3a6dbdf8e9e054c6ec1", "7a2e7c070c25e6d06460e9fe62f139c7", "43dcb78211d4d6d8bdb5a398a57d9d1d", "14118f0ecd4a86e35165e6130ba69c6b", "eec697ea33e3ddaaf0e77e65749a6f23", "da6e9648da85204c717e8beb87b19328", "0839fffc60203f1ba13bc89c26d437c4", "feabdeaab2e264e521be06c5fc4c0457" ] }, { "material_type": 1, "charge": 70956.941, "video_url": "http://txmov2.a.yximgs.com/upic/2021/02/03/18/BMjAyMTAyMDMxODIwMzdfMjI0NTY2OTI5MF80MzUxMDIxMDg2OF8wXzM=_b_Bfea5219f9c40bdf34f8420429c59434c.mp4?tag=1-1613958443-unknown-0-rk05fpbcb3-7dbb4cb30a941643&clientCacheKey=3x3xi88nniq6m6i_b.mp4&tt=b&di=8bba1b60&bp=13890", "photo_id": "5219390536383350388", "photo_name": "all", "signature": "0ec9b0bac40463d18f151be605682dc8", "channel_type": 0, "imageList": [ "9b71f206b6ca9d2f89712b79ebd0d699", "c802325b325cf67c5c7c13872572642d", "e79ca1b5dde8709e794b53582e40dbdd", "37b529460cbebcba259a412dce40bd9c", "b7b37d27e33d21923c7ade475e7d0ffb", "b4ebac5da9e624aae208f2d8d9ab6b0e", "0675ef5a12e9ed01954e40309ff226c1", "04ed3651b233aad5a1f7e76b1ead48e4", "6a954e0ecfce38ad854c715c4e0d3a26", "516a957c2c80a4a74a24d1073412647f", "95f1a42d06657c4b8b8554b81583db5f", "30ba9f8a90539f3afe43f3046c54f488", "e48236f0509398412efac2f9ee258c6d", "a9f21f3731b653784fcf2dca6d4ca427", "014383e5b7c33cb9e0a515bf11e9a786" ] } ], "message": "SUCCESS" } """ if not app_version: request_data = {"accountId": account_id, "num": cnt, "startTime": start_time, "endTime": end_time} else: request_data = {"accountId": account_id, "num": cnt, "startTime": start_time, "endTime": end_time, 'appVersion': app_version} try: request = requests.post(url, headers=headers, data=json.JSONEncoder().encode(request_data)).text request_json = json.loads(request) if request_json["code"] != 0: logger.info("account_id=%s, app_version=%s, the res of getHistoryTopVideoList is %s" % (account_id, app_version, request_json['message'])) except Exception: logger.error('account_id=%s, app_version=%s, the res of getHistoryTopVideoList is %s, the traceback is %s ' % (account_id, app_version, request, traceback.format_exc())) return {"code": -1} return request_json def get_campaign_and_group_name_rule(account_id): sql = """select campaign_name, group_name from ctop_ai_kuaishou_advertiser_strategy where account_id = %s order by create_time desc limit 1 """ % account_id df = pd.read_sql(sql, engine) if df.empty: return None, None campaign_name = df['campaign_name'].values[0] group_name = df['group_name'].values[0] return campaign_name, group_name def get_request_data(account_id, campaign_id, video_info, campaign_name, group_name, ai_strategy_remark, name_replace='', unit_type=4, click_track_url=None, app_id=None): res = { "video": video_info, "operation_type": 1, "account_id": account_id, "ai_strategy_remark": ai_strategy_remark, "campaign_info": {"campaign_id": campaign_id, "campaign_name": (campaign_name.replace('自定义', name_replace) + str(datetime.datetime.now())) if name_replace else campaign_name}, 'group_info': {'group_name': (group_name.replace('自定义', name_replace) + str(datetime.datetime.now())) if name_replace else (group_name + str(datetime.datetime.now())), 'begin_time': str(datetime.date.today()), 'unit_type': unit_type, 'app_id': app_id}, 'creative_info': {'is_sticky': 0, 'click_track_url': click_track_url} } return res