|
@@ -0,0 +1,516 @@
|
|
|
+
|
|
|
+import json
|
|
|
+import random
|
|
|
+import requests
|
|
|
+import time
|
|
|
+from datetime import datetime
|
|
|
+import pymysql
|
|
|
+import logging
|
|
|
+from concurrent.futures import ThreadPoolExecutor
|
|
|
+from model.DataBaseUtils import MysqlUtils
|
|
|
+logging.getLogger().setLevel(logging.WARNING)
|
|
|
+from model.ComUtils import *
|
|
|
+from model.DateUtils import DateUtils
|
|
|
+du = DateUtils()
|
|
|
+db = MysqlUtils()
|
|
|
+max_workers = 10
|
|
|
+count = []
|
|
|
+t = du.get_n_days(-10)
|
|
|
+
|
|
|
+def get_adcreatives(account_id,access_token,flag): # 获取创意
|
|
|
+ url = 'https://api.e.qq.com/v1.1/adcreatives/get'
|
|
|
+ li =[]
|
|
|
+ page = 1
|
|
|
+
|
|
|
+ while True:
|
|
|
+ parameters = {
|
|
|
+ 'access_token': access_token,
|
|
|
+ 'timestamp': int(time.time()),
|
|
|
+ 'nonce': str(time.time()) + str(random.randint(0, 999999)),
|
|
|
+ 'fields': ('campaign_id', 'adcreative_id', 'adcreative_name', 'adcreative_elements', 'promoted_object_type', 'page_type',
|
|
|
+ 'page_spec', 'link_page_spec', 'universal_link_url', 'promoted_object_id','site_set'),
|
|
|
+ "filtering": [{
|
|
|
+ "field": "created_time",
|
|
|
+ "operator": "GREATER_EQUALS",
|
|
|
+ "values":
|
|
|
+ [
|
|
|
+ DateUtils.str_to_stamp(t)
|
|
|
+ ]}],
|
|
|
+ "account_id": account_id,
|
|
|
+ "page": page,
|
|
|
+ "page_size": 100,
|
|
|
+ "is_deleted": False
|
|
|
+ }
|
|
|
+
|
|
|
+ for k in parameters:
|
|
|
+ if type(parameters[k]) is not str:
|
|
|
+ parameters[k] = json.dumps(parameters[k])
|
|
|
+
|
|
|
+ while True:
|
|
|
+ h = requests.get(url, params=parameters)
|
|
|
+ if h.status_code == 200:
|
|
|
+ r = h.json()
|
|
|
+ # print(r)
|
|
|
+
|
|
|
+ break
|
|
|
+ else:
|
|
|
+ time.sleep(1)
|
|
|
+ print("爬取失败 等待1s")
|
|
|
+
|
|
|
+
|
|
|
+ if 'data' in r.keys():
|
|
|
+
|
|
|
+ for i in r['data']['list']:
|
|
|
+ # print(i)
|
|
|
+
|
|
|
+ if flag=='MP':
|
|
|
+ if len(i['adcreative_elements'])>0:
|
|
|
+ d = i['adcreative_elements']
|
|
|
+ title =d.get('title','')
|
|
|
+ if 'image' in d.keys():
|
|
|
+ image=d.get('image','')
|
|
|
+ elif 'image_list' in d.keys():
|
|
|
+ image =','.join(d.get('image_list'))
|
|
|
+ else:
|
|
|
+ image=''
|
|
|
+
|
|
|
+ else:
|
|
|
+ title = image=''
|
|
|
+
|
|
|
+
|
|
|
+ li.append((
|
|
|
+ i['adcreative_id'],i['adcreative_name'],i['campaign_id'],image,title,
|
|
|
+ i.get('promoted_object_type',''),i.get('page_type',''),
|
|
|
+ i['page_spec'].get('page_id',''),i.get('promoted_object_id',''),
|
|
|
+ '','','MP'
|
|
|
+ ))
|
|
|
+ else:
|
|
|
+ if len(i['adcreative_elements'])>0:
|
|
|
+ d =i['adcreative_elements']
|
|
|
+ if 'image' in d.keys():
|
|
|
+ image =d['image']
|
|
|
+ elif 'element_story' in d.keys():
|
|
|
+ image= ','.join([x['image'] for x in d['element_story']])
|
|
|
+ else:
|
|
|
+ image=''
|
|
|
+ title =d.get('title','')
|
|
|
+ description = d.get('description','')
|
|
|
+
|
|
|
+
|
|
|
+ else:
|
|
|
+ image=title=description=''
|
|
|
+
|
|
|
+
|
|
|
+ li.append(
|
|
|
+ (
|
|
|
+ i['adcreative_id'], i['adcreative_name'], i['campaign_id'],image,title,
|
|
|
+ i.get('promoted_object_type', ''), i.get('page_type', ''),
|
|
|
+ i['page_spec'].get('page_id', ''), i.get('promoted_object_id', ''),
|
|
|
+ ','.join(i['site_set']),description,'GDT'
|
|
|
+
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ total_page = r['data']['page_info']['total_page']
|
|
|
+ if total_page > page:
|
|
|
+ page += 1
|
|
|
+ else:
|
|
|
+ break
|
|
|
+ else:
|
|
|
+ break
|
|
|
+ if len(li)>0:
|
|
|
+ print(f"{account_id}有创意:",len(li))
|
|
|
+ sql='replace into adcreative_info values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) '
|
|
|
+ db.quchen_text.executeMany(sql,li)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def images_info_get(account_id,access_token): # 获取图片信息
|
|
|
+
|
|
|
+ fields = ('image_id','width','height','file_size','signature','preview_url')
|
|
|
+ interface = 'images/get'
|
|
|
+ url = 'https://api.e.qq.com/v1.3/' + interface
|
|
|
+
|
|
|
+ page = 1
|
|
|
+ li = []
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ while True:
|
|
|
+
|
|
|
+ common_parameters = {
|
|
|
+ 'access_token': access_token,
|
|
|
+ 'timestamp': int(time.time()),
|
|
|
+ 'nonce': str(time.time()) + str(random.randint(0, 999999)),
|
|
|
+ 'fields': fields
|
|
|
+ }
|
|
|
+
|
|
|
+ parameters = {
|
|
|
+ "account_id": account_id,
|
|
|
+ "filtering":[{
|
|
|
+ "field": "created_time",
|
|
|
+ "operator": "GREATER_EQUALS",
|
|
|
+ "values":
|
|
|
+ [
|
|
|
+ DateUtils.str_to_stamp(t)
|
|
|
+ ]}],
|
|
|
+ "page": page,
|
|
|
+ "page_size": 100
|
|
|
+ }
|
|
|
+
|
|
|
+ parameters.update(common_parameters)
|
|
|
+ for k in parameters:
|
|
|
+ if type(parameters[k]) is not str:
|
|
|
+ parameters[k] = json.dumps(parameters[k])
|
|
|
+
|
|
|
+ while True:
|
|
|
+ h = requests.get(url, params=parameters)
|
|
|
+ # print(h.text)
|
|
|
+ if h.status_code == 200:
|
|
|
+ r = h.json()
|
|
|
+ break
|
|
|
+ else:
|
|
|
+ time.sleep(1)
|
|
|
+ print("请求出错 等待1s..")
|
|
|
+
|
|
|
+ if 'data' in r.keys():
|
|
|
+ li.extend(r['data']['list'])
|
|
|
+
|
|
|
+
|
|
|
+ total_page = r['data']['page_info']['total_page']
|
|
|
+ if total_page > page:
|
|
|
+ page += 1
|
|
|
+ else:
|
|
|
+ break
|
|
|
+ # print(li)
|
|
|
+ data = []
|
|
|
+ for i in li:
|
|
|
+ data.append((i['image_id'],i['width'],i['height'],i['signature'],i['preview_url']))
|
|
|
+ # print(data)
|
|
|
+ print(f"{account_id} 有图片:", li.__len__())
|
|
|
+ if li.__len__() > 0:
|
|
|
+ sql="replace into image_info value (%s,%s,%s,%s,%s)"
|
|
|
+ db.quchen_text.executeMany(sql, data)
|
|
|
+ db.close()
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def ad_info():
|
|
|
+ accounts = db.quchen_text.getData("""
|
|
|
+ select account_id,access_token,name channel,'GDT' type from advertiser_qq where name !='' or name is not null
|
|
|
+ union
|
|
|
+ select account_id,access_token,name channel,'MP' type from advertiser_vx where name !='' or name is not null
|
|
|
+
|
|
|
+ """)
|
|
|
+ total_data =[]
|
|
|
+ executor = ThreadPoolExecutor(max_workers=max_workers)
|
|
|
+ for i in accounts:
|
|
|
+ # print(i)
|
|
|
+ account_id =i[0]
|
|
|
+ access_token = i[1]
|
|
|
+ type = i[3]
|
|
|
+ executor.submit(get_ad_info,account_id, access_token,type,total_data)
|
|
|
+ executor.shutdown()
|
|
|
+
|
|
|
+ print(len(total_data))
|
|
|
+ if len(total_data)>0:
|
|
|
+ sql="replace into ad_info values(%s,%s,%s,%s,%s,%s,%s) "
|
|
|
+ db.quchen_text.executeMany(sql, total_data)
|
|
|
+
|
|
|
+
|
|
|
+"""获取广告基础信息"""
|
|
|
+
|
|
|
+
|
|
|
+def get_ad_info(account_id, access_token, flag):
|
|
|
+
|
|
|
+ path = 'ads/get'
|
|
|
+ fields = ('ad_id', 'ad_name', 'adcreative_id', 'adgroup_id', 'campaign_id')
|
|
|
+ url = 'https://api.e.qq.com/v1.3/' + path
|
|
|
+ li = []
|
|
|
+ page = 1
|
|
|
+
|
|
|
+ while True:
|
|
|
+ parameters = {
|
|
|
+ 'access_token': access_token,
|
|
|
+ 'timestamp': int(time.time()),
|
|
|
+ 'nonce': str(time.time()) + str(random.randint(0, 999999)),
|
|
|
+ 'fields': fields,
|
|
|
+ "filtering": [{
|
|
|
+ "field": "created_time",
|
|
|
+ "operator": "GREATER_EQUALS",
|
|
|
+ "values":
|
|
|
+ [
|
|
|
+ DateUtils.str_to_stamp(t)
|
|
|
+ ]}],
|
|
|
+ "account_id": account_id,
|
|
|
+ "page": page,
|
|
|
+ "page_size": 100,
|
|
|
+ "is_deleted": False
|
|
|
+ }
|
|
|
+
|
|
|
+ for k in parameters:
|
|
|
+ if type(parameters[k]) is not str:
|
|
|
+ parameters[k] = json.dumps(parameters[k])
|
|
|
+ r = requests.get(url, params=parameters).json()
|
|
|
+
|
|
|
+ # print(r)
|
|
|
+ total_page = r['data']['page_info']['total_page']
|
|
|
+
|
|
|
+ if page > total_page:
|
|
|
+ break
|
|
|
+ else:
|
|
|
+ page += 1
|
|
|
+
|
|
|
+ if r.get("data"):
|
|
|
+ for i in r['data']['list']:
|
|
|
+ li.append((str(i['ad_id']), i['ad_name'], i['adcreative_id'], i['campaign_id'], i['adgroup_id'],
|
|
|
+ account_id, flag))
|
|
|
+
|
|
|
+
|
|
|
+ if li.__len__()>0:
|
|
|
+ print(f"{account_id}有广告:",li.__len__())
|
|
|
+ sql = "replace into ad_info values(%s,%s,%s,%s,%s,%s,%s) "
|
|
|
+ db.quchen_text.executeMany(sql, li)
|
|
|
+ db.close()
|
|
|
+
|
|
|
+
|
|
|
+def get_ad_cost_day(account_id,access_token,flag,st,et):
|
|
|
+
|
|
|
+ if flag == 'MP':
|
|
|
+ ad_cost_day_mp(account_id,access_token, st, et)
|
|
|
+ else:
|
|
|
+ ad_cost_day_gdt(account_id,access_token, st, et)
|
|
|
+
|
|
|
+
|
|
|
+def ad_cost_day_gdt(account_id,access_token,st,et):
|
|
|
+ url = 'https://api.e.qq.com/v1.3/daily_reports/get'
|
|
|
+ fields = ('date', 'ad_id', 'cost', 'view_count', 'ctr', 'follow_count')
|
|
|
+ li = []
|
|
|
+ page = 1
|
|
|
+ while True:
|
|
|
+ parameters = {
|
|
|
+ 'access_token': access_token,
|
|
|
+ 'timestamp': int(time.time()),
|
|
|
+ 'nonce': str(time.time()) + str(random.randint(0, 999999)),
|
|
|
+ 'fields': fields,
|
|
|
+ "account_id": account_id,
|
|
|
+ "group_by" : ['ad_id','date'],
|
|
|
+ "level": 'REPORT_LEVEL_AD',
|
|
|
+ "page": page,
|
|
|
+ "page_size": 1000,
|
|
|
+ "date_range": {
|
|
|
+ "start_date": st,
|
|
|
+ "end_date": et
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for k in parameters:
|
|
|
+ if type(parameters[k]) is not str:
|
|
|
+ parameters[k] = json.dumps(parameters[k])
|
|
|
+ r = requests.get(url, params=parameters).json()
|
|
|
+ # print(r)
|
|
|
+
|
|
|
+ if r.get("data"):
|
|
|
+ for i in r['data']['list']:
|
|
|
+ if i['cost']>0:
|
|
|
+ li.append(
|
|
|
+ (
|
|
|
+ i['date'], i['ad_id'], i['cost']/100, i['view_count'], i['ctr']*i['view_count'],
|
|
|
+ i['follow_count']
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ total_page = r['data']['page_info']['total_page']
|
|
|
+ if page >= total_page:
|
|
|
+ break
|
|
|
+ else:
|
|
|
+ page += 1
|
|
|
+ # print(li)
|
|
|
+ if len(li) > 0:
|
|
|
+ print(f"{account_id} have ad cost :{len(li)} ")
|
|
|
+ db.quchen_text.executeMany('replace into ad_cost_day values(%s,%s,%s,%s,%s,%s)', li)
|
|
|
+ db.close()
|
|
|
+
|
|
|
+
|
|
|
+def ad_cost_day_mp(account_id,access_token,st,et):
|
|
|
+ url = 'https://api.e.qq.com/v1.3/daily_reports/get'
|
|
|
+ fields = ('date', 'ad_id', 'cost', 'view_count', 'valid_click_count', 'official_account_follow_count')
|
|
|
+ li = []
|
|
|
+ page = 1
|
|
|
+ while True:
|
|
|
+ parameters = {
|
|
|
+ 'access_token': access_token,
|
|
|
+ 'timestamp': int(time.time()),
|
|
|
+ 'nonce': str(time.time()) + str(random.randint(0, 999999)),
|
|
|
+ 'fields': fields,
|
|
|
+ "account_id": account_id,
|
|
|
+ "level": 'REPORT_LEVEL_AD_WECHAT',
|
|
|
+ "page": page,
|
|
|
+ "page_size": 1000,
|
|
|
+ "date_range": {
|
|
|
+ "start_date": st,
|
|
|
+ "end_date": et
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for k in parameters:
|
|
|
+ if type(parameters[k]) is not str:
|
|
|
+ parameters[k] = json.dumps(parameters[k])
|
|
|
+
|
|
|
+ r = requests.get(url, params=parameters).json()
|
|
|
+
|
|
|
+
|
|
|
+ if r.get("data"):
|
|
|
+ for i in r['data']['list']:
|
|
|
+ if i['cost']>0:
|
|
|
+ li.append(
|
|
|
+ (
|
|
|
+ i['date'],i['ad_id'],i['cost']/100,i['view_count'],i['valid_click_count'],
|
|
|
+ i['official_account_follow_count']
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ total_page = r['data']['page_info']['total_page']
|
|
|
+ if page >=total_page:
|
|
|
+ break
|
|
|
+ else:
|
|
|
+ page += 1
|
|
|
+ # print(li)
|
|
|
+ if len(li) > 0:
|
|
|
+ print(f"{account_id} have ad cost :{len(li)} ")
|
|
|
+ db.quchen_text.executeMany('replace into ad_cost_day values(%s,%s,%s,%s,%s,%s)', li)
|
|
|
+ db.close()
|
|
|
+
|
|
|
+def daily_reports_get(access_token, account_id, level, start_date, end_date, fields): # 获取wx投放计划日报数据
|
|
|
+
|
|
|
+ interface = 'daily_reports/get'
|
|
|
+ url = 'https://api.e.qq.com/v1.3/' + interface
|
|
|
+
|
|
|
+ common_parameters = {
|
|
|
+ 'access_token': access_token,
|
|
|
+ 'timestamp': int(time.time()),
|
|
|
+ 'nonce': str(time.time()) + str(random.randint(0, 999999)),
|
|
|
+ 'fields': fields
|
|
|
+ }
|
|
|
+
|
|
|
+ parameters = {
|
|
|
+ "account_id": account_id,
|
|
|
+ "level": level,
|
|
|
+ "date_range":
|
|
|
+ {
|
|
|
+ "start_date": start_date,
|
|
|
+ "end_date": end_date
|
|
|
+ },
|
|
|
+
|
|
|
+ "page": 1,
|
|
|
+ "page_size": 1000,
|
|
|
+ "fields":
|
|
|
+ [
|
|
|
+
|
|
|
+ ]
|
|
|
+ }
|
|
|
+
|
|
|
+ parameters.update(common_parameters)
|
|
|
+ for k in parameters:
|
|
|
+ if type(parameters[k]) is not str:
|
|
|
+ parameters[k] = json.dumps(parameters[k])
|
|
|
+
|
|
|
+ while True:
|
|
|
+ r = requests.get(url, params=parameters)
|
|
|
+ if r.status_code == 200:
|
|
|
+ break
|
|
|
+ else:
|
|
|
+ time.sleep(1)
|
|
|
+ print("请求出错 等待1s..")
|
|
|
+
|
|
|
+ return r.json()
|
|
|
+
|
|
|
+
|
|
|
+def daily_qq_reports_get(access_token, account_id, compaign_id, level, start_date, end_date, fields): # 获取gdt投放计划日报数据
|
|
|
+
|
|
|
+ interface = 'daily_reports/get'
|
|
|
+ url = 'https://api.e.qq.com/v1.1/' + interface
|
|
|
+
|
|
|
+ common_parameters = {
|
|
|
+ 'access_token': access_token,
|
|
|
+ 'timestamp': int(time.time()),
|
|
|
+ 'nonce': str(time.time()) + str(random.randint(0, 999999)),
|
|
|
+ 'fields': fields
|
|
|
+ }
|
|
|
+
|
|
|
+ parameters = {
|
|
|
+ "account_id": account_id,
|
|
|
+ "filtering":
|
|
|
+ [
|
|
|
+
|
|
|
+ {
|
|
|
+ "field": "campaign_id",
|
|
|
+ "operator": "EQUALS",
|
|
|
+ "values":
|
|
|
+ [
|
|
|
+ compaign_id
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "level": level,
|
|
|
+ "date_range":
|
|
|
+ {
|
|
|
+ "start_date": start_date,
|
|
|
+ "end_date": end_date
|
|
|
+ },
|
|
|
+
|
|
|
+ "page": 1,
|
|
|
+ "page_size": 1000,
|
|
|
+ "fields":
|
|
|
+ [
|
|
|
+
|
|
|
+ ]
|
|
|
+ }
|
|
|
+
|
|
|
+ parameters.update(common_parameters)
|
|
|
+ for k in parameters:
|
|
|
+ if type(parameters[k]) is not str:
|
|
|
+ parameters[k] = json.dumps(parameters[k])
|
|
|
+
|
|
|
+ r = requests.get(url, params=parameters)
|
|
|
+
|
|
|
+ return r.json()
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def mysql_insert_adcreative(data):
|
|
|
+ db = pymysql.connect('rm-bp1c9cj79872tx3aaro.mysql.rds.aliyuncs.com', 'superc', 'Cc719199895', 'quchen_text')
|
|
|
+ cursor = db.cursor()
|
|
|
+
|
|
|
+ sql = 'replace into adcreative (campaign_id,adcreative_id,adcreative_name,image_id,title,promoted_object_type,page_type,page_id,link_page_id,promoted_object_id) values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)'
|
|
|
+ try:
|
|
|
+ cursor.executemany(sql, data)
|
|
|
+ db.commit()
|
|
|
+
|
|
|
+ print('insert [adcreative] ', len(data))
|
|
|
+ except:
|
|
|
+ db.rollback()
|
|
|
+ print('insert [adcreative] defeat')
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == '__main__':
|
|
|
+ account_id = 19016239
|
|
|
+ access_token = '65407243a6072b7dee3a013b58225e16'
|
|
|
+ #
|
|
|
+ account_id2 = 14709511
|
|
|
+ access_token2 = 'e87f7b6f860eaeef086ddcc9c3614678'
|
|
|
+ # get_ad_cost_day(account_id2,access_token2,'GDT','2021-03-01','2021-03-24')
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|