cost_util.py 21 KB

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