Parcourir la source

ADD:后台模式 version:1

cxyu il y a 4 ans
Parent
commit
92f6a89aa2

+ 146 - 42
web_module/tornado_api.py

@@ -3,56 +3,78 @@ from settings import using_config
 import tornado.ioloop
 import tornado.web
 import json
+from wechat_api.get_wechat_info import WechatApi
+from wechat_action.login_ad import LogIn
 from wechat_action import sql_tools
+import threading
+from web_module import user_action
+from sqlalchemy import Table
+import pickle
+
 # TODO:需要添加上supervisor,来维护进程
 # TODO:有时间需要对tornado进行改进
 
 
 db = DB(config=using_config)
+wechat_cookies_table = Table('wechat_cookies', db.metadata,
+                             autoload=True, autoload_with=db.engine)
+layout_typesetting_table = Table('layout_typesetting', db.metadata,
+                                 autoload=True, autoload_with=db.engine)
 
 
 # 1.实现本机服务
 # 2.实现线上docker-selenium服务
 
-class login(tornado.web.RequestHandler):
-    # 0.登录,
-    #   1.成功---
-    #   2.不超过,返回一个二维码
-    def get(self):
-        self.write("Hello, world")
-
-    def post(self):
-        # 利用request属性
-        # 取出客户端提交的json字符串
-        jsonbyte = self.request.body
-        print('二进制格式json字符串:', jsonbyte)
-        jsonstr = jsonbyte.decode('utf8')  # 解码,二进制转为字符串
-        print('json字符串:', jsonstr)
-
-        # 从json字符串转换为json对象,然后利用json对象提供的api
-        # 从json字符串中取出我想要的内容(解析json字符串)
-        jsonobj = json.loads(jsonstr)  # 将字符串转为json对象
-        day = jsonobj.get('day')  # 就可以用api取值
-        title = jsonobj.get('title')
-        print('day: ', day, ', title: ', title)
 
-        self.write('hello post')
-
-
-class create_ad_plan(tornado.web.RequestHandler):
+class create_ad_plan_remote(tornado.web.RequestHandler):
     # 1.批量创建计划
     # 返回创建计划是否已经开始
+    def get(self):
+        pass
+
     def post(self):
         # 1.
         pass
 
 
-class create_ad_show(tornado.web.RequestHandler):
+class create_ad_layout_remote(tornado.web.RequestHandler):
     # 1.批量创建落地页
+    def post(self):
+        user_id = self.get_argument("user_id", None)
+        layout_name = self.get_argument("layout_name", None)
+        # wechat_json :[{'service_name':'one','wechat_name':''},{'service_name':'','wechat_name':''}]
+        wechat_json = self.get_argument('wechat_json', None)
+        log_ad, cookie_canuse = ad_human_info.refresh_wechat_cookies(self, user_id=user_id)
+        threading.Thread(target=user_action.create_layout,
+                         args=(user_id, layout_name, wechat_json, log_ad, db, cookie_canuse)).start()
+
+
+class create_ad_layout_local(tornado.web.RequestHandler):
+    def post(self):
+        user_id = self.get_argument("user_id", None)
+        layout_typesetting = self.get_argument("layout_typesetting", None)
+        layout_name = self.get_argument("layout_name", None)
+        print(user_id, layout_typesetting, layout_name)
+        sql_session = db.DBSession()
+        if user_id is None or layout_name is None or layout_typesetting is None:
+            self.write(json.dumps({'status': {'msg': 'url parameter error', "RetCode": 400}}))
+            return
+        # 落地页名字精确到毫秒,默认是全局唯一
+        # TODO:检查一下layout--内容 有无问题-----和前端确定一下
+
+        layout_typesetting_info = {'user_id': user_id, 'name': layout_name, 'typesetting': layout_typesetting}
+        layout_typesetting_inserte = sql_tools.save_layout_typesetting_info(
+            layout_typesetting_info=layout_typesetting_info,
+            table_layout_typesetting=layout_typesetting_table)
+        sql_session.execute(layout_typesetting_inserte)
+        sql_session.commit()
+        self.write(json.dumps({'status': {'msg': 'success', "RetCode": 200}}, ensure_ascii=False))
+
+
+class create_ad_plan_local(tornado.web.RequestHandler):
     pass
 
 
-# TODO:数据库创建一批虚拟数据,供明天测试使用起
 # TODO:wechat_info,human_info 这两张表有空时需要进行对应改进
 class ad_status(tornado.web.RequestHandler):
     # 1.创建情况
@@ -60,16 +82,61 @@ class ad_status(tornado.web.RequestHandler):
 
 
 class ad_human_info(tornado.web.RequestHandler):
+
+    @staticmethod
+    def refresh_wechat_cookies(tornado_web, user_id):
+        # 1.返回二维码链接
+        # ----1.查看cookie是否可用
+        sql_session = db.DBSession()
+        cookie_db = sql_tools.get_wechat_cookies(sql_session, user_id=user_id)
+
+        # 进行登录操作
+        log_ad = LogIn()
+
+        # 使driver可以使用
+        cookie_canuse = False
+        if cookie_db:
+            cookie_db = pickle.loads(cookie_db)
+
+            # TODO:log 日志需要进行对应配置
+            if not log_ad.wechat_cookies_check_alive(cookie_db):
+                # cookie 不能使用
+                wechat_code = log_ad.log_in()
+                tornado_web.write(json.dumps({'status': {'msg': 'success', "RetCode": 200},
+                                              'wechat_code': wechat_code}))
+                print('cookie can not use')
+            else:
+                # cookie 可以继续使用
+                cookie_canuse = True
+                log_ad.driver.get('https://a.weixin.qq.com/index.html')
+                tornado_web.write(json.dumps({'status': {'msg': 'success', "RetCode": 200}}))
+        else:
+            # cookie 不能使用
+            wechat_code = log_ad.log_in()
+            tornado_web.write(json.dumps({'status': {'msg': 'success', "RetCode": 200},
+                                          'wechat_code': wechat_code}))
+        return log_ad, cookie_canuse
+
     # 1.人群包获取
     def get(self):
+        # TODO:添加分页
+
         # 0.是否刷新
         # 1.获取userid,以及是否刷新
         user_id = self.get_argument("user_id", None)
         is_refresh = self.get_argument("is_refresh", None)
-        if is_refresh:
-            # 1.返回二维码链接
-            # ----1.查看cookie是否可用
-            pass
+        print(user_id, is_refresh)
+        if user_id is None or is_refresh is None:
+            self.write(json.dumps({'status': {'msg': 'url parameter error', "RetCode": 400}}))
+            return
+        sql_session = db.DBSession()
+        # TODO:一个涉及到selenium-driver的请求-生命周期.----看一下tornado是怎么处理请求的生命周期
+        if int(is_refresh) == 1:
+            log_ad, cookie_canuse = self.refresh_wechat_cookies(self, user_id=user_id)
+            threading.Thread(target=user_action.get_human_info,
+                             args=(
+                                 user_id, log_ad, db, cookie_canuse)).start()
+
         else:
             # 1.查看是否在刷新,
             #     在刷新中,
@@ -79,25 +146,62 @@ class ad_human_info(tornado.web.RequestHandler):
             #     不在刷新
             #       返回对应数据
             # 2.获取userid对应数据
-            sql_session = db.DBSession()
-            sql_tools.get_human_info(sql_session=sql_session,user_id=user_id)
-
-
-
-        pass
+            result = sql_tools.get_human_info(sql_session=sql_session, user_id=user_id)
+            result = [json.loads(x) for x in result]
+            print(result)
+            self.write(json.dumps({'status': {'msg': 'success', "RetCode": 200},
+                                   'human_info': result}, ensure_ascii=False))
 
 
-class ad_wechat_info():
+class ad_wechat_info(tornado.web.RequestHandler):
     # 1.公众号相关信息获取
     def get(self):
-        pass
+        # TODO:添加分页
+
+        # 0.是否刷新
+        # 1.获取userid,以及是否刷新
+        user_id = self.get_argument("user_id", None)
+        is_refresh = self.get_argument("is_refresh", None)
+        print(user_id, is_refresh)
+        if user_id is None or is_refresh is None:
+            self.write(json.dumps({'status': {'msg': 'url parameter error', "RetCode": 400}}))
+            return
+        sql_session = db.DBSession()
+        # TODO:一个涉及到selenium-driver的请求-生命周期.----看一下tornado是怎么处理请求的生命周期
+        if int(is_refresh) == 1:
+            log_ad, cookie_canuse = ad_human_info.refresh_wechat_cookies(self, user_id=user_id)
+            threading.Thread(target=user_action.get_human_info,
+                             args=(
+                                 user_id, log_ad, db, cookie_canuse)).start()
+        else:
+            # 1.查看是否在刷新,
+            #     在刷新中,
+            #       返回正在刷新
+
+            # -------不管上面逻辑让他们多刷新几次
+            #     不在刷新
+            #       返回对应数据
+            # 2.获取userid对应数据
+            result = sql_tools.get_wechat_info(sql_session=sql_session, user_id=user_id)
+            result_list = []
+            for _ in result:
+                service_name, wechat_name = _
+                result_list.append({'service_name': service_name, 'wechat_name': wechat_name})
+            print(result_list)
+            self.write(json.dumps({'status': {'msg': 'success', "RetCode": 200},
+                                   'wechat_info': result_list}, ensure_ascii=False))
 
 
 def make_app():
     return tornado.web.Application([
-        (r"/create_ad_plan", create_ad_plan),
-        (r"/create_ad_show", create_ad_show),
-    ], debug=True)
+        ("/create_ad_plan_local", create_ad_plan_local),
+        ("/create_ad_layout_local", create_ad_layout_local),
+        ("/create_ad_plan_remote", create_ad_plan_remote),
+        ("/create_ad_layout_remote", create_ad_layout_remote),
+        ("/ad_human_info", ad_human_info),
+        ("/ad_wechat_info", ad_wechat_info),
+        ("/ad_status", ad_status)
+    ], debug=True, autoreload=True)
 
 
 if __name__ == "__main__":

+ 193 - 0
web_module/user_action.py

@@ -0,0 +1,193 @@
+from wechat_action.sql_tools import save_wechat_cookies, save_human_info, delete_wechat_info, save_wechat_info
+from wechat_api.get_wechat_info import WechatApi
+from wechat_action.create_ad import CreateAd
+from wechat_action import sql_tools
+from sqlalchemy import Table
+import json
+import time
+
+
+def run(user_id, log_ad, db, cookie_canuse):
+    sql_session = db.DBSession()
+    # 检查是否有已经开启的任务
+    result = sql_tools.get_action_status(sql_session, user_id)
+    # 有:    只将任务进行添加操作todo
+    if result:
+        action_info = {'user_id': user_id, 'service_name': ''}
+
+        sql_tools.save_action_record()
+    # 无:    任务添加到数据库中doing
+
+    # 检查是否需要登录
+    # 任务开始
+    # 任务中间添加的----不断循环获取同userid,----doing,error,todo状态任务
+
+    # 关闭driver
+
+
+def cookie_acion(db, log_ad, cookie_canuse, user_id):
+    wechat_cookies_table = Table('wechat_cookies', db.metadata,
+                                 autoload=True, autoload_with=db.engine)
+    sql_session = db.DBSession()
+    # 等待页面加载完成
+    log_ad.log_in_wait()
+    # 1.保存cookie,
+    if not cookie_canuse:
+        wechat_cookies = log_ad.wechat_cookie_pickle()
+
+        update_res = wechat_cookies_table.update() \
+            .where(wechat_cookies_table.c.user_id == user_id) \
+            .values(cookies=wechat_cookies)
+        update_res = sql_session.execute(update_res)
+        sql_session.commit()
+        if update_res.rowcount == 0:
+            wechat_cookies_info = {'user_id': user_id, 'cookies': wechat_cookies}
+            wechat_insert = save_wechat_cookies(wechat_cookies_info=wechat_cookies_info,
+                                                table_wechat_cookies=wechat_cookies_table)
+
+            sql_session.execute(wechat_insert)
+            sql_session.commit()
+        print('update wechat cookies')
+
+
+# TODO:这里都是线程调度的函数,设定线程生命周期最长60分钟
+
+def get_human_info(user_id, log_ad, db, cookie_canuse):
+    # 数据库
+    human_info_table = Table('human_info', db.metadata,
+                             autoload=True, autoload_with=db.engine)
+    wechat_info_table = Table('wechat_info', db.metadata,
+                              autoload=True, autoload_with=db.engine)
+    sql_session = db.DBSession()
+
+    # TODO:log_ad 在这个线程结束之后并没有自动关闭,需要设置一下log_ad这个类删除,
+    #   然后看一下多次请求之后,线程数量,
+
+    # 1.cookies保存
+    cookie_acion(db, log_ad, cookie_canuse, user_id)
+    # 2.刷新人群包
+
+    # 3.刷新微信 公众号 分层 信息
+
+    # wechat_info.每次都删除掉前面全部数据,进行更新
+    # human_info 进行全局更新
+    w_api = WechatApi(log_ad=log_ad)
+    res_list = w_api.get_human_info()
+
+    # human info 相关数据进行更新
+    for _ in res_list:
+        service_name = _['service_name']
+        wechat_name = _['wechat_name']
+        human_info = _['data']['list']
+
+        update_res = human_info_table.update() \
+            .where(human_info_table.c.service_name == service_name) \
+            .where(human_info_table.c.wechat_name == wechat_name) \
+            .values(human_info=human_info)
+        update_res = sql_session.execute(update_res)
+        sql_session.commit()
+        if update_res.rowcount == 0:
+            human_info = {'service_name': service_name, 'wechat_name': wechat_name, 'human_info': human_info}
+            human_insert = save_human_info(human_info=human_info,
+                                           table_human=human_info_table)
+
+            sql_session.execute(human_insert)
+            sql_session.commit()
+        print('update human info')
+
+    # wechat info进行数据更新
+    # 1.删除所有数据
+    delete_wechat_info(sql_session=sql_session, user_id=user_id)
+    # 2.重新添加一遍相关数据
+    for _ in res_list:
+        service_name = _['service_name']
+        wechat_name = _['wechat_name']
+        wechat_info = {'service_name': service_name, 'wechat_name': wechat_name, 'user_id': user_id}
+        wechat_insert = save_wechat_info(wechat_info=wechat_info,
+                                         table_wechat=wechat_info_table)
+
+        sql_session.execute(wechat_insert)
+        sql_session.commit()
+    print('update wechat info')
+    # 浏览器关闭
+    log_ad.driver.close()
+
+
+def create_layout(user_id, layout_name, wechat_json, log_ad, db, cookie_canuse):
+    # TODO:
+    #  1.任务有不断中途新增,该如何操作.------只管
+    #  2.落地页创建一半失败了怎么办
+    #  4.cookie记录每次刷新都会失效,需要改进
+
+    action_record_table = Table('action_record', db.metadata,
+                                autoload=True, autoload_with=db.engine)
+    sql_session = db.DBSession()
+    # 等待页面加载完成
+
+    # 1.cookies保存
+    cookie_acion(db, log_ad, cookie_canuse, user_id)
+
+    # 获取到对应layout
+    typesetting_json = sql_tools.get_layout_typesetting(sql_session=sql_session, user_id=user_id,
+                                                        typesetting_name=layout_name)
+    if not typesetting_json:
+        return
+    print(typesetting_json)
+    typesetting_dict = json.loads(typesetting_json)
+    # action 进行对应记录
+    wechat_json = json.loads(wechat_json)
+    for _ in wechat_json:
+        action_info = {'user_id': user_id, 'service_name': _['service_name'], 'wechat_name': _['wechat_name'],
+                       'action_type': json.dumps({'action_type': 'layout_create', 'object_name': layout_name}),
+                       'status': 'todo'}
+        record_insert = sql_tools.save_action_record(action_record_info=action_info,
+                                                     table_action_record=action_record_table)
+        sql_session.execute(record_insert)
+        sql_session.commit()
+
+    for _ in wechat_json:
+        service_name = _['service_name']
+        wechat_name = _['wechat_name']
+        log_ad.select_ad_master(service_name, wechat_name)
+        res = CreateAd(login_ad=log_ad, user_id=user_id).create_layout(typesetting_dict)
+        print(res)
+        if not res['sucess']:
+            now_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
+            try:
+                log_ad.driver.save_screenshot('{layout_name}-{now_time}-{service_name}-{wechat_name}.png'.format(
+                    layout_name=layout_name,
+                    now_time=now_time,
+                    service_name=service_name,
+                    wechat_name=wechat_name))
+            except:
+                pass
+            # 截图,传回错误信息
+
+        status = 'done' if res['sucess'] else 'error'
+        action_type = json.dumps({'action_type': 'layout_create', 'object_name': layout_name})
+        # TODO:线上落地页名字进行设置
+        update_res = action_record_table.update() \
+            .where(action_record_table.c.service_name == service_name) \
+            .where(action_record_table.c.wechat_name == wechat_name) \
+            .where(action_record_table.c.user_id == user_id) \
+            .where(action_record_table.c.action_type == action_type) \
+            .values({
+            action_record_table.c.status: status,
+            action_record_table.c.result: res['result_info']
+            })
+        # values 添加两个列
+        sql_session.execute(update_res)
+        sql_session.commit()
+        log_ad.refresh_driver()
+
+
+    # 成功一个record,更新一个record
+    log_ad.refresh_driver()
+
+
+def create_ad_plan():
+    pass
+
+
+if __name__ == "__main__":
+    pass

+ 7 - 47
wechat_action/create_ad.py

@@ -1,30 +1,19 @@
-from wechat_action.sql_tools import save_ad_layout_result
 from selenium.webdriver.support.wait import WebDriverWait
 from selenium.webdriver.common.keys import Keys
 from selenium.webdriver import ActionChains
-from sqlalchemy import Table
 from logging import handlers
 import logging
 import random
 import time
-import json
 import re
 import os
 
 
 class CreateAd:
-    def __init__(self, login_ad, layout_db, user_id):
+    def __init__(self, login_ad, 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):
@@ -42,10 +31,6 @@ 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 get_layout(self):
-        # 数据库获取数据,然后进行编排
-        # 创建编排
-        pass
 
     def set_advertisement_sign(self):
         # 设置广告标记
@@ -723,43 +708,18 @@ class CreateAd:
             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:
-            #TODO:有空时讲 e 内容设置为原始内容
+            # TODO:有空时讲 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}
+                return {'sucess': False, 'result_info': str(e)}
             else:
-                self.create_layout(layout, err_num=err_num + 1)
+                return self.create_layout(layout, err_num=err_num + 1)
 
+    def check_sucess(self):
+        #TODO: 添加一个页面检查,查看落地页是否已经在微信后台创建
+        pass
 
 if __name__ == '__main__':
     logging.basicConfig(

+ 78 - 16
wechat_action/login_ad.py

@@ -7,18 +7,24 @@ from wechat_action.send_ad_idea import IdeaAction
 from wechat_action.human_ad import HumanAd
 from selenium.webdriver import ChromeOptions
 from selenium.webdriver.common.keys import Keys
+from sqlalchemy import Table
 import time
+import pickle
+from settings import using_config
+from wechat_action.sql_models import DB
+import requests
+import json
 
 
 class LogIn:
-    def __init__(self, service_name, wechat_name):
+    # TODO:整体运行使用逻辑,需要修改几次
+    def __init__(self):
         # 获取到单独服务商下的独立公众号页面
-        self.service_name = service_name
-        self.wechat_name = wechat_name
-        self.driver = self.get_driver()
-        self.log_in()
-        self.select_ad_master()
+        # TODO:之后的落地页创建,推广计划创建,改动service_name,wechat_name通过,login函数主动改动
 
+        self.driver = self.get_driver()
+        # self.log_in()
+        # self.select_ad_master()
 
     def get_driver(self):
         options = ChromeOptions()
@@ -32,19 +38,25 @@ class LogIn:
         return driver
 
     def log_in(self):
+        # self.wechat_cookie_use()
+
         self.driver.get('https://a.weixin.qq.com/index.html')
 
         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'
         frame_login = self.driver.find_element_by_xpath('//*[@id="login_container"]/iframe')
         self.driver.switch_to.frame(frame_login)
         # WebDriverWait(driver, 3).until(EC.invisibility_of_element_located((By.CSS_SELECTOR, img_selector)))
         # time.sleep(3)
         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('广告投放'))
+        return img_url.get_attribute('src')
+
+    def log_in_wait(self):
+        # 默认等待6分钟
+        WebDriverWait(self.driver, 6 * 60).until(lambda driver: driver.find_elements_by_link_text('广告投放'))
 
-    def select_ad_master(self):
+    def select_ad_master(self, service_name, wechat_name):
+        time.sleep(5)
         self.driver.execute_script('''
                     window.scroll(0,1000000);
                     ''')
@@ -55,13 +67,13 @@ class LogIn:
         service_names = self.driver.find_elements_by_class_name('CoreLayout__headerDropdownItem-X4S98')
         choice_service = None
         for _ in service_names:
-            if self.service_name in _.text:
+            if service_name in _.text:
                 choice_service = _
         choice_service.click()
         # 挑选广告投放位置
-        input_wechat_name =self.driver.find_element_by_class_name('TextInput_new__iconRight-pekjS')
+        input_wechat_name = self.driver.find_element_by_class_name('TextInput_new__iconRight-pekjS')
         input_wechat_name.click()
-        input_wechat_name.send_keys(self.wechat_name)
+        input_wechat_name.send_keys(wechat_name)
         input_wechat_name.send_keys(Keys.RETURN)
         self.driver.execute_script('''
             window.scroll(100000,1000000);
@@ -70,26 +82,76 @@ class LogIn:
             ''')
         time.sleep(5)
         elements = self.driver.find_elements_by_link_text('广告投放')
-        # ActionChains(driver).move_to_element(elements[0]).perform()
         elements[0].click()
         time.sleep(1)
         # 切换窗口,点击创建广告,切到广告页面
 
         self.driver.switch_to.window(self.driver.window_handles[-1])
-
         WebDriverWait(self.driver, 100).until(lambda driver: driver.find_element_by_class_name(
             'adui-button-hasLeftIcon'))
 
+    @staticmethod
+    def get_cookie(driver):
+
+        WebDriverWait(driver, 100).until(
+            lambda x: [True for _ in driver.get_cookies() if 'token_ticket' == _['name']]
+        )
+        cookies = driver.get_cookies()
+        cookie_dict = {}
+        for _ in cookies:
+            print(_)
+            cookie_dict[_['name']] = _['value']
+        return cookie_dict
+
+    def wechat_cookie_pickle(self):
+        self.driver.get('https://a.weixin.qq.com/client')
+        WebDriverWait(self.driver, 100).until(
+            lambda x: [True for _ in self.driver.get_cookies() if 'token_ticket' == _['name']]
+        )
+        cookies = self.driver.get_cookies()
+        cookies_obj = pickle.dumps(cookies)
+        return cookies_obj
+
+    def wechat_cookies_check_alive(self, driver_cookies):
+        # wechat 检查cookies 是否可用
+        # 可用返回ture
+        check_url = 'https://a.weixin.qq.com/cgi-bin/agency/get_delivery_metrics?page=1&page_size=10&search_key=&order_by=&ascending=1&only_collect=0&g_tk=5381&_={}'.format(
+            int(time.time() * 1000))
+        # cookie_dict = {}
+        # for _ in driver_cookies:
+        #     cookie_dict[_['name']] = _['value']
+        # rsp_json = requests.get(url=check_url, cookies=cookie_dict).json()
+
+        self.driver.get('https://www.baidu.com')
+        for _ in driver_cookies:
+            self.driver.add_cookie(_)
+        self.driver.get('https://a.weixin.qq.com/client')
+        self.driver.get(check_url)
+
+        print('检查cookies 结果', self.driver.page_source)
+        if '4101' in self.driver.page_source:
+            return False
+        else:
+            return True
+
+
+
+    def upadte_user_info(self):
+        # TODO: 更新 用户相关信息
+        #  每次登录就更新一次相关数据,------公众号相关数据,人群报相关数据
+
+        pass
+
     def get_driver_loged(self):
         return self.driver
 
     def refresh_driver(self):
         while True:
-            if len(self.driver.window_handles)>1:
+            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
+                break

+ 140 - 7
wechat_action/sql_tools.py

@@ -1,8 +1,141 @@
-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'])
+# 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
+
+
+def save_wechat_cookies(wechat_cookies_info, table_wechat_cookies):
+    insert_wechat_cookies = table_wechat_cookies.insert()
+    insert_layout = insert_wechat_cookies.values \
+        (user_id=wechat_cookies_info['user_id'],
+         cookies=wechat_cookies_info['cookies']
+         )
     return insert_layout
+
+
+def save_human_info(human_info, table_human):
+    insert_human = table_human.insert()
+    insert_human = insert_human.values \
+        (service_name=human_info['service_name'],
+         wechat_name=human_info['wechat_name'],
+         human_info=human_info['human_info']
+         )
+    return insert_human
+
+
+def save_layout_typesetting_info(layout_typesetting_info, table_layout_typesetting):
+    insert_layout_typesetting = table_layout_typesetting.insert()
+    insert_layout_typesetting = insert_layout_typesetting.values \
+        (typesetting=layout_typesetting_info['typesetting'],
+         user_id=layout_typesetting_info['user_id'],
+         name=layout_typesetting_info['name']
+         )
+    return insert_layout_typesetting
+
+
+def save_wechat_info(wechat_info, table_wechat):
+    insert_wechat = table_wechat.insert()
+    insert_wechat = insert_wechat.values \
+        (service_name=wechat_info['service_name'],
+         wechat_name=wechat_info['wechat_name'],
+         user_id=wechat_info['user_id']
+         )
+    return insert_wechat
+
+
+def save_action_record(action_record_info, table_action_record):
+    insert_action_record = table_action_record.insert()
+    insert_action_record = insert_action_record.values \
+        (service_name=action_record_info['service_name'],
+         wechat_name=action_record_info['wechat_name'],
+         user_id=action_record_info['user_id'],
+         action_type=action_record_info['action_type'],
+         status=action_record_info['status'],
+         )
+    return insert_action_record
+
+
+def delete_wechat_info(sql_session, user_id):
+    sql = '''
+    delete from wechat_info 
+        where user_id = '{}' 
+    '''.format(user_id)
+    sql_session.execute(sql)
+    sql_session.commit()
+
+
+def get_human_info(sql_session, user_id):
+    sql = '''
+        select human_info from human_info hi 
+        where concat(service_name ,wechat_name ) in
+        (select concat(service_name ,wechat_name) from wechat_info
+        where user_id ='{}') ;
+    '''.format(user_id)
+    cursor = sql_session.execute(sql)
+    lines = cursor.fetchall()
+    result_list = [line[0] for line in lines]
+    return result_list
+
+
+def get_layout_typesetting(sql_session, user_id, typesetting_name):
+    sql = '''
+            select * from layout_typesetting lt 
+            where user_id ='{}' and name='{}';
+    '''.format(user_id, typesetting_name)
+    cursor = sql_session.execute(sql)
+    lines = cursor.fetchall()
+    if lines:
+        result_list = lines[0][0]
+        return result_list
+
+
+def get_undo_action(sql_session, user_id):
+    # TODO:sql 里面添加doing,error状态的挑选
+    sql = '''
+        select action_type ,wechat_name ,service_name 
+            from action_record 
+        where user_id='{}' and status ='todo' ;
+    '''.format(user_id)
+    cursor = sql_session.execute(sql)
+    lines = cursor.fetchall()
+    result_list = [line for line in lines]
+    return result_list
+
+
+def get_action_status(sql_session, user_id):
+    # TODO:sql 里面添加doing,error状态的挑选
+    sql = '''
+        select count(*)
+            from action_record 
+        where user_id='{}' and status ='doing' ;
+    '''.format(user_id)
+    cursor = sql_session.execute(sql)
+    lines = cursor.fetchall()
+    result = lines[0][0]
+    return result
+
+
+def get_wechat_info(sql_session, user_id):
+    sql = '''
+        select service_name ,wechat_name from wechat_info
+        where user_id ='{}' ;
+    '''.format(user_id)
+    cursor = sql_session.execute(sql)
+    lines = cursor.fetchall()
+    result_list = [line for line in lines]
+    return result_list
+
+
+def get_wechat_cookies(sql_session, user_id):
+    sql = '''
+    select cookies from wechat_cookies where user_id='{}'
+    '''.format(user_id)
+    cursor = sql_session.execute(sql)
+    lines = cursor.fetchall()
+    print(type(lines), lines)
+    if lines:
+        return lines[0][0]

+ 24 - 55
wechat_api/get_wechat_info.py

@@ -8,6 +8,7 @@ from wechat_action.human_ad import HumanAd
 from selenium.webdriver import ChromeOptions
 from selenium.webdriver.common.keys import Keys
 from functools import wraps
+from wechat_action import login_ad
 import time
 import re
 import requests
@@ -15,58 +16,18 @@ import random
 
 
 class WechatApi():
-    def __init__(self):
-        self.driver = self.get_driver()
-        self.log_in()
-
-    def get_driver(self):
-        options = ChromeOptions()
-        # 防止selenium快速崩坏
-        options.add_argument("--disable-dev-shm-usage")
-        # driver = webdriver.Remote(
-        #     command_executor='http://192.168.7.245:4444/wd/hub',
-        #     options=options)
-        driver = webdriver.Chrome()
-        driver.maximize_window()
-        return driver
-
-    def log_in(self):
-        self.driver.get('https://a.weixin.qq.com/index.html')
-
-        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'
-        frame_login = self.driver.find_element_by_xpath('//*[@id="login_container"]/iframe')
-        self.driver.switch_to.frame(frame_login)
-        # WebDriverWait(driver, 3).until(EC.invisibility_of_element_located((By.CSS_SELECTOR, img_selector)))
-        # time.sleep(3)
-        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: self.driver.find_elements_by_link_text('广告投放'))
-
-    def get_cookie(self):
-
-        WebDriverWait(self.driver, 100).until(
-            lambda x: [True for _ in self.driver.get_cookies() if 'token_ticket' == _['name']]
-        )
-        cookies = self.driver.get_cookies()
-        cookie_dict = {}
-        for _ in cookies:
-            print(_)
-            cookie_dict[_['name']] = _['value']
-        return cookie_dict
-
-    def wechat_cookie_save(self):
-        # TODO:wechat  cookie 存入数据库
-        pass
+    def __init__(self, log_ad):
+        self.log_ad = log_ad
+        self.driver = self.log_ad.driver
+        self.human_info_list = []
 
     def api_get_name(self):
-        # TODO:公众号有时拿不到
         def _api_get_name(self, service_name):
             WebDriverWait(self.driver, 100).until(
                 lambda driver: True if service_name in self.driver.page_source and len(
                     re.findall('g_tk=(\d+)', self.driver.page_source)) else False)
 
-            cookie_dict = self.get_cookie()
+            cookie_dict = self.log_ad.get_cookie(self.driver)
 
             url_token = re.findall('g_tk=(\d+)', self.driver.page_source)
             url_token = url_token[0]
@@ -84,7 +45,7 @@ class WechatApi():
         url_token = url_token[0]
         wechat_names_url = 'https://a.weixin.qq.com/cgi-bin/agency/get_delivery_metrics?page=1&page_size=10&search_key=&order_by=&ascending=1&only_collect=0&g_tk={token}&_={time_}'.format(
             token=url_token, time_=int(time.time()))
-        cookie_dict = self.get_cookie()
+        cookie_dict = self.log_ad.get_cookie(self.driver)
         rsp = requests.get(url=wechat_names_url, cookies=cookie_dict)
         service_name = self.driver.find_element_by_xpath('//*[@id="root"]/div/header/div/div[3]/div/div[1]').text
         print(service_name, rsp.text)
@@ -93,8 +54,8 @@ class WechatApi():
         self.service_loop(_api_get_name, {'self': self, 'service_name': service_name})
 
     def get_human_info(self):
+        #TODO:需要有重试机制
         def _get_human_info(self, service_name):
-
             # 耗时一秒以内
             # self.driver.get('https://a.weixin.qq.com/client')
 
@@ -102,7 +63,7 @@ class WechatApi():
                 lambda driver: True if service_name in self.driver.page_source and len(
                     re.findall('g_tk=(\d+)', self.driver.page_source)) else False)
 
-            cookie_dict = self.get_cookie()
+            cookie_dict = self.log_ad.get_cookie(self.driver)
             url_token = re.findall('g_tk=(\d+)', self.driver.page_source)[0]
 
             # 得到各个appid
@@ -113,14 +74,11 @@ class WechatApi():
             print(wechat_names_url)
             print(rsp.text)
 
-            wechat_id_list = []
-            for i in rsp.json()['list']:
-                wechat_id_list.append(i['appid'])
-
             # 普通用户的需要在1s内获取到
             # 得到wechat_token
-            for i in wechat_id_list:
-                wechat_id = i
+            for i in rsp.json()['list']:
+                wechat_name = i['nickname']
+                wechat_id = i['appid']
                 wechat_tran_url = 'http://a.weixin.qq.com/cgi-bin/agency/redirect_mp?appid={wechat_id}&g_tk={token}&mgr_type=1'.format(
                     token=url_token, wechat_id=wechat_id)
                 session = requests.session()
@@ -129,17 +87,28 @@ class WechatApi():
                 print(rsp.url)
                 token_id = re.findall('token=(\d+)', rsp.url)[0]
                 print(token_id)
-                'http://a.weixin.qq.com/cgi-bin/agency/redirect_mp?appid=wxf82b302b1dde69e9&g_tk=1227235269&mgr_type=1'
                 # 得到人群包
+                #TODO:人群包相关的数据
                 human_url = 'https://mp.weixin.qq.com/promotion/dmpmgr?action=readlist&page=1&page_size=100&token={wechat_token}&appid=&spid=&_={time_}'.format(
                     wechat_token=token_id, time_=int(time.time()))
                 print(human_url)
                 rsp = session.get(url=human_url)
                 print(rsp.text)
+                res_json = rsp.json()
+                res_json['service_name'] = service_name
+                res_json['wechat_name'] = wechat_name
+
+                self.human_info_list.append(res_json)
+                print(self.human_info_list)
+                import json
+                print(json.dumps(self.human_info_list))
 
+
+        time.sleep(random.uniform(3, 5))
         service_name = self.driver.find_element_by_xpath('//*[@id="root"]/div/header/div/div[3]/div/div[1]').text
         _get_human_info(self, service_name=service_name)
         self.service_loop(_get_human_info, {'self': self, 'service_name': service_name})
+        return self.human_info_list
 
     def service_loop(self, function, kwargs):