from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.common.keys import Keys from selenium.webdriver import ActionChains from logging import handlers from datetime import datetime import logging import requests import random import shutil import time import re import os class CreateAd: def __init__(self, login_ad, service_name, wechat_name): self.log_ad = login_ad self.service_name = service_name self.wechat_name = wechat_name self.driver = login_ad.get_driver_loged() self.get_into_create_page() self.send_file_limit_num = 8 self.img_dir = './img' def get_into_create_page(self): # 进入创建页面 self.driver.find_element_by_id('material').click() try: # 落地页内容有的账户有,有的无,无的默认等5s WebDriverWait(self.driver, 5).until(lambda driver: len(self.driver.find_elements_by_xpath( '//*[@class="adui-table-cell"]'))) for i in self.driver.find_elements_by_xpath( '//*[@class="adui-table-cell"]'): WebDriverWait(self.driver, 5).until(lambda driver: i.is_displayed() and i.is_enabled()) except Exception as e: logging.error(str(e)) time.sleep(5) WebDriverWait(self.driver, 10).until(lambda driver: self.driver.find_element_by_xpath( '//*[@class="ui-fl-r adui-button-base adui-button-primary adui-button-small"]')) create_element = self.driver.find_element_by_xpath( '//*[@class="ui-fl-r adui-button-base adui-button-primary adui-button-small"]') WebDriverWait(self.driver, 10).until( lambda driver: create_element.is_displayed() and create_element.is_enabled()) create_element.click() logging.info('点击新建推广页 结束') WebDriverWait(self.driver, 5).until(lambda driver: driver.find_element_by_css_selector( '#wxadcontainer > div:nth-child(1) > div:nth-child(2) > div.dialog-1fj_N480ZT > div > div > div:nth-child(1) > div.dialogCardFooter-17KpBD1lgN > button')) self.driver.find_element_by_css_selector( '#wxadcontainer > div:nth-child(1) > div:nth-child(2) > div.dialog-1fj_N480ZT > div > div > div:nth-child(1) > div.dialogCardFooter-17KpBD1lgN > button').click() self.driver.switch_to.window(self.driver.window_handles[-1]) WebDriverWait(self.driver, 100).until(lambda driver: driver.find_element_by_class_name('addContent-8pexaaAGYy')) self.driver.find_element_by_class_name('addContent-8pexaaAGYy').click() WebDriverWait(self.driver, 100).until(lambda driver: driver.find_element_by_class_name('topArea-qOwEAeNuIn')) logging.info('进入到推广页,编辑界面') def set_advertisement_sign(self, layout_name): # 设置广告标记 self.driver.find_element_by_xpath('//*[@class="icon-edQB0KK2VG"]').click() input_element = self.driver.find_element_by_xpath('//input[@class="input-2lFnByGCRh"]') input_element.send_keys(Keys.BACKSPACE) input_element.send_keys(layout_name) def set_background_color(self, color): color_buttons = self.driver.find_elements_by_class_name('adui-cp-picker') c_buttons_can_use = [] for _ in color_buttons: if _.is_displayed() and _.is_enabled(): c_buttons_can_use.append(_) c_buttons_can_use[0].click() time.sleep(random.uniform(0.2, 0.3)) input_elements = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]') for _ in input_elements: if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == 'FFFFFF': _.click() _.send_keys(color) def set_head_assemb(self, info): logging.info('开始设置头版首页') def single_page_set(): self.driver.find_element_by_xpath('//*[@id="stage-sidebar"]/div[1]/div/div[1]/div/div').click() time.sleep(random.uniform(0.1, 0.2)) # 设置图片格式 if info['content']['adSite'] != '朋友圈信息流': self.driver.find_elements_by_xpath('//*[@class="adui-radio-indicator"]')[1].click() elif info['content']['outerStyle'] != '常规广告': select_e = self.driver.find_elements_by_xpath('//*[@class="adui-select-selection-item"]') for _ in select_e: if _.text == '常规广告': _.click() time.sleep(0.1) select_e = self.driver.find_elements_by_xpath('//*[@class="adui-select-item-option-content"]') for _ in select_e: if _.text == '卡片广告': _.click() # 上传图片 file_name = re.split('\/', info['content']['url'])[-1] self.driver.find_element_by_class_name('upload-img-item-inner-2gsg7NjaZ8').click() WebDriverWait(self.driver, 10).until( lambda x: len([_ for _ in self.driver.find_elements_by_class_name('title-29sncpKgTl') if _.is_displayed() and _.is_enabled()]) > 0) turn_page_buttons = self.driver.find_elements_by_class_name('paginationIcon-1EfoH0sNRF') can_use_button = [] for _ in turn_page_buttons: if _.is_enabled() and _.is_displayed(): can_use_button.append(_) # 不断翻页获取到元素为止 chose_over = False while True: page_elements = self.driver.find_elements_by_class_name('title-29sncpKgTl') for _ in page_elements: if _.is_displayed() and _.is_enabled(): if file_name in _.text: _.click() chose_over = True break if chose_over or len(can_use_button) == 0: break # 翻到最后一页时停止 page_text = self.driver.find_element_by_class_name('count_small-37CcvfzoTl').text page_nums = re.findall('\d+', page_text) if int(page_nums[0].strip()) == int(page_nums[1].strip()): break # 翻页 can_use_button[2].click() # 确保翻页成功 WebDriverWait(self.driver, 10).until( lambda x: page_text != self.driver.find_element_by_class_name('count_small-37CcvfzoTl').text) self.driver.find_element_by_xpath('//*[@id="test_material_container_confirm"]').click() try: WebDriverWait(self.driver, 4).until( lambda driver: driver.find_element_by_class_name( 'btnFist-uueBS6DQFa')) _ = self.driver.find_element_by_class_name( 'btnFist-uueBS6DQFa') WebDriverWait(self.driver, 4).until( lambda x: (_.is_displayed() and _.is_enabled())) time.sleep(1) _.click() WebDriverWait(self.driver, 100).until( lambda driver: driver.find_element_by_class_name( 'btn-3E823IXt3m')) _ = self.driver.find_element_by_class_name( 'btn-3E823IXt3m') WebDriverWait(self.driver, 100).until( lambda x: (_.is_displayed() and _.is_enabled())) time.sleep(1) _.click() except Exception as e: pass logging.info('头版首页单图上传结束') def multi_page_set(): # TODO:现在图片设置为素材库,需要对应下载然后存储 self.driver.find_element_by_css_selector( '#stage-sidebar > div.topArea-qOwEAeNuIn > div > div:nth-child(2)').click() time.sleep(random.uniform(0.1, 0.2)) page_size = len(info_v) if page_size == 3: pass if page_size == 4: self.driver.find_element_by_css_selector( '#stage-settings > div:nth-child(1) > div > div > div:nth-child(3) > div.adui-form-item > div.adui-form-control > div > button:nth-child(2)').click() if page_size == 6: self.driver.find_element_by_css_selector( '#stage-settings > div:nth-child(1) > div > div > div:nth-child(3) > div.adui-form-item > div.adui-form-control > div > button:nth-child(3)').click() time.sleep(random.uniform(0.1, 0.2)) self.driver.find_element_by_class_name('imageUploadItem-tA9JX0RWua').click() WebDriverWait(self.driver, 1000).until( lambda driver: self.driver.find_element_by_class_name('adui-tabs-tab') ) input_elements = self.driver.find_elements_by_tag_name('input') input_find_element = None for _ in input_elements: if '输入关键词搜索素材' in _.get_attribute('placeholder'): input_find_element = _ for _ in info_v: file_name = os.path.basename(_) logging.info(file_name) input_find_element.send_keys(file_name) input_find_element.send_keys(Keys.RETURN) WebDriverWait(self.driver, 1000).until( lambda driver: driver.find_element_by_class_name('img-2HvhMmpnzP')) file_element = self.driver.find_element_by_class_name('img-2HvhMmpnzP') WebDriverWait(self.driver, 1000).until( lambda x: (file_element.is_displayed() and file_element.is_enabled())) ActionChains(self.driver).move_to_element(file_element).perform() time.sleep(random.uniform(0.5, 1)) file_element.click() for i in range(len(file_name) + 10): input_find_element.send_keys(Keys.BACKSPACE) time.sleep(random.uniform(0.5, 1)) self.driver.find_element_by_xpath('/html/body/div[12]/div/div/div[2]/div/div[3]/button[2]').click() # 切图操作如果有的话进行对应操作. for i in range(len(info_v) + 1): try: WebDriverWait(self.driver, 6).until( lambda driver: driver.find_element_by_xpath( '/html/body/div[13]/div/div/div[2]/div/div[3]/button[2]')) self.driver.find_element_by_xpath('/html/body/div[13]/div/div/div[2]/div/div[3]/button[2]').click() except: pass logging.info('头版多图选择 结束') def movie_set(): # TODO:视频转为链接, file_name = os.path.basename(info_v) self.driver.find_element_by_xpath('//*[@id="stage-sidebar"]/div[1]/div/div[3]/div/div').click() self.driver.find_element_by_xpath('//*[@class="comptEditButton-2JsnAFdOGZ"]').click() WebDriverWait(self.driver, 100).until( lambda x: len([_ for _ in self.driver.find_elements_by_class_name('title-29sncpKgTl') if _.is_displayed() and _.is_enabled()]) > 0) # turn_page_buttons = self.driver.find_elements_by_class_name('paginationIcon-1EfoH0sNRF') can_use_button = [] for _ in turn_page_buttons: if _.is_enabled() and _.is_displayed(): can_use_button.append(_) # 不断翻页获取到元素为止 chose_over = False while True: page_elements = self.driver.find_elements_by_class_name('title-29sncpKgTl') for _ in page_elements: if _.is_displayed() and _.is_enabled(): if file_name in _.text: _.click() chose_over = True break if chose_over or len(can_use_button) == 0: # can_use_button 数量说明是否可以翻页,如果不可以翻页,则直接停止 break # 翻到最后一页时停止 page_text_elements = self.driver.find_elements_by_class_name('count_small-37CcvfzoTl') for _ in page_text_elements: if _.is_enabled() and _.is_displayed(): page_text = _.text page_text_element = _ page_nums = re.findall('\d+', page_text) if int(page_nums[0].strip()) == int(page_nums[1].strip()): break # 翻页 can_use_button[2].click() # 确保翻页成功 WebDriverWait(self.driver, 10).until( lambda x: page_text != page_text_element.text) sc_buttons = self.driver.find_elements_by_id('test_material_container_confirm') for _ in sc_buttons: if _.is_enabled() and _.is_displayed(): _.click() info_type = info['type'] info_v = None # TODO: 暂时存在,之后修改好multi_page_set 和movie_set.就删除 if info['type'] == 'topImg': single_page_set() if info['type'] == 'topSlider': multi_page_set() if info['type'] == 'topVideo': movie_set() # 设置头部组件 pass def set_page(self, config_info): logging.info('开始设置图片模块') page_link = config_info['url'] # 设置图片模块 self.driver.find_element_by_xpath('//*[@id="stage-sidebar"]/section/div[2]/div[1]/div/div').click() time.sleep(random.uniform(0.1, 0.2)) file_name = re.split('\/', page_link)[-1] upload_elements = self.driver.find_elements_by_class_name('upload-img-item-inner-2gsg7NjaZ8') for _ in upload_elements: if _.is_displayed() and _.is_enabled(): _.click() WebDriverWait(self.driver, 10).until( lambda x: len([_ for _ in self.driver.find_elements_by_class_name('title-29sncpKgTl') if _.is_displayed() and _.is_enabled()]) > 0) # 不断翻页获取到元素为止 chose_over = False logging.info('翻页开始') while True: page_elements = self.driver.find_elements_by_class_name('title-29sncpKgTl') for _ in page_elements: if _.is_displayed() and _.is_enabled(): if file_name in _.text: _.click() chose_over = True break turn_page_buttons = self.driver.find_elements_by_class_name('paginationIcon-1EfoH0sNRF') can_use_button = [] for _ in turn_page_buttons: if _.is_enabled() and _.is_displayed(): can_use_button.append(_) if chose_over or len(can_use_button) == 0: # can_use_button 数量说明是否可以翻页,如果不可以翻页,则直接停止 break # 翻到最后一页时停止 page_text_elements = self.driver.find_elements_by_class_name('count_small-37CcvfzoTl') for _ in page_text_elements: if _.is_enabled() and _.is_displayed(): page_text = _.text page_text_element = _ page_nums = re.findall('\d+', page_text) if int(page_nums[0].strip()) == int(page_nums[1].strip()): break # 翻页 can_use_button[2].click() # 确保翻页成功 WebDriverWait(self.driver, 10).until( lambda x: page_text != page_text_element.text) logging.info('翻页结束') sc_buttons = self.driver.find_elements_by_id('test_material_container_confirm') for _ in sc_buttons: if _.is_enabled() and _.is_displayed(): _.click() logging.info('是否截图开始') try: WebDriverWait(self.driver, 4).until( lambda driver: driver.find_element_by_class_name( 'btnFist-uueBS6DQFa')) _ = self.driver.find_element_by_class_name( 'btnFist-uueBS6DQFa') WebDriverWait(self.driver, 4).until( lambda x: (_.is_displayed() and _.is_enabled())) # 已经出现但任需要等待 time.sleep(1) _.click() WebDriverWait(self.driver, 100).until( lambda x: len([_ for _ in self.driver.find_elements_by_class_name('btn-3E823IXt3m') if _.is_displayed() and _.is_enabled()]) > 0) for _ in self.driver.find_elements_by_class_name('btn-3E823IXt3m'): if _.is_displayed() and _.is_enabled(): _.click() except Exception as e: logging.info(e) logging.info('是否截图结束') # 设置文本边距 if config_info['marginTop'] != 0 or config_info['marginBottom'] != 0: distance_buttons = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]') distance_buttons_can_use = [] for _ in distance_buttons: if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '0': distance_buttons_can_use.append(_) distance_buttons_can_use[0].click() for i in range(4): distance_buttons_can_use[0].send_keys(Keys.BACKSPACE) distance_buttons_can_use[0].send_keys(config_info['marginTop']) distance_buttons_can_use[1].click() for i in range(4): distance_buttons_can_use[1].send_keys(Keys.BACKSPACE) distance_buttons_can_use[1].send_keys(config_info['marginBottom']) logging.info('图片模块设置结束') def set_content(self, config_info): logging.info(' 开始设置文本模块') # 设置文本模块 # 1.文本内容2.文本颜色3.是否加粗4.文本位置设置5.文本大小 # 设置文本内容 self.driver.find_element_by_xpath('//*[@id="stage-sidebar"]/section/div[2]/div[5]/div/div').click() time.sleep(random.uniform(0.2, 0.3)) input_elements = self.driver.find_elements_by_xpath('//textarea[@class="adui-input-base"]') # pyperclip.copy(config_info['text']) js_base = ''' function copyToClipboard(text) { var dummy = document.createElement("textarea"); // to avoid breaking orgain page when copying more words // cant copy when adding below this code // dummy.style.display = 'none' document.body.appendChild(dummy); //Be careful if you use texarea. setAttribute('value', value), which works with "input" does not work with "textarea". – Eduard dummy.value = text; dummy.select(); document.execCommand("copy"); document.body.removeChild(dummy); } ''' content_change = config_info['text'] content_change = content_change.replace("\\", "\\\\") content_change = content_change.replace('\n', '\\n') content_change = content_change.replace('\n', '\\n') content_change = content_change.replace("'", "\'") js_base = js_base + '''copyToClipboard('{}');'''.format(content_change) self.driver.execute_script(js_base) for _ in input_elements: if _.is_enabled() and _.is_displayed(): _.send_keys(Keys.CONTROL, 'v') # 设置颜色 if config_info['color'] != '#595959': color_buttons = self.driver.find_elements_by_class_name('adui-cp-picker') c_buttons_can_use = [] for _ in color_buttons: if _.is_displayed() and _.is_enabled(): c_buttons_can_use.append(_) c_buttons_can_use[1].click() time.sleep(random.uniform(0.2, 0.3)) input_elements = self.driver.find_elements_by_tag_name('input') for _ in input_elements: if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '595959': _.click() _.send_keys(config_info['color']) # 设置是否加粗 if config_info['fontWeight'] != 'normal': big_elements = self.driver.find_elements_by_class_name('adui-button-content') for _ in big_elements: if _.text == '加粗' and _.is_displayed() and _.is_enabled(): _.click() # 设置文本位置 if config_info['textAlign'] != 'left': loc_buttons = self.driver.find_elements_by_xpath( "//div[contains(@class, 'adui-button-group_banner')]//button") loc_buttons_can_use = [] for _ in loc_buttons: if _.is_enabled() and _.is_displayed(): loc_buttons_can_use.append(_) if config_info['textAlign'] == 'center': loc_buttons_can_use[1].click() if config_info['textAlign'] == 'right': loc_buttons_can_use[2].click() # 设置文本大小 if config_info['fontSize'] != 15: str_buttons = self.driver.find_elements_by_xpath("//*[@class='adui-select-selection-search']") str_buttons_can_use = [] for _ in str_buttons: if _.is_displayed() and _.is_enabled(): str_buttons_can_use.append(_) str_buttons_can_use[1].click() time.sleep(random.uniform(0.5, 1)) str_num_buttons = self.driver.find_elements_by_xpath("//*[@class='adui-select-item-option-content']") str_num_can_use = [] for _ in str_num_buttons: if _.is_displayed() and _.is_enabled(): str_num_can_use.append(_) # str_num_map = {14: 0, 15: 1, 16: 2, 18: 3, 20: 4, 24: 5, 36: 6} # str_num_can_use[str_num_map[config_info['fontSize']]].click() for _ in str_num_can_use: if _.text == str(config_info['fontSize']): _.click() # 设置文本边距 if config_info['marginTop'] != 22 or config_info['marginBottom'] != 22: distance_buttons = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]') distance_buttons_can_use = [] for _ in distance_buttons: if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '22': distance_buttons_can_use.append(_) distance_buttons_can_use[0].click() for i in range(4): distance_buttons_can_use[0].send_keys(Keys.BACKSPACE) distance_buttons_can_use[0].send_keys(config_info['marginTop']) distance_buttons_can_use[1].click() for i in range(4): distance_buttons_can_use[1].send_keys(Keys.BACKSPACE) distance_buttons_can_use[1].send_keys(config_info['marginBottom']) def set_follow_button(self, config_info): # TODO:是否一键关注 # 设置关注按钮 # 0.是否一键关注 1.设置button文本内容 2.是否加粗 3.设置字体颜色,边框颜色,填充色 4.设置边距 self.driver.find_element_by_xpath('//*[@id="stage-sidebar"]/section/div[4]/div[2]/div/div').click() # 开始设置一键关注 if 'follow' in config_info.keys(): if not config_info['follow']: time.sleep(0.1) follow_bs = self.driver.find_elements_by_xpath( '//*[@class="form-caption-3Xp3o6Drwf"]/div/span') for _ in follow_bs: if _.is_displayed() and _.is_enabled(): _.click() # 文本设置 input_elements = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]') for _ in input_elements: if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '关注公众号': _.click() _.clear() for i in range(10): _.send_keys(Keys.BACKSPACE) _.send_keys(config_info['text']) # 文本是否加粗 if config_info['fontWeight'] != 'normal': big_elements = self.driver.find_elements_by_xpath('//span[@class="adui-button-content"]') for _ in big_elements: if _.text == '加粗' and _.is_displayed() and _.is_enabled(): _.click() # 颜色设置 input_elements = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]') input_elements_can_use = [] for _ in input_elements: if _.is_enabled() and _.is_displayed() and ( _.get_attribute("value") == '07C160' or _.get_attribute("value") == 'FFFFFF'): input_elements_can_use.append(_) if config_info['textColor'] != '#FFFFFF': input_elements_can_use[0].click() input_elements_can_use[0].send_keys(config_info['textColor']) time.sleep(random.uniform(0.1, 0.5)) if config_info['borderColor'] != '#FFFFFF': input_elements_can_use[1].click() input_elements_can_use[1].send_keys(config_info['borderColor']) time.sleep(random.uniform(0.1, 0.5)) input_elements_can_use[2].click() input_elements_can_use[2].send_keys(config_info['backColor']) time.sleep(random.uniform(0.1, 0.5)) # 间隙设置 size_buttons = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]') size_buttons_can_use = [] for _ in size_buttons: if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '28': size_buttons_can_use.append(_) size_buttons_can_use[0].click() for i in range(4): size_buttons_can_use[0].send_keys(Keys.BACKSPACE) size_buttons_can_use[0].send_keys(config_info['marginTop']) size_buttons_can_use[1].click() for i in range(4): size_buttons_can_use[1].send_keys(Keys.BACKSPACE) size_buttons_can_use[1].send_keys(config_info['marginBottom']) def set_text_button(self): # 设置图文按钮 pass def send_file_multi(self, layout, err_num=0): # 有问题,暂时不使用 # 上传文件,文件上传与整体流程切割开 token = re.findall('token=(\d+)', self.driver.current_url) url_ = 'https://mp.weixin.qq.com/promotion/frame?t=ad_system/common_frame&t1=material_std/material_library&token={}'.format( token[0]) js = "window.open('{}')".format(url_) self.driver.execute_script(js) time.sleep(random.uniform(1, 2)) self.driver.switch_to.window(self.driver.window_handles[-1]) file_set = set() for v in layout.values(): if isinstance(v, dict): if 'multi_page' in v.keys() or 'page' in v.keys() or 'movie' in v.keys(): v_name = list(v.keys())[0] if isinstance(v[v_name], list): for _ in v[v_name]: file_set.add(_) else: file_set.add(v[v_name]) file_list = list(file_set) # print(file_list) # print('file list size', len(file_list)) send_file_sign = self.send_file_limit_num for _ in file_list: # print(_) self.driver.find_element_by_xpath('//*[@id="wxadcontainer"]/div[1]/div[2]/div[4]/input').send_keys(_) time.sleep(100) while True: # 失败,失败直接退出重跑 # 正在上传数量,如果是正在上传小于限定数量,就不断输入 # 上传完毕,小于限定数量,不断输入,.....已经上传好了,就关闭 time.sleep(1) send_reslut_content = self.driver.find_element_by_xpath( '//*[@id="wxadcontainer"]/div[1]/div[2]/div[4]/div/strong').text if '失败' in send_reslut_content: if err_num < 3: self.send_file(layout, err_num=err_num + 1) else: exit() if '正在上传' in send_reslut_content: if send_file_sign < len(file_list): send_num = re.findall('(\d+)', send_reslut_content)[0] if int(send_num) < self.send_file_limit_num: # 还可以继续上传 x = send_file_sign can_send_sign = send_file_sign + (self.send_file_limit_num - send_num) y = can_send_sign if can_send_sign < len(file_list) else len(file_list) for i in range(x, y): send_file_sign = send_file_sign + 1 self.driver.find_element_by_xpath( '//*[@id="wxadcontainer"]/div[1]/div[2]/div[4]/input').send_keys(file_list[i]) else: pass if '上传成功' in send_reslut_content: if send_file_sign < len(file_list): send_num = re.findall('(\d+)', send_reslut_content)[0] if int(send_num) < self.send_file_limit_num: # 还可以继续上传 x = send_file_sign can_send_sign = send_file_sign + (self.send_file_limit_num - send_num) y = can_send_sign if can_send_sign < len(file_list) else len(file_list) for i in range(x, y): send_file_sign = send_file_sign + 1 self.driver.find_element_by_xpath( '//*[@id="wxadcontainer"]/div[1]/div[2]/div[4]/input').send_keys(file_list[i]) else: break time.sleep(1000) self.driver.execute_script('window.close();') def send_file(self, file_link, err_num=0): # 下载图片,存储于 if not os.path.exists(self.img_dir): os.makedirs(self.img_dir) link_pra = re.split('\/', file_link) file_path = os.getcwd() + '/' + self.img_dir + '/' + link_pra[-1] rsp = requests.get(file_link) with open(file_path, 'wb') as f: f.write(rsp.content) # 有问题,暂时不使用 self.driver.execute_script('location.reload();') self.driver.find_element_by_xpath('//*[@id="wxadcontainer"]/div[1]/div[2]/div[4]/input').send_keys(file_path) def send_file_alone(self, layout): def get_url(v_info): if 'url' in v_info.keys(): file_set.add(v_info['url']) for v in v_info.values(): if isinstance(v, dict): get_url(v) if isinstance(v, list): for _ in v: if isinstance(_, dict): get_url(_) # 上传文件,单线程 # 上传文件,文件上传与整体流程切割开 logging.info('开始传送文件') WebDriverWait(self.driver, 10).until( lambda x: len(re.findall('token=(\d+)', self.driver.current_url))) token = re.findall('token=(\d+)', self.driver.current_url) url_ = 'https://mp.weixin.qq.com/promotion/frame?t=ad_system/common_frame&t1=material_std/material_library&token={}'.format( token[0]) js = "window.open('{}')".format(url_) self.driver.execute_script(js) time.sleep(random.uniform(1, 2)) self.driver.switch_to.window(self.driver.window_handles[-1]) file_set = set() # TODO:之后还有multi_page 和 movie # for v in layout.values(): # if isinstance(v, dict): # if 'multi_page' in v.keys() or 'page' in v.keys() or 'movie' in v.keys(): # v_name = list(v.keys())[0] # if isinstance(v[v_name], list): # for _ in v[v_name]: # file_set.add(_) # else: # file_set.add(v[v_name]) get_url(layout) for _ in file_set: self.send_file(_) err_num = 0 while True: time.sleep(1) send_reslut_content = self.driver.find_element_by_xpath( '//*[@id="wxadcontainer"]/div[1]/div[2]/div[4]/div/strong').text if '上传成功' in send_reslut_content: break if '失败' in send_reslut_content: err_num = err_num + 1 self.send_file(_) if err_num > 3: raise ValueError("图片上传失败") self.driver.execute_script('window.close();') self.driver.switch_to.window(self.driver.window_handles[-1]) logging.info('传送文件,结束') def set_share_content(self, title_content, des_content): self.driver.find_element_by_xpath('//*[@id="wxadcontainer"]/div[1]/div/section/header/div[2]/button[2]').click() WebDriverWait(self.driver, 50).until(lambda driver: driver.find_element_by_xpath( '//*[@id="wxadcontainer"]/div[1]/div/div/div/div[1]/section/section/div[2]/div[1]/div/div/input')) title_input = self.driver.find_element_by_xpath( '//*[@id="wxadcontainer"]/div[1]/div/div/div/div[1]/section/section/div[2]/div[1]/div/div/input') title_input.click() title_input.send_keys(title_content) des_input = self.driver.find_element_by_xpath( '//*[@id="wxadcontainer"]/div[1]/div/div/div/div[1]/section/section/div[2]/div[2]/div/div/input') des_input.click() des_input.send_keys(des_content) self.driver.find_element_by_xpath('//*[@id="wxadcontainer"]/div[1]/div/header/div[2]/button').click() WebDriverWait(self.driver, 10).until( lambda driver: driver.find_element_by_xpath('/html/body/div[6]/div/div/div[2]/div/div[3]/button[2]')) self.driver.find_element_by_xpath('/html/body/div[6]/div/div/div[2]/div/div[3]/button[2]').click() time.sleep(1) @staticmethod def check_sucess_api(log_ad, layout_name): # 默认在进入公众号初始页面 logging.info('开始检查落地页是否创建成功') WebDriverWait(log_ad.driver, 100).until( lambda driver: True if 'token' in log_ad.driver.current_url else False) cookie_dict = log_ad.get_cookie(log_ad.driver, login_cookie=False) token_id = re.findall('token=(\d+)', log_ad.driver.current_url)[0] requests.session() layout_url = 'https://mp.weixin.qq.com/promotion/landingpage_manager?action=list_pages&page=1&page_size=10&canvas_name={layout_name}&login_from=&is_grant=0&owner_uid=&token={wechat_token}&appid=&spid=&_={time_}'.format( layout_name=layout_name, wechat_token=token_id, time_=int(time.time() * 1000)) session = requests.session() rsp = session.get(url=layout_url, cookies=cookie_dict) result_json = rsp.json() if 'landing_page_list' in result_json.keys(): if len(result_json['landing_page_list']): logging.info('对应落地页存在于微信后台') return True def remove_all_file(self): shutil.rmtree(os.getcwd() + '/' + self.img_dir) pass def create_layout(self, layout, sql_session, err_num=0): # try: self.send_file_alone(layout) self.set_advertisement_sign(layout_name=layout['layoutName']) self.set_head_assemb(layout['topContent']) self.set_background_color(layout['pageBackColor']) for _ in layout['content']: if _['type'] == 'img': self.set_page(_['content']) if _['type'] == 'txt': self.set_content(_['content']) if _['type'] == 'followAcc': self.set_follow_button(_['content']) self.set_share_content(title_content=layout['shareTittle'], des_content=layout['shareDesc']) self.remove_all_file() if self.check_sucess_api(layout_name=layout['layoutName'], log_ad=self.log_ad): return {'sucess': True, 'result_info': ''} else: if err_num > 3: return {'sucess': False, 'result_info': '过程中全程无错误,失败'} else: self.log_ad.refresh_driver() self.log_ad.select_ad_master(service_name=self.service_name, wechat_name=self.wechat_name, sql_session=sql_session) self.get_into_create_page() return self.create_layout(layout, sql_session, err_num=err_num + 1) except Exception as e: logging.error(e) self.log_ad.driver.save_screenshot( 'user_id:{}_time_{}_layout_name:{}_layout_error.png'.format(self.log_ad.user_id, datetime.now().strftime( "%Y-%m-%d, %H:%M:%S"), layout['layoutName'])) # TODO:有空时讲 e 内容设置为原始内容 if err_num > 3: return {'sucess': False, 'result_info': str(e)} else: self.log_ad.refresh_driver() self.log_ad.select_ad_master(service_name=self.service_name, wechat_name=self.wechat_name, sql_session=sql_session) self.get_into_create_page() return self.create_layout(layout, sql_session, err_num=err_num + 1) if __name__ == '__main__': logging.basicConfig( handlers=[ logging.handlers.RotatingFileHandler('./create_ad_layout.log', maxBytes=10 * 1024 * 1024, backupCount=5, encoding='utf-8') , logging.StreamHandler() # 供输出使用 ], level=logging.INFO, format="%(asctime)s - %(levelname)s %(filename)s %(funcName)s %(lineno)s - %(message)s" )