cost_util.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. import json
  2. import random
  3. import requests
  4. import time
  5. from datetime import datetime
  6. import pymysql
  7. import logging
  8. from concurrent.futures import ThreadPoolExecutor
  9. from model.DataBaseUtils import MysqlUtils
  10. from model.ComUtils import *
  11. from model.DateUtils import DateUtils
  12. du = DateUtils()
  13. db = MysqlUtils()
  14. max_workers = 10
  15. count = []
  16. t = du.get_n_days(-10)
  17. def get_campaign(account_id, access_token, flag,campaign_ids,dt):
  18. path = 'campaigns/get'
  19. fields = ('campaign_id', 'campaign_name', 'configured_status', 'campaign_type', 'promoted_object_type',
  20. 'daily_budget','budget_reach_date','created_time','last_modified_time','speed_mode','is_deleted')
  21. url = 'https://api.e.qq.com/v1.3/' + path
  22. li = []
  23. page = 1
  24. while True:
  25. parameters = {
  26. 'access_token': access_token,
  27. 'timestamp': int(time.time()),
  28. 'nonce': str(time.time()) + str(random.randint(0, 999999)),
  29. 'fields': fields,
  30. "filtering": [{
  31. "field": "campaign_id",
  32. "operator": "IN",
  33. "values":
  34. campaign_ids.split(',')
  35. }],
  36. "account_id": account_id,
  37. "page": page,
  38. "page_size": 100,
  39. "is_deleted": False
  40. }
  41. for k in parameters:
  42. if type(parameters[k]) is not str:
  43. parameters[k] = json.dumps(parameters[k])
  44. while True:
  45. r = requests.get(url, params=parameters).json()
  46. code = r['code']
  47. if code == 11017:
  48. time.sleep(61)
  49. else:
  50. break
  51. # logging.info(r)
  52. total_page = r['data']['page_info']['total_page']
  53. if page > total_page:
  54. break
  55. else:
  56. page += 1
  57. if r.get("data"):
  58. for i in r['data']['list']:
  59. li.append((str(i['campaign_id']), i['campaign_name'], i['configured_status'], i['campaign_type'],
  60. i['promoted_object_type'],i['daily_budget'],i.get('budget_reach_date'),
  61. DateUtils.stamp_to_str(i['created_time']),
  62. DateUtils.stamp_to_str(i['last_modified_time']),i.get('speed_mode'),i.get('is_deleted'),
  63. account_id, flag, dt))
  64. # logging.info(li)
  65. """mp 没有 speed_mode,is_deleted,budget_reach_date"""
  66. if li.__len__() > 0:
  67. logging.info(f"{account_id}有计划:"+ str(li.__len__()))
  68. sql = "replace into campaign_info values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
  69. db.quchen_text.executeMany(sql, li)
  70. db.close()
  71. def get_adcreatives(account_id,access_token,flag,adc_ids,dt): # 获取创意
  72. #接口https://developers.e.qq.com/docs/api/adsmanagement/adcreatives/adcreatives_get?version=1.3
  73. url = 'https://api.e.qq.com/v1.1/adcreatives/get'
  74. li =[]
  75. page = 1
  76. while True:
  77. parameters = {
  78. 'access_token': access_token,
  79. 'timestamp': int(time.time()),
  80. 'nonce': str(time.time()) + str(random.randint(0, 999999)),
  81. 'fields': ('campaign_id', 'adcreative_id', 'adcreative_name', 'adcreative_elements', 'promoted_object_type', 'page_type',
  82. 'page_spec', 'link_page_spec', 'universal_link_url', 'promoted_object_id','site_set'),
  83. "filtering": [{
  84. "field": "adcreative_id",
  85. "operator": "IN",
  86. "values": adc_ids.split(',')
  87. }],
  88. "account_id": account_id,
  89. "page": page,
  90. "page_size": 100,
  91. "is_deleted": False
  92. }
  93. for k in parameters:
  94. if type(parameters[k]) is not str:
  95. parameters[k] = json.dumps(parameters[k])
  96. while True:
  97. h = requests.get(url, params=parameters)
  98. # logging.info(h.json())
  99. if h.status_code == 200:
  100. r = h.json()
  101. # logging.info(r)
  102. break
  103. else:
  104. time.sleep(1)
  105. logging.info("爬取失败 等待1s")
  106. if 'data' in r.keys():
  107. is_video=0
  108. for i in r['data']['list']:
  109. # logging.info(i)
  110. if flag=='MP':
  111. if len(i['adcreative_elements'])>0:
  112. d = i['adcreative_elements']
  113. title =d.get('title','')
  114. description = d.get('description', '')
  115. if 'image' in d.keys():
  116. image=d.get('image','')
  117. elif 'image_list' in d.keys():
  118. image =','.join(d.get('image_list'))
  119. elif 'video' in d.keys():
  120. image = d['video']
  121. is_video=1
  122. else:
  123. image = ''
  124. else:
  125. title = image=''
  126. li.append((
  127. i['adcreative_id'],i['adcreative_name'],i['campaign_id'],image,title,
  128. i.get('promoted_object_type',''),i.get('page_type',''),
  129. i['page_spec'].get('page_id',''),i.get('promoted_object_id',''),
  130. '',description,'MP',account_id,dt,is_video
  131. ))
  132. else:
  133. if len(i['adcreative_elements'])>0:
  134. d =i['adcreative_elements']
  135. if 'image' in d.keys():
  136. image =d['image']
  137. elif 'element_story' in d.keys():
  138. image= ','.join([x['image'] for x in d['element_story']])
  139. else:
  140. image=''
  141. title =d.get('title','')
  142. description = d.get('description','')
  143. else:
  144. image=title=description=''
  145. li.append(
  146. (
  147. i['adcreative_id'], i['adcreative_name'], i['campaign_id'],image,title,
  148. i.get('promoted_object_type', ''), i.get('page_type', ''),
  149. i['page_spec'].get('page_id', ''), i.get('promoted_object_id', ''),
  150. ','.join(i['site_set']),description,'GDT',account_id,dt,is_video
  151. )
  152. )
  153. total_page = r['data']['page_info']['total_page']
  154. if total_page > page:
  155. page += 1
  156. else:
  157. break
  158. else:
  159. break
  160. if len(li)>0:
  161. logging.info(f"{account_id}有创意:"+str(len(li)))
  162. sql='replace into adcreative_info values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) '
  163. db.quchen_text.executeMany(sql,li)
  164. def images_info_get(account_id,access_token,image_ids): # 获取图片信息
  165. #接口https://developers.e.qq.com/docs/api/business_assets/image/images_get?version=1.3
  166. fields = ('image_id','width','height','file_size','signature','preview_url')
  167. interface = 'images/get'
  168. url = 'https://api.e.qq.com/v1.3/' + interface
  169. page = 1
  170. li = []
  171. while True:
  172. common_parameters = {
  173. 'access_token': access_token,
  174. 'timestamp': int(time.time()),
  175. 'nonce': str(time.time()) + str(random.randint(0, 999999)),
  176. 'fields': fields
  177. }
  178. parameters = {
  179. "account_id": account_id,
  180. "filtering":[{
  181. "field": "image_id",
  182. "operator": "IN",
  183. "values": image_ids.split(',')
  184. }],
  185. "page": page,
  186. "page_size": 100
  187. }
  188. parameters.update(common_parameters)
  189. for k in parameters:
  190. if type(parameters[k]) is not str:
  191. parameters[k] = json.dumps(parameters[k])
  192. while True:
  193. h = requests.get(url, params=parameters)
  194. # logging.info(h.text)
  195. if h.status_code == 200:
  196. r = h.json()
  197. break
  198. else:
  199. time.sleep(1)
  200. logging.info("请求出错 等待1s..")
  201. if 'data' in r.keys():
  202. li.extend(r['data']['list'])
  203. total_page = r['data']['page_info']['total_page']
  204. if total_page > page:
  205. page += 1
  206. else:
  207. break
  208. # logging.info(li)
  209. data = []
  210. for i in li:
  211. data.append((i['image_id'],i['width'],i['height'],i['signature'],i['preview_url']))
  212. # logging.info(data)
  213. logging.info(f"{account_id} 有图片:"+str(li.__len__()))
  214. if li.__len__() > 0:
  215. sql="replace into image_info value (%s,%s,%s,%s,%s)"
  216. db.quchen_text.executeMany(sql, data)
  217. db.close()
  218. def video_info_get(account_id,access_token,image_ids): # 获取视频信息
  219. #接口https://developers.e.qq.com/docs/api/business_assets/video/videos_get?version=1.3
  220. fields = ('video_id','width','height','file_size','signature','preview_url')
  221. interface = 'videos/get'
  222. url = 'https://api.e.qq.com/v1.3/' + interface
  223. page = 1
  224. li = []
  225. while True:
  226. common_parameters = {
  227. 'access_token': access_token,
  228. 'timestamp': int(time.time()),
  229. 'nonce': str(time.time()) + str(random.randint(0, 999999)),
  230. 'fields': fields
  231. }
  232. parameters = {
  233. "account_id": account_id,
  234. "filtering":[{
  235. "field": "media_id",
  236. "operator": "IN",
  237. "values": image_ids.split(',')
  238. }],
  239. "page": page,
  240. "page_size": 100
  241. }
  242. parameters.update(common_parameters)
  243. for k in parameters:
  244. if type(parameters[k]) is not str:
  245. parameters[k] = json.dumps(parameters[k])
  246. while True:
  247. h = requests.get(url, params=parameters)
  248. # logging.info(h.text)
  249. if h.status_code == 200:
  250. r = h.json()
  251. break
  252. else:
  253. time.sleep(1)
  254. logging.info("请求出错 等待1s..")
  255. if 'data' in r.keys():
  256. li.extend(r['data']['list'])
  257. total_page = r['data']['page_info']['total_page']
  258. if total_page > page:
  259. page += 1
  260. else:
  261. break
  262. # logging.info(li)
  263. data = []
  264. for i in li:
  265. data.append((i['video_id'],i['width'],i['height'],i['signature'],i['preview_url']))
  266. # logging.info(data)
  267. logging.info(f"{account_id} 有视频:"+ str(li.__len__()))
  268. if li.__len__() > 0:
  269. sql="replace into video_info value (%s,%s,%s,%s,%s)"
  270. db.quchen_text.executeMany(sql, data)
  271. db.close()
  272. def ad_info():
  273. accounts = db.quchen_text.getData("""
  274. select account_id,access_token,name channel,'GDT' type from advertiser_qq where name !='' or name is not null
  275. union
  276. select account_id,access_token,name channel,'MP' type from advertiser_vx where name !='' or name is not null
  277. """)
  278. total_data =[]
  279. executor = ThreadPoolExecutor(max_workers=max_workers)
  280. for i in accounts:
  281. # logging.info(i)
  282. account_id =i[0]
  283. access_token = i[1]
  284. type = i[3]
  285. executor.submit(get_ad_info,account_id, access_token,type,total_data)
  286. executor.shutdown()
  287. logging.info(len(total_data))
  288. if len(total_data)>0:
  289. sql="replace into ad_info values(%s,%s,%s,%s,%s,%s,%s) "
  290. db.quchen_text.executeMany(sql, total_data)
  291. """获取广告基础信息"""
  292. def get_ad_info(account_id, access_token, flag,ad_ids,dt):
  293. #接口为https://developers.e.qq.com/docs/apilist/ads/ad?version=1.3#a3
  294. path = 'ads/get'
  295. fields = ('ad_id', 'ad_name', 'adcreative_id', 'adgroup_id', 'campaign_id')
  296. url = 'https://api.e.qq.com/v1.3/' + path
  297. li = []
  298. page = 1
  299. while True:
  300. parameters = {
  301. 'access_token': access_token,
  302. 'timestamp': int(time.time()),
  303. 'nonce': str(time.time()) + str(random.randint(0, 999999)),
  304. 'fields': fields,
  305. "filtering": [{
  306. "field": "ad_id",
  307. "operator": "IN",
  308. "values":
  309. ad_ids.split(',')
  310. }],
  311. "account_id": account_id,
  312. "page": page,
  313. "page_size": 100,
  314. "is_deleted": False
  315. }
  316. for k in parameters:
  317. if type(parameters[k]) is not str:
  318. parameters[k] = json.dumps(parameters[k])
  319. while True:
  320. r = requests.get(url, params=parameters).json()
  321. code = r['code']
  322. if code == 11017:
  323. time.sleep(61)
  324. else:
  325. break
  326. # logging.info(r)
  327. total_page = r['data']['page_info']['total_page']
  328. if page > total_page:
  329. break
  330. else:
  331. page += 1
  332. if r.get("data"):
  333. for i in r['data']['list']:
  334. li.append((str(i['ad_id']), i['ad_name'], i['adcreative_id'], i['campaign_id'], i['adgroup_id'],
  335. account_id, flag, dt))
  336. if li.__len__()>0:
  337. logging.info(f"{account_id}有广告:"+str(li.__len__()))
  338. sql = "replace into ad_info values(%s,%s,%s,%s,%s,%s,%s,%s) "
  339. db.quchen_text.executeMany(sql, li)
  340. db.close()
  341. def get_ad_cost_day(account_id,access_token,flag,st,et):
  342. if flag == 'MP':
  343. ad_cost_day_mp(account_id,access_token, st, et)
  344. else:
  345. ad_cost_day_gdt(account_id,access_token, st, et)
  346. def ad_cost_day_gdt(account_id,access_token,st,et):
  347. #接口文档https://developers.e.qq.com/docs/api/insights/ad_insights/daily_reports_get?version=1.3
  348. url = 'https://api.e.qq.com/v1.3/daily_reports/get'
  349. fields = ('date', 'ad_id','adgroup_id', 'cost', 'view_count', 'ctr', 'follow_count','web_order_count','order_amount')
  350. li = []
  351. page = 1
  352. while True:
  353. parameters = {
  354. 'access_token': access_token,
  355. 'timestamp': int(time.time()),
  356. 'nonce': str(time.time()) + str(random.randint(0, 999999)),
  357. 'fields': fields,
  358. "account_id": account_id,
  359. "group_by" : ['ad_id','date'],
  360. "level": 'REPORT_LEVEL_AD',
  361. "page": page,
  362. "page_size": 1000,
  363. "date_range": {
  364. "start_date": st,
  365. "end_date": et
  366. }
  367. }
  368. for k in parameters:
  369. if type(parameters[k]) is not str:
  370. parameters[k] = json.dumps(parameters[k])
  371. while True:
  372. r = requests.get(url, params=parameters).json()
  373. # logging.info(r)
  374. code =r['code']
  375. if code==11017:
  376. time.sleep(61)
  377. else:
  378. break
  379. if r.get("data"):
  380. for i in r['data']['list']:
  381. if i['cost']>0:
  382. li.append(
  383. (
  384. i['date'], i['ad_id'],i['adgroup_id'], i['cost']/100, i['view_count'], i['ctr']*i['view_count'],
  385. i['follow_count'],i['web_order_count'],i['order_amount']/100,account_id,'GDT'
  386. )
  387. )
  388. total_page = r['data']['page_info']['total_page']
  389. if page >= total_page:
  390. break
  391. else:
  392. page += 1
  393. # logging.info(li)
  394. if len(li) > 0:
  395. logging.info(f"{account_id} have ad cost :{len(li)} ")
  396. db.quchen_text.executeMany('replace into ad_cost_day values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)', li)
  397. db.close()
  398. def ad_cost_day_mp(account_id,access_token,st,et):
  399. url = 'https://api.e.qq.com/v1.3/daily_reports/get'
  400. fields = ('date', 'ad_id','adgroup_id', 'cost', 'view_count', 'valid_click_count', 'official_account_follow_count','order_count','order_amount')
  401. li = []
  402. page = 1
  403. while True:
  404. parameters = {
  405. 'access_token': access_token,
  406. 'timestamp': int(time.time()),
  407. 'nonce': str(time.time()) + str(random.randint(0, 999999)),
  408. 'fields': fields,
  409. "account_id": account_id,
  410. "level": 'REPORT_LEVEL_AD_WECHAT',
  411. "page": page,
  412. "page_size": 1000,
  413. "date_range": {
  414. "start_date": st,
  415. "end_date": et
  416. }
  417. }
  418. for k in parameters:
  419. if type(parameters[k]) is not str:
  420. parameters[k] = json.dumps(parameters[k])
  421. while True:
  422. r = requests.get(url, params=parameters).json()
  423. # logging.info(r['data']['list'])
  424. # import pandas as pd
  425. # logging.info(pd.DataFrame(r['data']['list']))
  426. code = r['code']
  427. if code == 11017:
  428. time.sleep(61)
  429. else:
  430. break
  431. if r.get("data"):
  432. for i in r['data']['list']:
  433. if i['cost']>0:
  434. li.append(
  435. (
  436. i['date'],i['ad_id'],i['adgroup_id'],i['cost']/100,i['view_count'],i['valid_click_count'],
  437. i['official_account_follow_count'],i['order_count'],i['order_amount']/100,account_id,'MP'
  438. )
  439. )
  440. total_page = r['data']['page_info']['total_page']
  441. if page >=total_page:
  442. break
  443. else:
  444. page += 1
  445. # logging.info(li)
  446. # exit()
  447. if len(li) > 0:
  448. logging.info(f"{account_id} have ad cost :{len(li)} ")
  449. db.quchen_text.executeMany('replace into ad_cost_day values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)', li)
  450. db.close()
  451. def daily_reports_get(access_token, account_id, level, start_date, end_date, fields): # 获取wx投放计划日报数据
  452. interface = 'daily_reports/get'
  453. url = 'https://api.e.qq.com/v1.3/' + interface
  454. common_parameters = {
  455. 'access_token': access_token,
  456. 'timestamp': int(time.time()),
  457. 'nonce': str(time.time()) + str(random.randint(0, 999999)),
  458. 'fields': fields
  459. }
  460. parameters = {
  461. "account_id": account_id,
  462. "level": level,
  463. "date_range":
  464. {
  465. "start_date": start_date,
  466. "end_date": end_date
  467. },
  468. "page": 1,
  469. "page_size": 1000,
  470. "fields":
  471. [
  472. ]
  473. }
  474. parameters.update(common_parameters)
  475. for k in parameters:
  476. if type(parameters[k]) is not str:
  477. parameters[k] = json.dumps(parameters[k])
  478. while True:
  479. r = requests.get(url, params=parameters)
  480. if r.status_code == 200:
  481. break
  482. else:
  483. time.sleep(1)
  484. logging.info("请求出错 等待1s..")
  485. return r.json()
  486. def daily_qq_reports_get(access_token, account_id, compaign_id, level, start_date, end_date, fields): # 获取gdt投放计划日报数据
  487. interface = 'daily_reports/get'
  488. url = 'https://api.e.qq.com/v1.1/' + interface
  489. common_parameters = {
  490. 'access_token': access_token,
  491. 'timestamp': int(time.time()),
  492. 'nonce': str(time.time()) + str(random.randint(0, 999999)),
  493. 'fields': fields
  494. }
  495. parameters = {
  496. "account_id": account_id,
  497. "filtering":
  498. [
  499. {
  500. "field": "campaign_id",
  501. "operator": "EQUALS",
  502. "values":
  503. [
  504. compaign_id
  505. ]
  506. }
  507. ],
  508. "level": level,
  509. "date_range":
  510. {
  511. "start_date": start_date,
  512. "end_date": end_date
  513. },
  514. "page": 1,
  515. "page_size": 1000,
  516. "fields":
  517. [
  518. ]
  519. }
  520. parameters.update(common_parameters)
  521. for k in parameters:
  522. if type(parameters[k]) is not str:
  523. parameters[k] = json.dumps(parameters[k])
  524. r = requests.get(url, params=parameters)
  525. return r.json()
  526. def mysql_insert_adcreative(data):
  527. db = pymysql.connect('rm-bp1c9cj79872tx3aaro.mysql.rds.aliyuncs.com', 'superc', 'Cc719199895', 'quchen_text')
  528. cursor = db.cursor()
  529. 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)'
  530. try:
  531. cursor.executemany(sql, data)
  532. db.commit()
  533. logging.info('insert [adcreative] '+ str(len(data)))
  534. except:
  535. db.rollback()
  536. logging.info('insert [adcreative] defeat')
  537. if __name__ == '__main__':
  538. account_id = 19206910
  539. access_token = '89079ccc8db047b078a0108e36a7e276'
  540. #
  541. account_id2 = 14709511
  542. access_token2 = 'e87f7b6f860eaeef086ddcc9c3614678'
  543. get_ad_cost_day(account_id,access_token,'MP','2021-04-09','2021-04-09')
  544. # get_adcreatives(account_id,access_token,'MP','3187867673','2021-04-09')