from selenium.webdriver import ActionChains from selenium.webdriver.support.wait import WebDriverWait from wechat_action.create_ad_plan_idea import IdeaAction from wechat_action.human_ad import HumanAd from selenium.webdriver.common.keys import Keys import re import time import logging import random import requests class CreateAdPlan(): # TODO:因为人群包现在可能存在唯一性,公众号间的复制,需要怎么处理 def __init__(self, task, login_ad, service_name, wechat_name): self.task = task # self.task_check() self.service_name = service_name self.wechat_name = wechat_name self.login_ad = login_ad self.driver = login_ad.get_driver_loged() self.ad_idea_action = IdeaAction(self.driver, task) self.ad_human_action = HumanAd(self.driver) def set_ad_title(self): logging.info('开始设置广告标题') title_ = self.driver.find_element_by_xpath('//*[@class="input-2lFnByGCRh"]') for i in range(40): title_.send_keys(Keys.BACKSPACE) title_.click() time.sleep(0.1) title_.send_keys(self.task['title']) title_.send_keys(Keys.RETURN) time.sleep(random.uniform(0.1, 0.2)) def set_ad_cpm(self): # TODO:设置完之后,test函数中进行对应修改 logging.info('开始设置cpm') if self.task['cpm']['cpm_set'] == '2': self.driver.save_screenshot('cpm{}.png'.format(time.time())) self.driver.find_element_by_xpath( '//*[@id="wxadcontainer"]/div[1]/div/div[2]/main/div/div[2]/div[1]/div/div[2]/div/div[1]/section[2]/form/div/div[1]/div[1]/button[2]/span').click() time.sleep(0.1) select_elements = self.driver.find_elements_by_xpath('//*[@class="adui-radio-base adui-radio-small"]') for _ in select_elements: if '优先跑量' in _.text and self.task['cpm']['module'] == '2': _.click() time.sleep(0.1) if '下单' in _.text: _.click() time.sleep(0.1) def set_ad_locations(self): logging.info('设置对应广告位') gg_button = self.driver.find_element_by_class_name( 'adui-button-hasLeftIcon') WebDriverWait(self.driver, 100).until( lambda driver: gg_button.is_displayed() and gg_button.is_enabled()) gg_button.click() # 设置广告形式 self.driver.switch_to.window(self.driver.window_handles[-1]) self.driver.execute_script(''' window.scroll(100000,0); ''') WebDriverWait(self.driver, 10).until( lambda driver: self.driver.find_element_by_css_selector('#PRODUCTTYPE_WECHAT')) # 设置公众号名字 for i in range(30): self.driver.find_element_by_xpath('//*[@id="test_plan_name"]/input').send_keys(Keys.BACKSPACE) self.driver.find_element_by_xpath('//*[@id="test_plan_name"]/input').send_keys( self.task['title']) # 推广公众号 wechat_gg = self.driver.find_element_by_css_selector('#PRODUCTTYPE_WECHAT') wechat_gg.click() localtion = self.task['plan_base'][1] if localtion == 'gzh_botoom': # 默认是这个选项,所以不用进行点选 pass if localtion == 'gzh_movie': wechat_localtion = self.driver.find_element_by_id('pos_8') wechat_localtion.click() if localtion == 'pyq': wechat_localtion = self.driver.find_element_by_css_selector( '#wxadcontainer > div:nth-child(1) > div > div.content-2-HFBij0Uh > main > div > div:nth-child(3) > div.adui-grid-row > div:nth-child(1)') wechat_localtion.click() if localtion == 'gzh_big_pic': self.driver.find_element_by_xpath( '//*[@id="wxadcontainer"]/div[1]/div/div[2]/main/div/div[3]/div[3]/div[1]/div/button').click() time.sleep(0.5) self.driver.find_element_by_xpath( '//*[@id="wxadcontainer"]/div[1]/div/div[2]/main/div/div[3]/div[3]/div[3]/ol/li[2]').click() time.sleep(random.uniform(0.1, 0.3)) # 花销设置 # cost_input = self.driver.find_element_by_css_selector( # '#wxadcontainer > div:nth-child(1) > div > div.content-2-HFBij0Uh > main > div > div:nth-child(5) > div:nth-child(2) > div:nth-child(1) > div > input') # cost_input.send_keys('100') # 进入下一页 next_button = self.driver.find_element_by_css_selector('#plan_next_step') next_button.click() def set_ad_time(self): # TODO:log 添加user_id方便后期查看 logging.info('设置对应投放时间') WebDriverWait(self.driver, 10).until( lambda driver: self.driver.find_elements_by_xpath('//*[@class="adui-input-base"]')) input_elements = self.driver.find_elements_by_xpath('//*[@class="adui-input-base"]') if self.task['date_set']['date_module'] == '2': select_elements = self.driver.find_elements_by_xpath('//*[@class="adui-radio-base adui-radio-small"]') for _ in select_elements: if '长期投放' in _.text: _.click() input_elements[0].click() time.sleep(0.1) input_elements[0].send_keys(Keys.RIGHT) for i in range(7): time.sleep(random.uniform(0.1, 0.2)) input_elements[0].send_keys(Keys.BACKSPACE) for _ in self.task['date_set']['date_list'][0][1:]: time.sleep(random.uniform(0.1, 0.2)) input_elements[0].send_keys(_) input_elements[0].send_keys(Keys.RETURN) time.sleep(random.uniform(0.1, 0.2)) else: input_elements[0].click() input_elements[0].send_keys(Keys.RIGHT) for i in range(7): time.sleep(random.uniform(0.1, 0.2)) input_elements[0].send_keys(Keys.BACKSPACE) for _ in self.task['date_set']['date_list'][0][1:]: time.sleep(random.uniform(0.1, 0.2)) input_elements[0].send_keys(_) time.sleep(random.uniform(0.1, 0.2)) input_elements[1].click() time.sleep(0.1) input_elements[1].send_keys(Keys.RIGHT) for i in range(7): time.sleep(random.uniform(0.1, 0.2)) input_elements[1].send_keys(Keys.BACKSPACE) time.sleep(random.uniform(0.1, 0.2)) for _ in self.task['date_set']['date_list'][1][1:]: time.sleep(random.uniform(0.1, 0.2)) input_elements[1].send_keys(_) input_elements[1].send_keys(Keys.RETURN) time.sleep(0.2) self.driver.save_screenshot('time-{}.png'.format(time.time())) time.sleep(0.1) def set_ad_human_location(self): # TODO:对常驻地,出差旅行,进行区分 logging.info('设置对应人群信息-非人群包') WebDriverWait(self.driver, 10).until( lambda driver: self.driver.find_element_by_css_selector('#area_input > div > i')) self.driver.find_element_by_css_selector('#area_input > div > i').click() if self.task['plan_base'][1] == 'gzh_botoom': self.driver.find_element_by_class_name('icon-3cAquX1RLZ').click() if self.task['plan_base'][1] == 'gzh_movie': citys = self.driver.find_elements_by_class_name('checkbox-1pfRMRqv-R') for _ in citys: _.click() if self.task['plan_base'][1] == 'gzh_big_pic': self.driver.find_element_by_class_name('icon-3cAquX1RLZ').click() self.driver.find_element_by_xpath('//*[@id="bid_objective_6"]/span[1]').click() if self.task['plan_base'][1] == 'pyq': # self.driver.find_element_by_class_name('icon-3cAquX1RLZ').click() citys = self.driver.find_elements_by_class_name('checkbox-1pfRMRqv-R') for _ in citys: ActionChains(self.driver).move_to_element(_).click().perform() def set_ad_cost(self): # 投放计划创建 # 广告创建 logging.info('设置对应广告花销') day_cost = self.driver.find_element_by_css_selector('#budget_input') WebDriverWait(self.driver, 10).until(lambda x: (day_cost.is_displayed() and day_cost.is_enabled())) day_cost.send_keys(self.task['cost']['day_cost']) time.sleep(random.uniform(0.2, 0.3)) bid_cost = self.driver.find_element_by_xpath('//*[@id="price_input"]') for i in range(10): bid_cost.send_keys(Keys.BACKSPACE) time.sleep(random.uniform(0.2, 0.3)) bid_cost.send_keys(self.task['cost']['bid']) self.driver.find_element_by_css_selector('#target_next_step').click() def set_ad_human(self): # TODO:检查人群是否正常 logging.info('设置人群包') self.driver.find_element_by_xpath('//*[@id="test-dmp-container"]/div[2]/span/span[1]').click() time.sleep(0.1) select_human_element = self.driver.find_element_by_xpath( '//*[@id="test-dmp-container"]/div[2]/div[2]/div[1]/div/div[1]/button/span') ActionChains(self.driver).move_to_element(select_human_element).click().perform() time.sleep(0.4) WebDriverWait(self.driver, 100).until( lambda x: [_ for _ in self.driver.find_elements_by_xpath('//*[@class="adui-input-base"]') if _.get_attribute("placeholder") == '输入名称搜索人群包']) human_input = [_ for _ in self.driver.find_elements_by_xpath('//*[@class="adui-input-base"]') if _.get_attribute("placeholder") == '输入名称搜索人群包'][0] for _ in self.task['human_info_package']['name']: human_input.click() human_input.send_keys(_) human_input.send_keys(Keys.RETURN) WebDriverWait(self.driver, 30).until( lambda driver: len(self.driver.find_elements_by_xpath('//*[@class="adui-table-cellInner"]')) == 3) time.sleep(1) WebDriverWait(self.driver, 30).until( lambda driver: [x for x in self.driver.find_elements_by_xpath('//*[@class="adui-table-cellInner"]') if x.is_displayed() and x.is_enabled() and x.text == _]) human_names = self.driver.find_elements_by_xpath('//*[@class="adui-table-cellInner"]') for human_name in human_names: if human_name.text == _: human_name.click() for _ in range(len(_) + 1): time.sleep(0.1) human_input.send_keys(Keys.BACKSPACE) self.driver.find_element_by_xpath( '//*[@class="adui-button-base adui-button-primary adui-button-small"]').click() def set_ad_humam_gender(self): logging.info('设置性别') if self.task['human_info_parameter']['gender'] == '0': self.driver.find_element_by_xpath('//*[@id="gender_"]/span[2]').click() if self.task['human_info_parameter']['gender'] == '1': self.driver.find_element_by_xpath('//*[@id="gender_MALE"]/span[2]').click() if self.task['human_info_parameter']['gender'] == '2': self.driver.find_element_by_xpath('//*[@id="gender_FEMALE"]/span[2]').click() def set_ad_age(self): logging.info('设置年龄') age_elements = self.driver.find_elements_by_xpath('//*[@class="adui-select-selector"]') age_elements[0].click() time.sleep(0.1) age_list = self.task['human_info_parameter']['age_list'] # TODO:有时间规整一下,前端传过来的数据,dict中的值 数字全为字符串,或者全为数字 # 256,一截,[14(17),24][25,32][33,40][41,48][49,56][57,64] # 8 为基本下滑单位,+1为实际两数相减需要加一, -0.1因为刚刚好最后一位时就会下滑到下一页,最后一位无法获取 if age_list[0] == 14: age_elements[1].click() time.sleep(random.uniform(0.1, 0.2)) self.driver.execute_script(''' document.getElementsByClassName('rc-virtual-list-holder')[0].scrollTop={}; '''.format(((age_list[1] - 17 + 1 - 0.1) / 8) * 256)) self.driver.find_element_by_xpath('//*[@id="end_age_{}"]'.format(int(age_list[1]))).click() else: self.driver.execute_script(''' document.getElementsByClassName('rc-virtual-list-holder')[0].scrollTop={}; '''.format(int((age_list[0] - 17 + 1 - 0.1) / 8) * 256)) time.sleep(random.uniform(0.1, 0.2)) self.driver.find_element_by_xpath('//*[@id="begin_age_{}"]'.format(int(age_list[0]))).click() # 年龄---设置 age_elements[1].click() time.sleep(random.uniform(0.1, 0.2)) self.driver.execute_script(''' document.getElementsByClassName('rc-virtual-list-holder')[1].scrollTop={}; '''.format(int((age_list[1] - age_list[0] + 1 - 0.1) / 8) * 256)) time.sleep(random.uniform(0.1, 0.2)) self.driver.find_element_by_xpath('//*[@id="end_age_{}"]'.format(int(age_list[1]))).click() def set_ad_idea(self): # 创意创建 logging.info('设置创意') if self.task['plan_base'][1] == 'gzh_botoom': self.ad_idea_action.idea_gzh_bottom() if self.task['plan_base'][1] == 'gzh_movie': self.ad_idea_action.idea_movie_gzh_movie() if self.task['plan_base'][1] == 'gzh_big_pic': self.ad_idea_action.idea_big_pic() if self.task['plan_base'][1] == 'pyq': self.ad_idea_action.idea_pyq() next_button = self.driver.find_element_by_class_name('adui-button-primary') WebDriverWait(self.driver, 1000).until(lambda x: (next_button.is_displayed() and next_button.is_enabled())) next_button.click() def push_ad(self): # 提交 logging.info('提交广告') time.sleep(random.uniform(3, 4)) agreement_element = self.driver.find_element_by_class_name('label-3_CrbQVNtc') if agreement_element.get_attribute('aria-checked') != 'true': self.driver.find_element_by_class_name('icon-3cAquX1RLZ').click() time.sleep(random.uniform(0.5, 1)) self.driver.find_element_by_class_name('adui-button-primary').click() WebDriverWait(self.driver, 10).until( lambda driver: True if len( re.findall('广告已提交审核', self.driver.page_source)) else False) def task_check(self): # TODO: # 1.检查任务有无输入问题, # 2.需要重点确认输入金额,时间是否正确.从最后页面内容进行再次确认 # if 'master' not in self.task.keys() or 'localtion' not in self.task.keys(): # exit() pass def check_is_sucess(self): logging.info('检查广告计划创建是否成功') plan_name = self.task['title'] WebDriverWait(self.login_ad.driver, 100).until( lambda driver: True if 'token' in self.login_ad.driver.current_url else False) cookie_dict = self.login_ad.get_cookie(self.login_ad.driver, login_cookie=False) token_id = re.findall('token=(\d+)', self.login_ad.driver.current_url)[0] time_big = str(int(time.time() * 1000)) time_small = str(int(time.time())) token = token_id plan_check_url = 'https://mp.weixin.qq.com/promotion/as_rock?action=get_campaign_data&args={"op_type":1,"where":{},"page":1,"page_size":20,"pos_type":999,"ad_filter":{"name":"' \ + plan_name + '"},"advanced":true,"create_time_range":{"start_time":1610884851},"time_range":{"start_time":1610748800,"last_time":' + time_small + '}}&token=' + token + '&appid=&spid=&_=' + time_big rsp = requests.get(plan_check_url, cookies=cookie_dict) if 'list' in rsp.json(): if len(rsp.json()['list']): return True def run(self, err_num=0): try: # self.ad_human_action.check_human_info() self.set_ad_locations() self.set_ad_time() self.set_ad_title() self.set_ad_cpm() self.set_ad_human_location() self.set_ad_human() self.set_ad_humam_gender() self.set_ad_age() self.set_ad_cost() self.set_ad_idea() self.push_ad() # 切回到前一页 if self.check_is_sucess(): logging.info('创建广告计划成功') return {'sucess': True, 'result_info': ''} else: if err_num > 3: return {'sucess': False, 'result_info': '过程中全程无错误,失败'} else: self.login_ad.refresh_driver() self.login_ad.select_ad_master(service_name=self, wechat_name=self.wechat_name) return self.run(err_num=err_num + 1) except Exception as e: raise time.sleep(5) self.driver.save_screenshot('liuyi{}.png'.format(time.time())) time.sleep(5) # TODO:有空时讲 e 内容设置为原始内容 if err_num > 3: return {'sucess': False, 'result_info': str(e)} else: self.login_ad.refresh_driver() self.login_ad.select_ad_master(service_name=self.service_name, wechat_name=self.wechat_name) return self.run(err_num=err_num + 1)