cost_util.py 21 KB

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