Quellcode durchsuchen

ADD:添加数据库部分,dingtalk部分

cxyu vor 4 Jahren
Ursprung
Commit
3fc3cbf2bc

+ 83 - 0
communication_tools/dingtalk.py

@@ -0,0 +1,83 @@
+import json
+import time
+import hmac
+import hashlib
+import base64
+import requests
+import urllib.parse
+import logging
+from settings import ding_talk
+import re
+import socket
+
+
+def intranet_ip():
+    try:
+        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        s.connect(('8.8.8.8', 80))
+        ip = s.getsockname()[0]
+    finally:
+        s.close()
+    return str(ip)
+
+
+def web_ip():
+    response = requests.get('http://ip.tool.chinaz.com/')
+    ips = re.findall('\d+\.\d+\.\d+\.\d+', response.text)
+    if len(ips) > 0:
+        return ips[0]
+    else:
+        return None
+
+
+def sign_dingtalk():
+    timestamp = round(time.time() * 1000)
+    secret = ding_talk['secret_sign']
+    secret_enc = bytes(secret, 'utf-8')
+    string_to_sign = '{}\n{}'.format(timestamp, secret)
+    string_to_sign_enc = bytes(string_to_sign, 'utf-8')
+    hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
+    sign = urllib.parse.quote(base64.b64encode(hmac_code))
+    return timestamp, sign
+
+
+def send_message(content, atsombody=None, is_self=True, is_carryip=False):
+    '''
+    :param content:发送文本
+    :param atsombody: [
+                "156xxxx8827",
+                "151XXX2316"
+            ]
+    :param is_self:
+    :return:
+    '''
+    try:
+        base_url = 'https://oapi.dingtalk.com/robot/send?access_token=dc19e91491341b81f29d7fc347071647031e3d33d8df73f15e4529ad01520e22'
+        timestamp, sign = sign_dingtalk()
+        url = base_url + "&timestamp={timestamp}&sign={sign}".format(timestamp=timestamp, sign=sign)
+        if is_carryip:
+            ip_intranet = intranet_ip()
+            ip_public = web_ip()
+            ip_content = '内网ip {} ,公网ip {}'.format(ip_intranet, ip_public)
+            content = content + '\n' + ip_content
+        data = {
+            "msgtype": "text",
+            "text": {
+                "content": content[:10000]
+            },
+            "at": {
+                "atMobiles": [atsombody],
+                "isAtAll": False
+            }
+        }
+        headers = {'content-type': 'application/json'}  # 请求头
+        time.sleep(1)
+        response = requests.post(url=url, headers=headers, data=json.dumps(data))
+        if response.json()['errcode'] == 0:
+            logging.info('钉钉信息:{} 发送成功'.format(content))
+        else:
+            time.sleep(10)
+            logging.warning('钉钉信息出现问题:{}'.format(str(response.text)))
+    except Exception as e:
+        logging.error('钉钉发消息发生问题 error:{} ')
+        time.sleep(10)

+ 103 - 43
wechat_action/create_ad.py

@@ -1,24 +1,30 @@
-from wechat_action.login_ad import LogIn
-from selenium import webdriver
-from selenium.webdriver import ActionChains
-from selenium.webdriver.common.by import By
-from selenium.webdriver.support import expected_conditions as EC
+from wechat_action.sql_tools import save_ad_layout_result
 from selenium.webdriver.support.wait import WebDriverWait
-from selenium.webdriver import ChromeOptions
 from selenium.webdriver.common.keys import Keys
+from selenium.webdriver import ActionChains
+from sqlalchemy import Table
+from logging import handlers
 import logging
-import time
 import random
+import time
+import json
 import re
 import os
-from logging import handlers
 
 
 class CreateAd:
-    def __init__(self, service_name, wechat_name):
-        # TODO:创建完页面需要关闭所有页面并回到一开始的页面
-        self.driver = LogIn(service_name, wechat_name).get_driver_loged()
+    def __init__(self, login_ad, layout_db, user_id):
+        self.user_id = user_id
+        self.service_name = login_ad.service_name
+        self.wechat_name = login_ad.wechat_name
+        # self.driver = LogIn(service_name, wechat_name).get_driver_loged()
+        self.driver = login_ad.get_driver_loged()
         self.get_into_create_page()
+        self.db = layout_db
+        self.metadata = self.db.metadata
+        self.sql_session = self.db.DBSession()
+        self.layout_table = Table('layout_record', self.metadata,
+                                  autoload=True, autoload_with=self.db.engine)
         self.send_file_limit_num = 8
 
     def get_into_create_page(self):
@@ -36,7 +42,7 @@ class CreateAd:
         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'))
 
-    def create_layout(self):
+    def get_layout(self):
         # 数据库获取数据,然后进行编排
         # 创建编排
         pass
@@ -168,19 +174,18 @@ class CreateAd:
                 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(1, 2))
+                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(1, 4))
-
+                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()
-            time.sleep(random.uniform(2, 4))
+
             # 切图操作如果有的话进行对应操作.
             for i in range(len(info_v) + 1):
                 try:
-                    WebDriverWait(self.driver, 4).until(
+                    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()
@@ -379,7 +384,7 @@ class CreateAd:
                 if _.is_displayed() and _.is_enabled():
                     str_buttons_can_use.append(_)
             str_buttons_can_use[1].click()
-            time.sleep(random.uniform(1, 3))
+            time.sleep(random.uniform(0.5, 1))
 
             str_num_buttons = self.driver.find_elements_by_xpath("//*[@class='adui-select-dropdown-menu-item']")
             str_num_can_use = []
@@ -669,36 +674,91 @@ class CreateAd:
                     err_num = err_num + 1
                     self.send_file(_)
                     if err_num > 3:
-                        # TODO:退出机制需要考虑一下,tornado返回错误信息
-                        exit()
+                        raise ValueError("图片上传失败")
 
         self.driver.execute_script('window.close();')
         self.driver.switch_to.window(self.driver.window_handles[-1])
 
-    def set_share_content(self):
-        # TODO:设置分享标题,文本
-        pass
+    def set_share_content(self, share_info):
+        title_content = share_info['share_info']['title']
+        des_content = share_info['share_info']['des']
+        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)
 
-    def get_layout(self, layout):
-        # TODO:设置重试机制,然后错误后试错几次,查看是否成功
-        self.send_file_alone(layout)
-        advertisement_sign = self.set_advertisement_sign()
-        self.set_head_assemb(layout[-1])
-        if -2 in layout.keys():
-            self.set_background_color()
-
-        for _ in range(max(layout.keys()) + 1):
-            info = layout[_]
-            info_key = list(info.keys())[0]
-            info_v = info[info_key]
-            if info_key == 'page':
-                self.set_page(info_v)
-            if info_key == 'content':
-                self.set_content(info_v)
-            if info_key == 'follow_button':
-                self.set_follow_button_(info_v)
-        time.sleep(100)
-        return advertisement_sign
+    def create_layout(self, layout, err_num=0):
+        #
+        try:
+            self.send_file_alone(layout)
+            advertisement_sign = self.set_advertisement_sign()
+            self.set_head_assemb(layout[-1])
+            if -2 in layout.keys():
+                self.set_background_color()
+
+            for _ in range(max(layout.keys()) + 1):
+                info = layout[_]
+                info_key = list(info.keys())[0]
+                info_v = info[info_key]
+                if info_key == 'page':
+                    self.set_page(info_v)
+                if info_key == 'content':
+                    self.set_content(info_v)
+                if info_key == 'follow_button':
+                    self.set_follow_button_(info_v)
+
+            self.set_share_content(layout[-3])
+            self.driver.execute_script('window.close();')
+            # 切回到前一页
+            self.driver.switch_to.window(self.driver.window_handles[-1])
+            layout_info = {}
+            layout_info['id'] = int(time.time() * 1000)
+            layout_info['userid'] = self.user_id
+            layout_info['result'] = 'sucess'
+            layout_info['layout'] = json.dumps(layout, ensure_ascii=False)
+
+            layout_insert = save_ad_layout_result(layout_info=layout_info, table_layout=self.layout_table)
+            self.sql_session.execute(layout_insert)
+            self.sql_session.commit()
+
+            return {'sucess': True, 'result_info': advertisement_sign}
+        except Exception as e:
+
+            if err_num > 3:
+                layout_num = int(time.time() * 1000)
+                now_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
+                try:
+                    self.driver.save_screenshot('{layout_num}-{now_time}-{service_name}-{wechat_name}.png'.format(
+                        layout_num=layout_num,
+                        now_time=now_time,
+                        service_name=self.service_name,
+                        wechat_name=self.wechat_name))
+                except:
+                    pass
+                layout_info = {}
+                layout_info['id'] = layout_num
+                layout_info['userid'] = self.user_id
+                layout_info['result'] = str(e)
+                layout_info['layout'] = json.dumps(layout)
+                layout_insert = save_ad_layout_result(layout_info=layout_info, table_layout=self.layout_table)
+                self.sql_session.execute(layout_insert)
+                self.sql_session.commit()
+                # 截图,传回错误信息
+                return {'sucess': False, 'result_info': e}
+            else:
+                self.create_layout(layout, err_num=err_num + 1)
 
 
 if __name__ == '__main__':

+ 11 - 2
wechat_action/login_ad.py

@@ -33,7 +33,6 @@ class LogIn:
 
     def log_in(self):
         self.driver.get('https://a.weixin.qq.com/index.html')
-        self.driver.save_screenshot('wechat_page_start.png')
 
         img_selector = 'body > div.old-template > div > div > div.waiting.panelContent > div.wrp_code > img'
         'body > div.old-template > div > div > div.waiting.panelContent > div.wrp_code > img'
@@ -44,7 +43,6 @@ class LogIn:
         img_url = self.driver.find_element_by_css_selector(img_selector)
         print('img', img_url.get_attribute('src'))
         WebDriverWait(self.driver, 100).until(lambda driver: driver.find_elements_by_link_text('广告投放'))
-        self.driver.save_screenshot('get_in_page.png')
 
     def select_ad_master(self):
         self.driver.execute_script('''
@@ -84,3 +82,14 @@ class LogIn:
 
     def get_driver_loged(self):
         return self.driver
+
+    def refresh_driver(self):
+        while True:
+            if len(self.driver.window_handles)>1:
+                self.driver.switch_to.window(self.driver.window_handles[-1])
+                self.driver.execute_script('window.close();')
+                time.sleep(0.1)
+            else:
+                self.driver.switch_to.window(self.driver.window_handles[-1])
+                self.driver.get('https://a.weixin.qq.com/client')
+                break

+ 31 - 0
wechat_action/sql_models.py

@@ -0,0 +1,31 @@
+from sqlalchemy import create_engine, MetaData
+from sqlalchemy.orm import sessionmaker, scoped_session
+from settings import using_config
+
+
+class DB():
+    def __init__(self, config=None):
+        self.config = using_config if not config else config
+        self.engine = self.DBengine()
+        self.session = self.DBSession()
+        self.metadata = MetaData(self.engine)
+
+    def DBengine(self):
+        # 初始化数据库连接:
+        db_uri = 'mysql+pymysql://' \
+                 '{username}:{password}@{host}:{port}/{database}'.format(username=self.config['username'],
+                                                                         password=self.config['password'],
+                                                                         host=self.config['host'],
+                                                                         port=self.config['port'],
+                                                                         database=self.config['database'])
+
+        engine = create_engine(db_uri, pool_size=1024, pool_recycle=1800,
+                               pool_pre_ping=True, max_overflow=100, echo=False)
+        return engine
+
+    def DBSession(self):
+        # 创建DBSession类型:
+        session_factory = sessionmaker(bind=self.engine)
+        DBSession = scoped_session(session_factory)
+        DBSession = DBSession()
+        return DBSession

+ 8 - 0
wechat_action/sql_tools.py

@@ -0,0 +1,8 @@
+def save_ad_layout_result(layout_info, table_layout):
+    insert_layout = table_layout.insert()
+    insert_layout = insert_layout.values \
+        (id=layout_info['id'],
+         userid=layout_info['userid'],
+         result=layout_info['result'],
+         layout=layout_info['layout'])
+    return insert_layout