create_ad_layout.py 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. from selenium.webdriver.support.wait import WebDriverWait
  2. from selenium.webdriver.common.keys import Keys
  3. from selenium.webdriver import ActionChains
  4. from logging import handlers
  5. import logging
  6. import requests
  7. import random
  8. import shutil
  9. import time
  10. import re
  11. import os
  12. class CreateAd:
  13. def __init__(self, login_ad, service_name, wechat_name):
  14. self.log_ad = login_ad
  15. self.service_name = service_name
  16. self.wechat_name = wechat_name
  17. self.driver = login_ad.get_driver_loged()
  18. self.get_into_create_page()
  19. self.send_file_limit_num = 8
  20. self.img_dir = './img'
  21. def get_into_create_page(self):
  22. # 进入创建页面
  23. self.driver.find_element_by_id('material').click()
  24. # TODO:经常发生无法点击,添加enble无效,添加延时
  25. time.sleep(random.uniform(5, 7))
  26. WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element_by_class_name('ui-fl-r'))
  27. create_element = self.driver.find_element_by_class_name('ui-fl-r')
  28. WebDriverWait(self.driver, 10).until(
  29. lambda driver: create_element.is_displayed() and create_element.is_enabled())
  30. self.driver.find_element_by_class_name('ui-fl-r').click()
  31. WebDriverWait(self.driver, 5).until(lambda driver: driver.find_element_by_css_selector(
  32. '#wxadcontainer > div:nth-child(1) > div:nth-child(2) > div.dialog-1fj_N480ZT > div > div > div:nth-child(1) > div.dialogCardFooter-17KpBD1lgN > button'))
  33. self.driver.find_element_by_css_selector(
  34. '#wxadcontainer > div:nth-child(1) > div:nth-child(2) > div.dialog-1fj_N480ZT > div > div > div:nth-child(1) > div.dialogCardFooter-17KpBD1lgN > button').click()
  35. self.driver.switch_to.window(self.driver.window_handles[-1])
  36. WebDriverWait(self.driver, 100).until(lambda driver: driver.find_element_by_class_name('addContent-8pexaaAGYy'))
  37. self.driver.find_element_by_class_name('addContent-8pexaaAGYy').click()
  38. WebDriverWait(self.driver, 100).until(lambda driver: driver.find_element_by_class_name('topArea-qOwEAeNuIn'))
  39. def set_advertisement_sign(self, layout_name):
  40. # 设置广告标记
  41. self.driver.find_element_by_xpath('//*[@class="icon-edQB0KK2VG"]').click()
  42. input_element = self.driver.find_element_by_xpath('//input[@class="input-2lFnByGCRh"]')
  43. input_element.send_keys(Keys.BACKSPACE)
  44. input_element.send_keys(layout_name)
  45. def set_background_color(self):
  46. color_buttons = self.driver.find_elements_by_class_name('adui-cp-picker')
  47. c_buttons_can_use = []
  48. for _ in color_buttons:
  49. if _.is_displayed() and _.is_enabled():
  50. c_buttons_can_use.append(_)
  51. c_buttons_can_use[0].click()
  52. time.sleep(random.uniform(0.2, 0.3))
  53. input_elements = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]')
  54. for _ in input_elements:
  55. if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == 'FFFFFF':
  56. _.click()
  57. _.send_keys('F7F7F7')
  58. def set_head_assemb(self, info):
  59. def single_page_set():
  60. self.driver.find_element_by_xpath('//*[@id="stage-sidebar"]/div[1]/div/div[1]/div/div').click()
  61. time.sleep(random.uniform(0.1, 0.2))
  62. file_name = re.split('\/', info_v)[-1]
  63. self.driver.find_element_by_class_name('upload-img-item-inner-2gsg7NjaZ8').click()
  64. WebDriverWait(self.driver, 10).until(
  65. lambda x: len([_ for _ in self.driver.find_elements_by_class_name('title-29sncpKgTl') if
  66. _.is_displayed() and _.is_enabled()]) > 0)
  67. turn_page_buttons = self.driver.find_elements_by_class_name('paginationIcon-1EfoH0sNRF')
  68. can_use_button = []
  69. for _ in turn_page_buttons:
  70. if _.is_enabled() and _.is_displayed():
  71. can_use_button.append(_)
  72. # 不断翻页获取到元素为止
  73. chose_over = False
  74. while True:
  75. page_elements = self.driver.find_elements_by_class_name('title-29sncpKgTl')
  76. for _ in page_elements:
  77. if _.is_displayed() and _.is_enabled():
  78. if file_name in _.text:
  79. _.click()
  80. chose_over = True
  81. break
  82. if chose_over or len(can_use_button) == 0:
  83. break
  84. # 翻到最后一页时停止
  85. page_text = self.driver.find_element_by_class_name('count_small-37CcvfzoTl').text
  86. page_nums = re.findall('\d+', page_text)
  87. if int(page_nums[0].strip()) == int(page_nums[1].strip()):
  88. break
  89. # 翻页
  90. can_use_button[2].click()
  91. # 确保翻页成功
  92. WebDriverWait(self.driver, 10).until(
  93. lambda x: page_text != self.driver.find_element_by_class_name('count_small-37CcvfzoTl').text)
  94. self.driver.find_element_by_xpath('//*[@id="test_material_container_confirm"]').click()
  95. try:
  96. WebDriverWait(self.driver, 4).until(
  97. lambda driver: driver.find_element_by_class_name(
  98. 'btnFist-uueBS6DQFa'))
  99. _ = self.driver.find_element_by_class_name(
  100. 'btnFist-uueBS6DQFa')
  101. WebDriverWait(self.driver, 4).until(
  102. lambda x: (_.is_displayed() and _.is_enabled()))
  103. time.sleep(1)
  104. _.click()
  105. WebDriverWait(self.driver, 100).until(
  106. lambda driver: driver.find_element_by_class_name(
  107. 'btn-3E823IXt3m'))
  108. _ = self.driver.find_element_by_class_name(
  109. 'btn-3E823IXt3m')
  110. WebDriverWait(self.driver, 100).until(
  111. lambda x: (_.is_displayed() and _.is_enabled()))
  112. time.sleep(1)
  113. _.click()
  114. except Exception as e:
  115. pass
  116. logging.info('头版首页单图上传结束')
  117. def multi_page_set():
  118. # TODO:现在图片设置为素材库,需要对应下载然后存储
  119. self.driver.find_element_by_css_selector(
  120. '#stage-sidebar > div.topArea-qOwEAeNuIn > div > div:nth-child(2)').click()
  121. time.sleep(random.uniform(0.1, 0.2))
  122. page_size = len(info_v)
  123. if page_size == 3:
  124. pass
  125. if page_size == 4:
  126. self.driver.find_element_by_css_selector(
  127. '#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()
  128. if page_size == 6:
  129. self.driver.find_element_by_css_selector(
  130. '#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()
  131. time.sleep(random.uniform(0.1, 0.2))
  132. self.driver.find_element_by_class_name('imageUploadItem-tA9JX0RWua').click()
  133. WebDriverWait(self.driver, 1000).until(
  134. lambda driver: self.driver.find_element_by_class_name('adui-tabs-tab')
  135. )
  136. input_elements = self.driver.find_elements_by_tag_name('input')
  137. input_find_element = None
  138. for _ in input_elements:
  139. if '输入关键词搜索素材' in _.get_attribute('placeholder'):
  140. input_find_element = _
  141. for _ in info_v:
  142. file_name = os.path.basename(_)
  143. logging.info(file_name)
  144. input_find_element.send_keys(file_name)
  145. input_find_element.send_keys(Keys.RETURN)
  146. WebDriverWait(self.driver, 1000).until(
  147. lambda driver: driver.find_element_by_class_name('img-2HvhMmpnzP'))
  148. file_element = self.driver.find_element_by_class_name('img-2HvhMmpnzP')
  149. WebDriverWait(self.driver, 1000).until(
  150. lambda x: (file_element.is_displayed() and file_element.is_enabled()))
  151. ActionChains(self.driver).move_to_element(file_element).perform()
  152. time.sleep(random.uniform(0.5, 1))
  153. file_element.click()
  154. for i in range(len(file_name) + 10):
  155. input_find_element.send_keys(Keys.BACKSPACE)
  156. time.sleep(random.uniform(0.5, 1))
  157. self.driver.find_element_by_xpath('/html/body/div[12]/div/div/div[2]/div/div[3]/button[2]').click()
  158. # 切图操作如果有的话进行对应操作.
  159. for i in range(len(info_v) + 1):
  160. try:
  161. WebDriverWait(self.driver, 6).until(
  162. lambda driver: driver.find_element_by_xpath(
  163. '/html/body/div[13]/div/div/div[2]/div/div[3]/button[2]'))
  164. self.driver.find_element_by_xpath('/html/body/div[13]/div/div/div[2]/div/div[3]/button[2]').click()
  165. except:
  166. pass
  167. logging.info('头版多图选择 结束')
  168. def movie_set():
  169. # TODO:视频转为链接,
  170. file_name = os.path.basename(info_v)
  171. self.driver.find_element_by_xpath('//*[@id="stage-sidebar"]/div[1]/div/div[3]/div/div').click()
  172. self.driver.find_element_by_xpath('//*[@class="comptEditButton-2JsnAFdOGZ"]').click()
  173. WebDriverWait(self.driver, 100).until(
  174. lambda x: len([_ for _ in self.driver.find_elements_by_class_name('title-29sncpKgTl') if
  175. _.is_displayed() and _.is_enabled()]) > 0)
  176. #
  177. turn_page_buttons = self.driver.find_elements_by_class_name('paginationIcon-1EfoH0sNRF')
  178. can_use_button = []
  179. for _ in turn_page_buttons:
  180. if _.is_enabled() and _.is_displayed():
  181. can_use_button.append(_)
  182. # 不断翻页获取到元素为止
  183. chose_over = False
  184. while True:
  185. page_elements = self.driver.find_elements_by_class_name('title-29sncpKgTl')
  186. for _ in page_elements:
  187. if _.is_displayed() and _.is_enabled():
  188. if file_name in _.text:
  189. _.click()
  190. chose_over = True
  191. break
  192. if chose_over or len(can_use_button) == 0:
  193. # can_use_button 数量说明是否可以翻页,如果不可以翻页,则直接停止
  194. break
  195. # 翻到最后一页时停止
  196. page_text_elements = self.driver.find_elements_by_class_name('count_small-37CcvfzoTl')
  197. for _ in page_text_elements:
  198. if _.is_enabled() and _.is_displayed():
  199. page_text = _.text
  200. page_text_element = _
  201. page_nums = re.findall('\d+', page_text)
  202. if int(page_nums[0].strip()) == int(page_nums[1].strip()):
  203. break
  204. # 翻页
  205. can_use_button[2].click()
  206. # 确保翻页成功
  207. WebDriverWait(self.driver, 10).until(
  208. lambda x: page_text != page_text_element.text)
  209. sc_buttons = self.driver.find_elements_by_id('test_material_container_confirm')
  210. for _ in sc_buttons:
  211. if _.is_enabled() and _.is_displayed():
  212. _.click()
  213. info_key = list(info.keys())[0]
  214. info_v = info[info_key]
  215. if info_key == 'page':
  216. single_page_set()
  217. if info_key == 'multi_page':
  218. multi_page_set()
  219. if info_key == 'movie':
  220. movie_set()
  221. # 设置头部组件
  222. pass
  223. def set_page(self, page_link):
  224. # 设置图片模块
  225. self.driver.find_element_by_xpath('//*[@id="stage-sidebar"]/section/div[2]/div[1]/div/div').click()
  226. time.sleep(random.uniform(0.1, 0.2))
  227. file_name = re.split('\/', page_link)[-1]
  228. upload_elements = self.driver.find_elements_by_class_name('upload-img-item-inner-2gsg7NjaZ8')
  229. for _ in upload_elements:
  230. if _.is_displayed() and _.is_enabled():
  231. _.click()
  232. WebDriverWait(self.driver, 10).until(
  233. lambda x: len([_ for _ in self.driver.find_elements_by_class_name('title-29sncpKgTl') if
  234. _.is_displayed() and _.is_enabled()]) > 0)
  235. turn_page_buttons = self.driver.find_elements_by_class_name('paginationIcon-1EfoH0sNRF')
  236. can_use_button = []
  237. for _ in turn_page_buttons:
  238. if _.is_enabled() and _.is_displayed():
  239. can_use_button.append(_)
  240. # 不断翻页获取到元素为止
  241. chose_over = False
  242. while True:
  243. page_elements = self.driver.find_elements_by_class_name('title-29sncpKgTl')
  244. for _ in page_elements:
  245. if _.is_displayed() and _.is_enabled():
  246. if file_name in _.text:
  247. _.click()
  248. chose_over = True
  249. break
  250. if chose_over or len(can_use_button) == 0:
  251. # can_use_button 数量说明是否可以翻页,如果不可以翻页,则直接停止
  252. break
  253. # 翻到最后一页时停止
  254. page_text_elements = self.driver.find_elements_by_class_name('count_small-37CcvfzoTl')
  255. for _ in page_text_elements:
  256. if _.is_enabled() and _.is_displayed():
  257. page_text = _.text
  258. page_text_element = _
  259. page_nums = re.findall('\d+', page_text)
  260. if int(page_nums[0].strip()) == int(page_nums[1].strip()):
  261. break
  262. # 翻页
  263. can_use_button[2].click()
  264. # 确保翻页成功
  265. WebDriverWait(self.driver, 10).until(
  266. lambda x: page_text != page_text_element.text)
  267. sc_buttons = self.driver.find_elements_by_id('test_material_container_confirm')
  268. for _ in sc_buttons:
  269. if _.is_enabled() and _.is_displayed():
  270. _.click()
  271. try:
  272. WebDriverWait(self.driver, 4).until(
  273. lambda driver: driver.find_element_by_class_name(
  274. 'btnFist-uueBS6DQFa'))
  275. _ = self.driver.find_element_by_class_name(
  276. 'btnFist-uueBS6DQFa')
  277. WebDriverWait(self.driver, 4).until(
  278. lambda x: (_.is_displayed() and _.is_enabled()))
  279. # 已经出现但任需要等待
  280. time.sleep(1)
  281. _.click()
  282. WebDriverWait(self.driver, 100).until(
  283. lambda x: len([_ for _ in self.driver.find_elements_by_class_name('btn-3E823IXt3m') if
  284. _.is_displayed() and _.is_enabled()]) > 0)
  285. for _ in self.driver.find_elements_by_class_name('btn-3E823IXt3m'):
  286. if _.is_displayed() and _.is_enabled():
  287. _.click()
  288. except Exception as e:
  289. logging.info(e)
  290. logging.info('图片模块设置结束')
  291. def set_content(self, config_info):
  292. # TODO:长文本需要优化输入时间
  293. # 设置文本模块
  294. # 1.文本内容2.文本颜色3.是否加粗4.文本位置设置5.文本大小
  295. # 设置文本内容
  296. self.driver.find_element_by_xpath('//*[@id="stage-sidebar"]/section/div[2]/div[5]/div/div').click()
  297. time.sleep(random.uniform(0.2, 0.3))
  298. input_elements = self.driver.find_elements_by_xpath('//textarea[@class="adui-input-base"]')
  299. for _ in input_elements:
  300. if _.is_enabled() and _.is_displayed():
  301. _.send_keys(config_info['content'])
  302. # 设置颜色
  303. if config_info['color'] != '595959':
  304. color_buttons = self.driver.find_elements_by_class_name('adui-cp-picker')
  305. c_buttons_can_use = []
  306. for _ in color_buttons:
  307. if _.is_displayed() and _.is_enabled():
  308. c_buttons_can_use.append(_)
  309. c_buttons_can_use[1].click()
  310. time.sleep(random.uniform(0.2, 0.3))
  311. input_elements = self.driver.find_elements_by_tag_name('input')
  312. for _ in input_elements:
  313. if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '595959':
  314. _.click()
  315. _.send_keys(config_info['color'])
  316. # 设置是否加粗
  317. if config_info['is_bold']:
  318. big_elements = self.driver.find_elements_by_class_name('adui-button-content')
  319. for _ in big_elements:
  320. if _.text == '加粗' and _.is_displayed() and _.is_enabled():
  321. _.click()
  322. # 设置文本位置
  323. if config_info['loc'] != 'left':
  324. loc_buttons = self.driver.find_elements_by_xpath(
  325. "//div[contains(@class, 'adui-button-group_banner')]//button")
  326. loc_buttons_can_use = []
  327. for _ in loc_buttons:
  328. if _.is_enabled() and _.is_displayed():
  329. loc_buttons_can_use.append(_)
  330. if config_info['loc'] == 'middle':
  331. loc_buttons_can_use[1].click()
  332. if config_info['loc'] == 'right':
  333. loc_buttons_can_use[2].click()
  334. # 设置文本大小
  335. if config_info['str_num'] != 15:
  336. str_buttons = self.driver.find_elements_by_xpath("//*[@class='adui-select-selection-search']")
  337. str_buttons_can_use = []
  338. for _ in str_buttons:
  339. if _.is_displayed() and _.is_enabled():
  340. str_buttons_can_use.append(_)
  341. str_buttons_can_use[1].click()
  342. time.sleep(random.uniform(0.5, 1))
  343. str_num_buttons = self.driver.find_elements_by_xpath("//*[@class='adui-select-item-option-content']")
  344. str_num_can_use = []
  345. for _ in str_num_buttons:
  346. if _.is_displayed() and _.is_enabled():
  347. str_num_can_use.append(_)
  348. str_num_map = {14: 0, 16: 1, 18: 2, 20: 3, 24: 4, 36: 5}
  349. str_num_can_use[str_num_map[config_info['str_num']]].click()
  350. # 设置文本边距
  351. if config_info['str_distance'][0] != 22 or config_info['str_distance'][1] != 22:
  352. distance_buttons = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]')
  353. distance_buttons_can_use = []
  354. for _ in distance_buttons:
  355. if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '22':
  356. distance_buttons_can_use.append(_)
  357. distance_buttons_can_use[0].click()
  358. for i in range(4):
  359. distance_buttons_can_use[0].send_keys(Keys.BACKSPACE)
  360. distance_buttons_can_use[0].send_keys(config_info['str_distance'][0])
  361. distance_buttons_can_use[1].click()
  362. for i in range(4):
  363. distance_buttons_can_use[1].send_keys(Keys.BACKSPACE)
  364. distance_buttons_can_use[1].send_keys(config_info['str_distance'][1])
  365. def set_follow_button(self, button_type):
  366. # 设置关注按钮
  367. # 1.设置button文本内容2.是否加粗3.设置字体颜色,边框颜色,填充色4.设置边距
  368. self.driver.find_element_by_xpath('//*[@id="stage-sidebar"]/section/div[4]/div[2]/div/div').click()
  369. if button_type == 1:
  370. input_elements = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]')
  371. for _ in input_elements:
  372. if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '关注公众号':
  373. _.click()
  374. _.clear()
  375. for i in range(10):
  376. _.send_keys(Keys.BACKSPACE)
  377. _.send_keys('保存阅读记录')
  378. big_elements = self.driver.find_elements_by_xpath('//span[@class="adui-button-content"]')
  379. for _ in big_elements:
  380. if _.text == '加粗' and _.is_displayed() and _.is_enabled():
  381. _.click()
  382. input_elements = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]')
  383. for _ in input_elements:
  384. if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '07C160':
  385. _.click()
  386. _.send_keys('DE2821')
  387. if button_type == 2:
  388. input_elements = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]')
  389. for _ in input_elements:
  390. if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '关注公众号':
  391. _.click()
  392. _.clear()
  393. for i in range(10):
  394. _.send_keys(Keys.BACKSPACE)
  395. _.send_keys('点击此处,继续阅读')
  396. big_elements = self.driver.find_elements_by_xpath('//span[@class="adui-button-content"]')
  397. for _ in big_elements:
  398. if _.text == '加粗' and _.is_displayed() and _.is_enabled():
  399. _.click()
  400. input_elements = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]')
  401. for _ in input_elements:
  402. if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '07C160':
  403. _.click()
  404. _.send_keys('DE2821')
  405. size_buttons = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]')
  406. size_buttons_can_use = []
  407. for _ in size_buttons:
  408. if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '28':
  409. size_buttons_can_use.append(_)
  410. size_buttons_can_use[0].click()
  411. for i in range(4):
  412. size_buttons_can_use[0].send_keys(Keys.BACKSPACE)
  413. size_buttons_can_use[0].send_keys('0')
  414. size_buttons_can_use[1].click()
  415. for i in range(4):
  416. size_buttons_can_use[1].send_keys(Keys.BACKSPACE)
  417. size_buttons_can_use[1].send_keys('0')
  418. if button_type == 3:
  419. input_elements = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]')
  420. for _ in input_elements:
  421. if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '关注公众号':
  422. _.click()
  423. _.clear()
  424. for i in range(10):
  425. _.send_keys(Keys.BACKSPACE)
  426. _.send_keys('点我,继续阅读')
  427. big_elements = self.driver.find_elements_by_xpath('//span[@class="adui-button-content"]')
  428. for _ in big_elements:
  429. if _.text == '加粗' and _.is_displayed() and _.is_enabled():
  430. _.click()
  431. input_elements = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]')
  432. for _ in input_elements:
  433. if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '07C160':
  434. _.click()
  435. _.send_keys('FFFFFF')
  436. input_elements = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]')
  437. for _ in input_elements:
  438. if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == 'FFFFFF':
  439. _.click()
  440. _.send_keys('DE2821')
  441. break
  442. size_buttons = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]')
  443. size_buttons_can_use = []
  444. for _ in size_buttons:
  445. if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '28':
  446. size_buttons_can_use.append(_)
  447. size_buttons_can_use[0].click()
  448. for i in range(4):
  449. size_buttons_can_use[0].send_keys(Keys.BACKSPACE)
  450. size_buttons_can_use[0].send_keys('0')
  451. size_buttons_can_use[1].click()
  452. for i in range(4):
  453. size_buttons_can_use[1].send_keys(Keys.BACKSPACE)
  454. size_buttons_can_use[1].send_keys('100')
  455. def set_follow_button_(self, config_info):
  456. # 设置关注按钮
  457. # 1.设置button文本内容 2.是否加粗 3.设置字体颜色,边框颜色,填充色 4.设置边距
  458. self.driver.find_element_by_xpath('//*[@id="stage-sidebar"]/section/div[4]/div[2]/div/div').click()
  459. # 文本设置
  460. input_elements = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]')
  461. for _ in input_elements:
  462. if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '关注公众号':
  463. _.click()
  464. _.clear()
  465. for i in range(10):
  466. _.send_keys(Keys.BACKSPACE)
  467. _.send_keys(config_info['content'])
  468. # 文本是否加粗
  469. if config_info['is_bold']:
  470. big_elements = self.driver.find_elements_by_xpath('//span[@class="adui-button-content"]')
  471. for _ in big_elements:
  472. if _.text == '加粗' and _.is_displayed() and _.is_enabled():
  473. _.click()
  474. # 颜色设置
  475. input_elements = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]')
  476. input_elements_can_use = []
  477. for _ in input_elements:
  478. if _.is_enabled() and _.is_displayed() and (
  479. _.get_attribute("value") == '07C160' or _.get_attribute("value") == 'FFFFFF'):
  480. input_elements_can_use.append(_)
  481. input_elements_can_use[0].click()
  482. input_elements_can_use[0].send_keys(config_info['color1'])
  483. time.sleep(random.uniform(0.1, 0.5))
  484. input_elements_can_use[1].click()
  485. input_elements_can_use[1].send_keys(config_info['color2'])
  486. time.sleep(random.uniform(0.1, 0.5))
  487. input_elements_can_use[2].click()
  488. input_elements_can_use[2].send_keys(config_info['color3'])
  489. time.sleep(random.uniform(0.1, 0.5))
  490. # 间隙设置
  491. size_buttons = self.driver.find_elements_by_xpath('//input[@class="adui-input-base"]')
  492. size_buttons_can_use = []
  493. for _ in size_buttons:
  494. if _.is_enabled() and _.is_displayed() and _.get_attribute("value") == '28':
  495. size_buttons_can_use.append(_)
  496. size_buttons_can_use[0].click()
  497. for i in range(4):
  498. size_buttons_can_use[0].send_keys(Keys.BACKSPACE)
  499. size_buttons_can_use[0].send_keys(config_info['str_distance'][0])
  500. size_buttons_can_use[1].click()
  501. for i in range(4):
  502. size_buttons_can_use[1].send_keys(Keys.BACKSPACE)
  503. size_buttons_can_use[1].send_keys(config_info['str_distance'][1])
  504. def set_text_button(self):
  505. # 设置图文按钮
  506. pass
  507. def send_file_multi(self, layout, err_num=0):
  508. # 有问题,暂时不使用
  509. # 上传文件,文件上传与整体流程切割开
  510. token = re.findall('token=(\d+)', self.driver.current_url)
  511. url_ = 'https://mp.weixin.qq.com/promotion/frame?t=ad_system/common_frame&t1=material_std/material_library&token={}'.format(
  512. token[0])
  513. js = "window.open('{}')".format(url_)
  514. self.driver.execute_script(js)
  515. time.sleep(random.uniform(1, 2))
  516. self.driver.switch_to.window(self.driver.window_handles[-1])
  517. file_set = set()
  518. for v in layout.values():
  519. if isinstance(v, dict):
  520. if 'multi_page' in v.keys() or 'page' in v.keys() or 'movie' in v.keys():
  521. v_name = list(v.keys())[0]
  522. if isinstance(v[v_name], list):
  523. for _ in v[v_name]:
  524. file_set.add(_)
  525. else:
  526. file_set.add(v[v_name])
  527. file_list = list(file_set)
  528. # print(file_list)
  529. # print('file list size', len(file_list))
  530. send_file_sign = self.send_file_limit_num
  531. for _ in file_list:
  532. # print(_)
  533. self.driver.find_element_by_xpath('//*[@id="wxadcontainer"]/div[1]/div[2]/div[4]/input').send_keys(_)
  534. time.sleep(100)
  535. while True:
  536. # 失败,失败直接退出重跑
  537. # 正在上传数量,如果是正在上传小于限定数量,就不断输入
  538. # 上传完毕,小于限定数量,不断输入,.....已经上传好了,就关闭
  539. time.sleep(1)
  540. send_reslut_content = self.driver.find_element_by_xpath(
  541. '//*[@id="wxadcontainer"]/div[1]/div[2]/div[4]/div/strong').text
  542. if '失败' in send_reslut_content:
  543. if err_num < 3:
  544. self.send_file(layout, err_num=err_num + 1)
  545. else:
  546. exit()
  547. if '正在上传' in send_reslut_content:
  548. if send_file_sign < len(file_list):
  549. send_num = re.findall('(\d+)', send_reslut_content)[0]
  550. if int(send_num) < self.send_file_limit_num:
  551. # 还可以继续上传
  552. x = send_file_sign
  553. can_send_sign = send_file_sign + (self.send_file_limit_num - send_num)
  554. y = can_send_sign if can_send_sign < len(file_list) else len(file_list)
  555. for i in range(x, y):
  556. send_file_sign = send_file_sign + 1
  557. self.driver.find_element_by_xpath(
  558. '//*[@id="wxadcontainer"]/div[1]/div[2]/div[4]/input').send_keys(file_list[i])
  559. else:
  560. pass
  561. if '上传成功' in send_reslut_content:
  562. if send_file_sign < len(file_list):
  563. send_num = re.findall('(\d+)', send_reslut_content)[0]
  564. if int(send_num) < self.send_file_limit_num:
  565. # 还可以继续上传
  566. x = send_file_sign
  567. can_send_sign = send_file_sign + (self.send_file_limit_num - send_num)
  568. y = can_send_sign if can_send_sign < len(file_list) else len(file_list)
  569. for i in range(x, y):
  570. send_file_sign = send_file_sign + 1
  571. self.driver.find_element_by_xpath(
  572. '//*[@id="wxadcontainer"]/div[1]/div[2]/div[4]/input').send_keys(file_list[i])
  573. else:
  574. break
  575. time.sleep(1000)
  576. self.driver.execute_script('window.close();')
  577. def send_file(self, file_link, err_num=0):
  578. # 下载图片,存储于
  579. if not os.path.exists(self.img_dir):
  580. os.makedirs(self.img_dir)
  581. link_pra = re.split('\/', file_link)
  582. file_path = os.getcwd() + '/' + self.img_dir + '/' + link_pra[-1]
  583. rsp = requests.get(file_link)
  584. with open(file_path, 'wb') as f:
  585. f.write(rsp.content)
  586. # 有问题,暂时不使用
  587. self.driver.execute_script('location.reload();')
  588. self.driver.find_element_by_xpath('//*[@id="wxadcontainer"]/div[1]/div[2]/div[4]/input').send_keys(file_path)
  589. def send_file_alone(self, layout):
  590. # 上传文件,单线程
  591. # 上传文件,文件上传与整体流程切割开
  592. WebDriverWait(self.driver, 10).until(
  593. lambda x: len(re.findall('token=(\d+)', self.driver.current_url)))
  594. token = re.findall('token=(\d+)', self.driver.current_url)
  595. url_ = 'https://mp.weixin.qq.com/promotion/frame?t=ad_system/common_frame&t1=material_std/material_library&token={}'.format(
  596. token[0])
  597. js = "window.open('{}')".format(url_)
  598. self.driver.execute_script(js)
  599. time.sleep(random.uniform(1, 2))
  600. self.driver.switch_to.window(self.driver.window_handles[-1])
  601. file_set = set()
  602. for v in layout.values():
  603. if isinstance(v, dict):
  604. if 'multi_page' in v.keys() or 'page' in v.keys() or 'movie' in v.keys():
  605. v_name = list(v.keys())[0]
  606. if isinstance(v[v_name], list):
  607. for _ in v[v_name]:
  608. file_set.add(_)
  609. else:
  610. file_set.add(v[v_name])
  611. for _ in file_set:
  612. self.send_file(_)
  613. err_num = 0
  614. while True:
  615. time.sleep(1)
  616. send_reslut_content = self.driver.find_element_by_xpath(
  617. '//*[@id="wxadcontainer"]/div[1]/div[2]/div[4]/div/strong').text
  618. if '上传成功' in send_reslut_content:
  619. break
  620. if '失败' in send_reslut_content:
  621. err_num = err_num + 1
  622. self.send_file(_)
  623. if err_num > 3:
  624. raise ValueError("图片上传失败")
  625. self.driver.execute_script('window.close();')
  626. self.driver.switch_to.window(self.driver.window_handles[-1])
  627. def set_share_content(self, share_info):
  628. title_content = share_info['share_info']['title']
  629. des_content = share_info['share_info']['des']
  630. self.driver.find_element_by_xpath('//*[@id="wxadcontainer"]/div[1]/div/section/header/div[2]/button[2]').click()
  631. WebDriverWait(self.driver, 50).until(lambda driver: driver.find_element_by_xpath(
  632. '//*[@id="wxadcontainer"]/div[1]/div/div/div/div[1]/section/section/div[2]/div[1]/div/div/input'))
  633. title_input = self.driver.find_element_by_xpath(
  634. '//*[@id="wxadcontainer"]/div[1]/div/div/div/div[1]/section/section/div[2]/div[1]/div/div/input')
  635. title_input.click()
  636. title_input.send_keys(title_content)
  637. des_input = self.driver.find_element_by_xpath(
  638. '//*[@id="wxadcontainer"]/div[1]/div/div/div/div[1]/section/section/div[2]/div[2]/div/div/input')
  639. des_input.click()
  640. des_input.send_keys(des_content)
  641. self.driver.find_element_by_xpath('//*[@id="wxadcontainer"]/div[1]/div/header/div[2]/button').click()
  642. WebDriverWait(self.driver, 10).until(
  643. lambda driver: driver.find_element_by_xpath('/html/body/div[6]/div/div/div[2]/div/div[3]/button[2]'))
  644. self.driver.find_element_by_xpath('/html/body/div[6]/div/div/div[2]/div/div[3]/button[2]').click()
  645. time.sleep(1)
  646. def check_sucess(self, layout_name):
  647. # 进入素材中心
  648. WebDriverWait(self.driver, 100).until(
  649. lambda x: self.driver.find_element_by_id('material'))
  650. self.driver.find_element_by_id('material').click()
  651. # 输入--落地页名字
  652. input_element = self.driver.find_element_by_xpath('//*[@class="adui-input-base"]')
  653. input_element.send_keys(layout_name)
  654. time.sleep(random.uniform(0.5, 0.6))
  655. input_element.send_keys(Keys.RETURN)
  656. # TODO:有空去除掉时间
  657. time.sleep(random.uniform(3, 5))
  658. # 查询有无
  659. result = self.driver.find_elements_by_xpath('//*[@class="namelink-1V-GPp_906"]')
  660. print('结果', len(result))
  661. if len(result):
  662. return True
  663. def remove_all_file(self):
  664. shutil.rmtree(os.getcwd() + '/' + self.img_dir)
  665. pass
  666. def create_layout(self, layout, err_num=0):
  667. #
  668. try:
  669. self.send_file_alone(layout)
  670. self.set_advertisement_sign(layout_name=layout[-4]['layout_name'])
  671. self.set_head_assemb(layout[str(-1)])
  672. if -2 in layout.keys():
  673. self.set_background_color()
  674. for _ in range(max([int(x) for x in layout.keys()]) + 1):
  675. info = layout[str(_)]
  676. info_key = list(info.keys())[0]
  677. info_v = info[info_key]
  678. if info_key == 'page':
  679. self.set_page(info_v)
  680. if info_key == 'content':
  681. self.set_content(info_v)
  682. if info_key == 'follow_button':
  683. self.set_follow_button_(info_v)
  684. self.set_share_content(layout[str(-3)])
  685. self.remove_all_file()
  686. if self.check_sucess(layout_name=layout[-4]['layout_name']):
  687. return {'sucess': True, 'result_info': ''}
  688. else:
  689. if err_num > 3:
  690. return {'sucess': False, 'result_info': '过程中全程无错误,失败'}
  691. else:
  692. self.log_ad.refresh_driver()
  693. self.log_ad.select_ad_master(service_name=self.service_name, wechat_name=self.wechat_name)
  694. self.get_into_create_page()
  695. return self.create_layout(layout, err_num=err_num + 1)
  696. except Exception as e:
  697. raise
  698. # TODO:有空时讲 e 内容设置为原始内容
  699. if err_num > 3:
  700. return {'sucess': False, 'result_info': str(e)}
  701. else:
  702. self.log_ad.refresh_driver()
  703. self.log_ad.select_ad_master(service_name=self.service_name, wechat_name=self.wechat_name)
  704. self.get_into_create_page()
  705. return self.create_layout(layout, err_num=err_num + 1)
  706. if __name__ == '__main__':
  707. logging.basicConfig(
  708. handlers=[
  709. logging.handlers.RotatingFileHandler('./create_ad_layout.log',
  710. maxBytes=10 * 1024 * 1024,
  711. backupCount=5,
  712. encoding='utf-8')
  713. , logging.StreamHandler() # 供输出使用
  714. ],
  715. level=logging.INFO,
  716. format="%(asctime)s - %(levelname)s %(filename)s %(funcName)s %(lineno)s - %(message)s"
  717. )