Kaynağa Gözat

Merge branch 'Crawler'

Huan 5 yıl önce
ebeveyn
işleme
2638d7ec52

+ 1 - 1
CGB/Write.py

@@ -179,7 +179,7 @@ def Draw(dis_x=900,dis_y=700):
     if done[1] != 0: print('Init!')  # 检查是否错误
     Font = pygame.font.Font('Font\ZKST.ttf', 16)  # 设置字体(Linux下应该用\而不是/)
     root = pygame.display.set_mode((dis_x, dis_y),0)  # 创建屏幕
-    root_caption = pygame.display.set_caption('CoTan画图板')#定义标题(后期加上定义Logo)
+    root_caption = pygame.display.set_caption('CoTan草稿板')#定义标题(后期加上定义Logo)
     root.fill([255, 255, 255])  # 默认用白色填充窗口
     flat = True#循环条件(不是全局)
     while flat:

+ 993 - 0
Crawler/Crawler_controller.py

@@ -0,0 +1,993 @@
+from selenium import webdriver
+import threading
+import time
+import hashlib
+from time import sleep
+import bs4
+import re as regular
+from Crawler import Information_storage
+import requests
+from selenium.webdriver.common.action_chains import ActionChains
+from selenium.webdriver.common.keys import Keys
+keys_name_dict = {'ctrl':Keys.CONTROL,'shift':Keys.SHIFT,'tab':Keys.TAB,'left_ctrl':Keys.LEFT_CONTROL,'left_shift':Keys.LEFT_SHIFT,
+                      'left_alt':Keys.LEFT_ALT,'ALT':Keys.ALT,'enter':Keys.ENTER,'return':Keys.RETURN,'backspace':Keys.BACKSPACE,
+                      'del':Keys.DELETE,'pgup':Keys.PAGE_UP,'pgdn':Keys.PAGE_DOWN,'home':Keys.HOME,'end':Keys.END,'esc':Keys.CANCEL,
+                      'insert':Keys.INSERT,'meta':Keys.META,'up':Keys.UP,'down':Keys.DOWN,'right':Keys.RIGHT,'left':Keys.LEFT
+                     }#键-值映射
+for i in range(1,13):#F1 - F12按键
+    keys_name_dict[f'f{i}'] = eval(f'Keys.F{i}')
+
+data_base = Information_storage.DataBase_Home()
+
+class PAGE:
+    def __init__(self,time_out):
+        self.url=''
+        self.UA=''
+        self.func = 'PAGE'
+        self.time_out = time_out
+
+    def __str__(self):
+        return f'[{self.time_out}s]{self.func}-{self.url}:UA>{self.UA}'
+
+class REQUESTS_Base(PAGE):
+    def init(self,UA,url,cookies):
+        if UA == '':
+            UA = f'--user-agent ="Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' \
+                 f'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36 Edg/80.0.361.66"'
+        self.UA = UA
+        self.headers = {'Accept': 'text/html, application/xhtml+xml, image/jxr, */*',
+                   'Accept - Encoding': 'gzip, deflate',
+                   'Accept-Language': 'zh-Hans-CN, zh-Hans; q=0.5',
+                   'Connection': 'Keep-Alive',
+                   'User-Agent': UA}
+        self.url = url
+        self.cookies = cookies
+        self.new = True
+
+class URL_POST(REQUESTS_Base):#通过requests的post请求
+    def __init__(self, url, data, time_out,UA='',cookies=None, **kwargs):
+        super(URL_POST, self).__init__(time_out)
+        self.func = 'post'
+        self.data = data
+        self.requests = requests.post
+        self.init(UA,url,cookies)
+
+    def __str__(self):
+        return super(URL_POST, self).__str__() + f';data>{self.data}'
+
+class URL_GET(REQUESTS_Base):#通过requests的post请求
+    def __init__(self, url, time_out,UA='',cookies=None, **kwargs):
+        super(URL_GET, self).__init__(time_out)
+        self.func = 'simplify_get'
+        self.requests = requests.get
+        self.init(UA,url,cookies)
+
+class URL_PAGE(PAGE):
+    def __init__(self,url, time_out,first_run=False,head=False,no_plugins=True,no_js=False,no_java=False,
+                 no_img=False,UA='',cookies=None,new=False,down_load_dir='',**kwargs):
+        super(URL_PAGE, self).__init__(time_out)
+        self.url = url
+        self.func = 'get'
+        self.options = webdriver.ChromeOptions()
+        self.cookies = cookies#cookies存储位置
+        self.new = new#新键页面or新键浏览器
+        self.down_load_dir = down_load_dir
+        self.init(first_run,head,no_plugins,no_js,no_java,no_img,UA)
+
+    def init(self,first_run,head,no_plugins,no_js,no_java,no_img,UA):
+        self.options.add_argument('disable-infobars')#不显示
+        prefs = {'profile.default_content_settings.popups': 0, 'download.default_directory':self.down_load_dir}
+        self.options.add_experimental_option('prefs', prefs)#下载设置
+        if first_run:
+            self.options.add_argument('-first run')
+        if head:#无头设置
+            print('FFF')
+            self.options.add_argument('--headless')
+            self.options.add_argument('--disable-gpu')
+        if no_plugins:
+            self.options.add_argument('--disable-plugins')
+        if no_js:
+            self.options.add_argument('--disable-javascript')
+        if no_java:
+            self.options.add_argument('--disable-java')
+        if no_img:
+            self.options.add_argument('blink-settings=imagesEnabled=false')
+        if UA == '':
+            UA = (f'user-agent ="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
+                  f'Chrome/80.0.3987.132 Safari/537.36"')
+        # self.options.add_argument(f'--user-agent ="{UA}"')
+        self.UA = UA
+
+    def __str__(self):
+        return f'{self.func}-{self.url}:UA>{self.UA}'
+
+class url:#url管理器
+    num = 0#url处理器个数
+    def __init__(self,dic=f'',dic_run=f''):
+        url.num += 1
+        self.save_dir = dic
+        dic += f'/url[{url.num}].cot_url'
+        dic_run += f'/url_run[{url.num}].cot_url'
+        self.dir = dic
+        self.dir_run = dic_run
+        self.file = open(dic,'a')#写入url_history的文件
+        self.file_run = open(dic_run,'a')#写入已读url文件
+        self.url_list = []#待读url
+        self.url_history = []#url历史
+        self.filter = {}#过滤函数
+
+    def close(self):
+        self.file.close()
+        self.file_run.close()
+
+    def filter_func(self,url,**kwargs):#url过滤系统
+        for i in self.filter:
+            if not self.filter[i](url): return False
+        return True
+
+    def Add_func(self,func,name):#添加过滤函数
+        self.filter[name] = func
+
+    def Del_func(self,index):#删除过滤函数
+        del self.filter[list(self.filter.keys())[index]]
+
+    def return_func(self):
+        return list(self.filter.keys())
+
+    def add_url(self,url,func,data=None,**kwargs):#添加url
+        if func == '':func = 'get'
+        if func == 'get':url_ = url
+        else:
+            url_ = url + str(data)
+        if url_ not in self.url_history and self.filter_func(url,func=func):#1.url不存在历史,2.url满足筛选条件
+            if func == 'get':
+                self.url_list.append(URL_PAGE(url=url,**kwargs,down_load_dir=self.dir))#添加到待取得url
+            elif func == 'simplify_get':
+                self.url_list.append(URL_GET(url=url, **kwargs, down_load_dir=self.dir))  # 添加到待取得url
+            else:
+                self.url_list.append(URL_POST(url=url,data=data,**kwargs))  # 添加到待取得url
+
+            self.url_history.append(url_)#添加到历史url
+            self.__out_url(url_)#输出历史url
+            return True#写入成功
+        return False#写入失败
+
+    def del_url(self,index):#删除url
+        self.__out_url_run(f'DELETE {self.url_list[index]}')
+        del self.url_list[index]
+
+    def get_url(self) -> (URL_PAGE,URL_POST):#取得url
+        url_page = self.url_list[0]
+        self.__out_url_run(url_page.url)
+        del self.url_list[0]
+        return url_page
+
+    def __out_url(self,url):#输出url历史
+        self.file.write(f'{url}\n')
+        self.file.flush()
+
+    def __out_url_run(self,url):#输出已经运行的url
+        self.file_run.write(f'{url}\n')
+        self.file_run.flush()
+
+    def finish(self):
+        return len(self.url_list) == 0
+
+    def return_url(self):
+        return self.url_list.copy()
+
+    def return_url_history(self):
+        return self.url_history.copy()
+
+class Page_Downloader:
+    num = 0
+    def __init__(self,url:url,dic=''):
+        self.url = url
+        self.dir = dic
+        self.log = Information_storage.log(dic)
+        Page_Downloader.num += 1
+        self.page_source_dict = {}#页面保存信息
+        self.cookie_Thread = None#子进程
+        self.browser = None
+        self.cookie_dict = {}
+        self.cookie_dict_list = {}#sele的cookies
+        self.lase_func = ''
+
+    def close(self):
+        self.log.close()
+
+    def stop(self):
+        try:
+            self.break_ = False
+            self.browser.quit()
+            self.lase_func = ''
+        except:
+            pass
+
+    def strat_urlGet(self,*args,func_cookie):#用get请求url ->得到一个页面信息
+        self.break_ = False
+        self.page_source_dict = {}
+        self.nowurl = self.url.get_url()#获取一个url
+        url = self.nowurl.url
+        if self.nowurl.func == 'get':
+            if self.nowurl.new == True and self.lase_func == 'get':#重新启动
+                self.browser.quit()
+                self.browser = webdriver.Chrome(chrome_options=self.nowurl.options)
+            try:
+                self.browser.set_page_load_timeout(self.nowurl.time_out)  # 设置页面加载超时
+                self.browser.set_script_timeout(self.nowurl.time_out)  # 设置页面异步js执行超时
+                self.browser.get(url)
+            except:
+                self.browser = webdriver.Chrome(chrome_options=self.nowurl.options)
+                self.browser.set_page_load_timeout(self.nowurl.time_out)  # 设置页面加载超时
+                self.browser.set_script_timeout(self.nowurl.time_out)  # 设置页面异步js执行超时
+                self.browser.get(url)
+            try:
+                if self.nowurl.new != True:raise Exception
+                list_ = self.cookie_dict_list[self.nowurl.cookies]
+                self.Tra_cookies()
+                try:
+                    for i in list_:
+                        self.Add_cookies(i)
+                except:pass
+            except:
+                pass
+            self.start_cookies(func_cookie,url)
+        else:#requests模式
+            if self.lase_func == 'get':
+                try:self.browser.quit()
+                except:pass
+            try:
+                args = {'cookies':self.cookie_dict[self.nowurl.cookies]}
+                func_cookie([args['cookies']])
+            except:
+                args = {}
+                func_cookie([])
+            if self.nowurl.func == 'post':args['data'] = self.nowurl.data
+            self.browser = self.nowurl.requests(url,headers=self.nowurl.headers,**args,timeout=self.nowurl.time_out)
+            self.cookie_dict[url] = requests.utils.dict_from_cookiejar(self.browser.cookies)#保存cookies
+            func_cookie([self.cookie_dict[url]])
+        self.lase_func = self.nowurl.func
+        self.Parser.browser = self.browser
+        self.Parser.init(url)
+        return self.browser
+
+    def start_cookies(self,func_cookie,url):
+        self.break_ = True
+        def update_cookie():
+            nonlocal self
+            while self.break_:
+                try:
+                    cookies = self.browser.get_cookies()
+                    func_cookie(cookies)  # 与GUI通信显示cookie
+                    self.cookie_dict[url] = cookies
+                    time.sleep(.5)
+                except:
+                    pass
+
+        self.cookie_Thread = threading.Thread(target=update_cookie)
+        self.cookie_Thread.start()
+
+    def Del_cookies(self,name):#删除指定cookies
+        browser = self.browser
+        browser.delete_cookie(name)
+
+    def Tra_cookies(self):#清空cookies
+        browser = self.browser
+        browser.delete_all_cookies()
+
+    def Add_cookies(self,cookies:dict):#清空cookies
+        browser = self.browser
+        browser.add_cookie(cookies)
+
+    def update_cookies(self,name,cookies:dict):
+        browser = self.browser
+        cookies_list = browser.get_cookies()
+        for i in cookies_list:
+            if i.get('name',None) == name:
+                browser.delete_cookie(name)#删除原来cookies
+                i.update(cookies)
+                browser.add_cookie(i)
+                return
+        raise Exception
+
+    def set_Page_Parser(self,Parser):
+        self.Parser = Parser
+        self.Parser.browser = self.browser
+        self.Parser.url = self.url
+        self.Parser.dir = self.dir
+        self.Parser.log = self.log
+
+class Page_Parser:
+    def __init__(self,Downloader:Page_Downloader):
+        self.Downloader = Downloader
+        self.Downloader.set_Page_Parser(self)
+        self.func_list = []
+        self.func_dict = {}
+        self.n = 0
+        self.init()
+
+    def init(self,url=''):
+        self.element_dict = {}#记录属性的名字
+        self.now_url = url
+
+    def add_base(self,func):  # 装饰器
+        def wrap(browser=None,num=None,name=None, *args, **kwargs) -> bool:
+            try:
+                func(browser=browser,num=num, name=name, *args, **kwargs)
+                return True
+            except:
+                return False
+        return wrap
+
+    def add_func(self,name,func):
+        self.func_list.append(f'{name}[{self.n}]')
+        self.func_dict[f'{name}[{self.n}]'] = func
+        self.n += 1
+
+    def tra_func(self):
+        self.func_list = []
+        self.func_dict = {}
+        self.n = 0
+
+    def del_func(self,index,end=False):
+        if end:index = len(self.func_list) - index - 1
+        del self.func_dict[self.func_list[index]]
+        self.func_list[index] = 'Func_have_been_del'
+        self.func_dict['Func_have_been_del'] = lambda *args,**kwargs:None
+
+    def return_func(self,only=True):
+        if only:
+            return self.func_list.copy()
+        else:
+            return [f'var[{index}]@ {i}' for index,i in enumerate(self.func_list.copy())]
+
+    def find_ID(self,id,not_all=False,**kwargs):
+        @self.add_base
+        def find(browser, num, name, *args, **kwargs):
+            nonlocal self,id
+            if browser == None:browser = self.browser
+            if not_all:self.element_dict[f'{name}[{num}]'] = [browser.find_element_by_id(id)]#返回必须是list
+            else:self.element_dict[f'{name}[{num}]'] = browser.find_elements_by_id(id)
+        self.add_func(f'find_ID:{id}',find)#添加func
+
+    def find_class(self,class_name,not_all=False,**kwargs):
+        @self.add_base
+        def find(browser, num, name, *args, **kwargs):
+            nonlocal self,class_name
+            if browser == None:browser = self.browser
+            if not_all:self.element_dict[f'{name}[{num}]'] = [browser.find_element_by_class_name(class_name)]#返回必须是list
+            else:self.element_dict[f'{name}[{num}]'] = browser.find_elements_by_class_name(class_name)#返回必须是list
+        self.add_func(f'find_class:{class_name}',find)#添加func
+
+    def find_name(self,name_,not_all=False,**kwargs):
+        @self.add_base
+        def find(browser, num, name, *args, **kwargs):
+            nonlocal self,name_
+            if browser == None:browser = self.browser
+            if not_all:self.element_dict[f'{name}[{num}]'] = [browser.find_element_by_name(name_)]#返回必须是list
+            else:self.element_dict[f'{name}[{num}]'] = browser.find_elements_by_name(name_)#返回必须是list
+        self.add_func(f'find_name:{name_}',find)#添加func
+
+    def find_xpath(self,xpath,not_all=False,**kwargs):
+        @self.add_base
+        def find(browser, num, name, *args, **kwargs):
+            nonlocal self,xpath
+            if browser == None:browser = self.browser
+            if not_all:self.element_dict[f'{name}[{num}]'] = [browser.find_element_by_xpath(xpath)]#返回必须是list
+            else:self.element_dict[f'{name}[{num}]'] = browser.find_elements_by_xpath(xpath)#返回必须是list
+        self.add_func(f'find_xpath:{xpath}',find)#添加func
+
+    def find_css(self,css_selector,not_all=False,**kwargs):
+        @self.add_base
+        def find(browser, num, name, *args, **kwargs):
+            nonlocal self,css_selector
+            if browser == None:browser = self.browser
+            if not_all:self.element_dict[f'{name}[{num}]'] = [browser.find_element_by_css_selector(css_selector)]#返回必须是list
+            else:self.element_dict[f'{name}[{num}]'] = browser.find_elements_by_css_selector(css_selector)#返回必须是list
+        self.add_func(f'find_css:{css_selector}',find)#添加func
+
+    def find_tag_name(self,tag_name,not_all=False,**kwargs):
+        @self.add_base
+        def find(browser, num, name, *args, **kwargs):
+            nonlocal self,tag_name
+            if browser == None:browser = self.browser
+            if not_all:self.element_dict[f'{name}[{num}]'] = [browser.find_element_by_tag_name(tag_name)]#返回必须是list
+            else:self.element_dict[f'{name}[{num}]'] = browser.find_elements_by_tag_name(tag_name)#返回必须是list
+        self.add_func(f'find_tagName:{tag_name}',find)#添加func\
+
+    def find_link_text(self,link_text,not_all=False,**kwargs):#匹配link
+        @self.add_base
+        def find(browser, num, name, *args, **kwargs):
+            nonlocal self,link_text
+            if browser == None:browser = self.browser
+            if not_all:self.element_dict[f'{name}[{num}]'] = [browser.find_element_by_link_text(link_text)]#返回必须是list
+            else:self.element_dict[f'{name}[{num}]'] = browser.find_elements_by_link_text(link_text)#返回必须是list
+        self.add_func(f'find_link_text:{link_text}',find)#添加func
+
+    def find_partial_link_text(self,partial_link_text,not_all=False,**kwargs):#模糊匹配
+        @self.add_base
+        def find(browser, num, name, *args, **kwargs):
+            nonlocal self,partial_link_text
+            if browser == None:browser = self.browser
+            if not_all:self.element_dict[f'{name}[{num}]'] = [browser.find_element_by_partial_link_text(partial_link_text)]#返回必须是list
+            else:self.element_dict[f'{name}[{num}]'] = [browser.find_element_by_partial_link_text(partial_link_text)]#返回必须是list
+        self.add_func(f'find_partial_link_text:{partial_link_text}',find)#添加func
+
+    def find_switch_to_alert(self,*args,**kwargs):#定位弹出框
+        @self.add_base
+        def find(browser, num, name, *args, **kwargs):
+            nonlocal self
+            if browser == None:browser = self.browser
+            self.element_dict[f'{name}[{num}]'] = [browser.switch_to.alert()]
+        self.add_func(f'find_alert',find)#添加func
+
+    def find_switch_to_active_element(self,*args,**kwargs):#定位焦点元素
+        @self.add_base
+        def find(browser, num, name, *args, **kwargs):
+            nonlocal self
+            if browser == None:browser = self.browser
+            self.element_dict[f'{name}[{num}]'] = [browser.switch_to.active_element()]
+        self.add_func(f'active_element',find)#添加func
+
+    def find_switch_to_frame(self,reference,is_id=False,*args,**kwargs):#定位Frame
+        @self.add_base
+        def find(browser, num, name, *args, **kwargs):
+            nonlocal self,reference,is_id
+            if browser == None:browser = self.browser
+            if reference == None:
+                self.element_dict[f'{name}[{num}]'] = [browser.default_content()]# 回到主文档
+            elif reference == '':
+                self.element_dict[f'{name}[{num}]'] = [browser.parent_frame()]# 回到父文档
+            else:
+                if is_id:reference = int(reference)
+                self.element_dict[f'{name}[{num}]'] = [browser.switch_to.frame(str(reference))]# 定位进入文档
+        func_name = {None:'主文档','':'父文档'}.get(reference,reference)
+        self.add_func(f'find_frame:{func_name}',find)#添加func
+
+    def send_keys(self,text,element_value,index=0,**kwargs):#输入文字
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[element_value][index].send_keys(text)
+        self.add_func(f'sent_text:{text}>{element_value}[{index}]', action)  # 添加func
+
+    def User_Passwd(self,User,Passwd,element_value,index=0,**kwargs):#输入验证(User&Password)
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[element_value][index].authenticate(User,Passwd)
+        self.add_func(f'User:Passwd:{User};{Passwd}>{element_value}[{index}]', action)  # 添加func
+
+    def clear(self,element_value,index=0,**kwargs):#清空文本
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[element_value][index].clear()
+        self.add_func(f'clear_text>{element_value}[{index}]', action)  # 添加func
+
+    def click(self,element_value,index=0,**kwargs):#点击按钮
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[element_value][index].click()
+        self.add_func(f'click>{element_value}[{index}]', action)  # 添加func
+
+    def accept(self,element_value,index=0,**kwargs):#点击确定(弹出框)
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[element_value][index].accept()
+        self.add_func(f'accept>{element_value}[{index}]', action)  # 添加func
+
+    def dismiss(self,element_value,index=0,**kwargs):#点击取消(弹出框)
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[element_value][index].dismiss()
+        self.add_func(f'dismiss>{element_value}[{index}]', action)  # 添加func
+
+    def submit(self,element_value,index=0,**kwargs):#提交表单
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[element_value][index].submit()
+        self.add_func(f'submit>{element_value}[{index}]', action)  # 添加func
+
+    def deselect_by_index(self,element_value,deselect,index=0,**kwargs):#根据index取消选择
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[element_value][index].deselect_by_index(int(deselect))
+        self.add_func(f'deselect_by_index:{deselect}>{element_value}[{index}]', action)  # 添加func
+
+    def deselect_by_text(self,element_value,deselect,index=0,**kwargs):#根据text取消选择
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[element_value][index].deselect_by_visible_text(deselect)
+        self.add_func(f'deselect_by_text:{deselect}>{element_value}[{index}]', action)  # 添加func
+
+    def deselect_by_value(self,element_value,deselect,index=0,**kwargs):#根据value取消选择
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[element_value][index].deselect_by_value(deselect)
+        self.add_func(f'deselect_by_value:{deselect}>{element_value}[{index}]', action)  # 添加func
+
+    def select_by_index(self,element_value,deselect,index=0,**kwargs):#根据index选择
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[element_value][index].select_by_index(int(deselect))
+        self.add_func(f'select_by_index:{deselect}>{element_value}[{index}]', action)  # 添加func
+
+    def select_by_text(self,element_value,deselect,index=0,**kwargs):#根据text选择
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[element_value][index].select_by_visible_text(deselect)
+        self.add_func(f'select_by_text:{deselect}>{element_value}[{index}]', action)  # 添加func
+
+    def select_by_value(self,element_value,deselect,index=0,**kwargs):#根据value选择
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[element_value][index].select_by_value(deselect)
+        self.add_func(f'select_by_value:{deselect}>{element_value}[{index}]', action)  # 添加func
+
+    def back(self,**kwargs):# 返回
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.browser.back()
+        self.add_func(f'BACK', action)
+
+    def forward(self,**kwargs):# 前进
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.browser.forward()
+        self.add_func(f'FORWARD', action)
+
+    def refresh(self,**kwargs):# 刷新
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.browser.refresh()
+        self.add_func(f'REFRESH', action)
+
+    def wait_sleep(self,time:int=2,**kwargs):#暴力等待
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            sleep(time)
+        self.add_func(f'WAIT:{time}s', action)
+
+    def set_wait(self,time:int=2,**kwargs):#隐式等待
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            sleep(time)
+        self.add_func(f'Loading_wait:{time}s', action)
+
+    def run_JS(self,JS,**kwargs):
+        @self.add_base
+        def action(num,name,*args, **kwargs):
+            nonlocal self
+            get = self.browser.execute_script(JS)
+            if hasattr(get,'__getitem__'):#可切片
+                self.element_dict[f'{name}[{num}]'] = get  # 返回必须是list
+            else:
+                self.element_dict[f'{name}[{num}]'] = [get]
+        self.add_func(f'run_js:{JS}', action)
+
+    def to_text(self,**kwargs):#获取网页源码
+        @self.add_base
+        def action(num,name,*args, **kwargs):
+            nonlocal self
+            try:
+                self.element_dict[f'{name}[{num}]'] = [self.browser.page_source,self.now_url]
+            except:
+                self.element_dict[f'{name}[{num}]'] = [self.browser.text, self.now_url]#request
+        self.add_func(f'get_page_source', action)
+
+    def out_html(self,element_value,**kwargs):#输出网页源码
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            md5 = hashlib.md5()  # 应用MD5算法
+            md5.update(f'{time.time()}_{self.now_url}'.encode('utf-8'))
+            name = md5.hexdigest()
+            save_dir = self.dir + '/' + name + '.cotan_source'
+            print(save_dir)
+            with open(save_dir,'w') as f:
+                f.write(self.element_dict[element_value][0])
+            with open(save_dir + '.CoTanURL','w') as f:
+                f.write(self.element_dict[element_value][1])
+        self.add_func(f'write_html<{element_value}', action)
+
+    def del_all_cookies(self,**kwargs):#删除所有曲奇
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.browser.delete_all_cookies()
+        self.add_func(f'del_all_cookies', action)
+
+    def del_cookies(self,cookies_name,**kwargs):#删除指定曲奇
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.browser.delete_cookie(cookies_name)
+        self.add_func(f'del_cookies:{cookies_name}', action)
+
+    def add_cookies(self,cookies,**kwargs):#添加指定曲奇
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.browser.add_cookie(cookies)
+        self.add_func(f'add_cookies:{cookies}', action)
+
+    def update_cookies(self,cookies_name,cookies,**kwargs):#更新曲奇
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            now_cookies = self.browser.get_cookie(cookies_name)
+            self.browser.delete_cookie(cookies_name)
+            now_cookies.update(cookies)
+            self.browser.add_cookie(now_cookies)
+        self.add_func(f'add_cookies:{cookies}', action)
+
+    def get_cookies(self,cookies_name,**kwargs):#获取指定曲奇
+        @self.add_base
+        def action(num,name,*args, **kwargs):
+            nonlocal self
+            self.element_dict[f'{name}[{num}]'] = [self.browser.get_cookie(cookies_name)]
+        self.add_func(f'get_cookies:{cookies_name}', action)
+
+    def get_all_cookies(self,**kwargs):#获取所有曲奇
+        @self.add_base
+        def action(num,name,*args, **kwargs):
+            nonlocal self
+            self.element_dict[f'{name}[{num}]'] = self.browser.get_cookie()
+        self.add_func(f'get_all_cookies', action)
+
+    def make_bs(self, element_value, **kwargs):  # 解析成bs4对象
+        @self.add_base
+        def action(num,name,*args, **kwargs):
+            nonlocal self
+            self.element_dict[f'{name}[{num}]'] = [bs4.BeautifulSoup(self.element_dict[element_value][0], "html.parser")]
+        self.add_func(f'Parsing:{element_value}', action)  # 添加func
+
+    def listSlicing(self,index:(slice,int),element_value):
+        if type(index) is int:
+            return [self.element_dict[element_value][index]]
+        else:
+            return self.element_dict[element_value][index]
+
+    def to_Database(self,element_value,index,data:(str,list),dataBase_name:str,**kwargs):#传入data Base
+        @self.add_base
+        def action(*args, **kwargs):
+            global data_base
+            nonlocal self
+            iter_list = self.listSlicing(index, element_value)
+            for bs in iter_list:
+                new = []
+                for i in data:
+                    if i == '$name&':new.append(bs.name)
+                    elif i == '$self&':new.append(str(bs).replace('\n',''))
+                    elif i == '$string$':new.append(str(bs.string).replace('\n',''))
+                    else:
+                        new.append(bs.attrs.get(i,''))
+                data_base.add_DataBase(dataBase_name,new)
+        self.add_func(f'DataBase:{data}<{element_value}[{index}]>{dataBase_name}', action)  # 添加func
+
+    def to_Database_by_re(self,element_value,index,data:str,dataBase_name:str,**kwargs):#通过正则,传入dataBase
+        data = regular.compile(data)
+        @self.add_base
+        def action(*args, **kwargs):
+            global data_base
+            nonlocal self
+            iter_list = self.listSlicing(index, element_value)
+            for bs in iter_list:
+                new = regular.findall(data,str(bs))
+                data_base.add_DataBase(dataBase_name,new)
+        self.add_func(f'DataBase:{data}<{element_value}[{index}]>{dataBase_name}', action)  # 添加func
+
+    def findAll(self, element_value,tag:(str,list),attribute:dict,limit,recursive,index:(slice,int),**kwargs):#根据标签定位
+        if type(tag) is str:
+            tag = str(tag).split(',')
+        try:
+            limit = int(limit)
+        except:
+            limit = None
+        @self.add_base
+        def action(num,name,*args, **kwargs):
+            nonlocal self
+            iter_list = self.listSlicing(index,element_value)
+            paser_list = []
+            for bs in iter_list:
+                try:
+                    re = bs.find_all(tag,attribute,limit=limit,recursive=recursive)
+                except:
+                    try:
+                        if str(bs.name) not in tag:raise Exception
+                        for agrs_name in attribute:
+                            text = attribute[agrs_name]
+                            if type(text) is str:
+                                if bs.attrs[agrs_name] != text:raise Exception
+                            else:#正则匹配
+                                if not regular.match(text,bs.attrs[agrs_name]): raise Exception
+                        re = [bs]
+                    except:
+                        re = []
+                paser_list += re
+            self.element_dict[f'{name}[{num}]'] = paser_list
+        self.add_func(f'findAll:{element_value}[{index}]', action)  # 添加func
+
+    def findAll_by_text(self, element_value,text:(regular.compile,str),limit,recursive,index:(slice,int),**kwargs):#根据text定位
+        try:
+            limit = int(limit)
+        except:
+            limit = None
+        @self.add_base
+        def action(num,name,*args, **kwargs):
+            nonlocal self
+            iter_list = self.listSlicing(index,element_value)
+            paser_list = []
+            for bs in iter_list:
+                try:
+                    re = bs.find_all(text=text,limit=limit,recursive=recursive)
+                except:
+                    try:
+                        if type(text) is str:
+                            if str(bs.string) != text:raise Exception
+                        else:
+                            if not regular.match(text,str(bs.string)):raise Exception
+                        re = [bs]
+                    except:
+                        re = []
+                paser_list += re
+            self.element_dict[f'{name}[{num}]'] = paser_list
+        self.add_func(f'findAll_by_text:{element_value}[{index}]', action)  # 添加func
+
+    def __get_other_base(self,element_value,index:(slice,int),who='children',**kwargs):#获得子、后代、兄弟标签的基类
+        @self.add_base
+        def action(num,name,*args, **kwargs):
+            nonlocal self
+            iter_list = self.listSlicing(index, element_value)
+            paser_list = []
+            for bs in iter_list:
+                if who != 'brothers':
+                    paser_list += {'children':bs.children,'offspring':bs.descendants,'down':bs.next_siblings,
+                                   'up':bs.previous_siblings}.get(who,bs.children)
+                else:
+                    paser_list += bs.previous_siblings
+                    paser_list += bs.next_siblings
+            self.element_dict[f'{name}[{num}]'] = list(set(paser_list))
+        self.add_func(f'get_{who}:{element_value}[{index}]', action)  # 添加func
+
+    def get_children(self,element_value,index:(slice,int),**kwargs):
+        return self.__get_other_base(element_value,index)
+
+    def get_offspring(self,element_value,index:(slice,int),**kwargs):
+        return self.__get_other_base(element_value,index,'offspring')
+
+    def get_up(self,element_value,index:(slice,int),**kwargs):
+        return self.__get_other_base(element_value,index,'up')
+
+    def get_down(self,element_value,index:(slice,int),**kwargs):
+        return self.__get_other_base(element_value,index,'down')
+
+    def get_brothers(self,element_value,index:(slice,int),**kwargs):
+        return self.__get_other_base(element_value,index,'brothers')
+
+    def get_by_path(self,element_value,index:(slice,int),path,**kwargs):#根据bs4的目录选择
+        @self.add_base
+        def action(num,name,*args, **kwargs):
+            nonlocal self
+            iter_list = self.listSlicing(index, element_value)
+            paser_list = []
+            for bs in iter_list:
+                try:
+                    re = eval(str(path),{'self':bs})
+                    if re == None:raise Exception
+                    paser_list.append(re)
+                except:
+                    pass
+            self.element_dict[f'{name}[{num}]'] = paser_list
+        self.add_func(f'get>{path}:{element_value}[{index}]', action)  # 添加func
+
+    def Webpage_snapshot(self,**kwargs):
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            md5 = hashlib.md5()  # 应用MD5算法
+            md5.update(f'{time.time()}_{self.now_url}'.encode('utf-8'))
+            name = md5.hexdigest()
+            with open(self.dir + '/' + name + '.png.CoTanURL','w') as f:
+                f.write(self.now_url)
+            self.browser.save_screenshot(self.dir + '/' + name + '.png')
+            sleep(1)
+        self.add_func(f'Webpage_snapshot', action)  # 添加func
+
+    def add_url(self, element_value, index: (slice, int), url_name,update_func,url_args:dict, **kwargs):# 自动添加url
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            iter_list = self.listSlicing(index, element_value)
+            for bs in iter_list:
+                try:
+                    if url_name == '$name&':
+                        new_url = bs.name
+                    elif url_name == '$self&':
+                        new_url = str(bs).replace('\n', '')
+                    elif url_name == '$string$':
+                        new_url = str(bs.string).replace('\n', '')
+                    else:
+                        new_url = bs.attrs.get(url_name, '')
+                    url.add_url(new_url, **url_args)
+                except:
+                    pass
+            update_func()#更新tkinter
+        self.add_func(f'add_URL<{element_value}[{index}]:{url_name}', action)  # 添加func
+
+    def to_json(self,**kwargs):
+        @self.add_base
+        def action(num, name, *args, **kwargs):
+            nonlocal self
+            self.element_dict[f'{name}[{num}]'] = [self.browser.json()]#request 解析为 json
+        self.add_func(f'to_json', action)  # 添加func
+
+    def make_ActionChains(self,**kwargs):#创建动作链
+        @self.add_base
+        def action(num,name,*args, **kwargs):
+            nonlocal self
+            self.element_dict[f'{name}[{num}]'] = [ActionChains(self.browser)]
+        self.add_func(f'make_ActionChains', action)  # 添加func
+
+    def ActionChains_click(self,Chains,element_value,index,**kwargs):#单击左
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[Chains][0].click(self.element_dict[element_value][index])
+        self.add_func(f'[{Chains}]click>[{element_value}][{index}]', action)  # 添加func
+
+    def ActionChains_double_click(self,Chains,element_value,index,**kwargs):#双击左
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[Chains][0].double_click(self.element_dict[element_value][index])
+        self.add_func(f'[{Chains}]double_click>[{element_value}][{index}]', action)  # 添加func
+
+    def ActionChains_click_right(self,Chains,element_value,index,**kwargs):#点击右
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[Chains][0].context_click(self.element_dict[element_value][index])
+        self.add_func(f'[{Chains}]right_click>[{element_value}][{index}]', action)  # 添加func
+
+    def ActionChains_click_and_hold(self,Chains,element_value,index,**kwargs):#按住左
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[Chains][0].click_and_hold(self.element_dict[element_value][index])
+        self.add_func(f'[{Chains}]click_and_hold>[{element_value}][{index}]', action)  # 添加func
+
+    def ActionChains_release(self,Chains,element_value,index,**kwargs):#松开左键
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[Chains][0].release(self.element_dict[element_value][index])
+        self.add_func(f'[{Chains}]release>[{element_value}][{index}]', action)  # 添加func
+
+    def ActionChains_drag_and_drop(self,Chains,element_value,index,element_value2,index2,**kwargs):#拽托、松开
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[Chains][0].drag_and_drop(self.element_dict[element_value][index],
+                                                       self.element_dict[element_value2][index2])
+        self.add_func(f'[{Chains}]drag_and_drop>[{element_value}][{index}]', action)  # 添加func
+
+    def ActionChains_move(self,Chains,element_value,index,**kwargs):#移动鼠标
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[Chains][0].move_to_element(self.element_dict[element_value][index])
+        self.add_func(f'[{Chains}]drag_and_drop>[{element_value}][{index}]', action)  # 添加func
+
+    def Special_keys(self,key:str,is_special_keys):  # 装饰器
+        if is_special_keys:
+            return keys_name_dict.get(key.lower(), key),f'[{key.upper()}]'
+        else:
+            return key,key
+
+    def ActionChains_key_down(self,Chains,key,element_value,index,is_special_keys,**kwargs):#down
+        new_key,key = self.Special_keys(key,is_special_keys)
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[Chains][0].key_down(new_key,self.element_dict[element_value][index])
+        self.add_func(f'[{Chains}]key_down>{key}:[{element_value}][{index}]', action)  # 添加func
+
+    def ActionChains_key_up(self,Chains,key,element_value,index,is_special_keys,**kwargs):#down
+        new_key, key = self.Special_keys(key, is_special_keys)
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[Chains][0].key_up(new_key,self.element_dict[element_value][index])
+        self.add_func(f'[{Chains}]key_up>{key}:[{element_value}][{index}]', action)  # 添加func
+
+    def ActionChains_send_keys_to_element(self,Chains,key,element_value,index,is_special_keys,**kwargs):#发送到指定元素
+        new_key, key = self.Special_keys(key, is_special_keys)
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[Chains][0].send_keys_to_element(self.element_dict[element_value][index],new_key)
+        self.add_func(f'[{Chains}]sent>{key}:[{element_value}][{index}]', action)  # 添加func
+
+    def ActionChains_send_keys(self,Chains,key,is_special_keys,**kwargs):#发送到焦点元素
+        new_key, key = self.Special_keys(key, is_special_keys)
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[Chains][0].send_keys(new_key)
+        self.add_func(f'[{Chains}].sent>{key}', action)  # 添加func
+
+    def ActionChains_run(self,Chains,run_time=1,**kwargs):#执行
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.element_dict[Chains][0].perform()
+            sleep(run_time)
+        self.add_func(f'[{Chains}].run<{run_time}s', action)  # 添加func
+
+    def get_all_windows(self,*args,**kwargs):#获取所有句柄
+        @self.add_base
+        def find(browser, num, name, *args, **kwargs):
+            nonlocal self
+            if browser == None:browser = self.browser
+            self.element_dict[f'{name}[{num}]'] = browser.window_handles#获得窗口句柄
+        self.add_func(f'get_all_windows',find)#添加func
+
+    def get_now_windows(self,*args,**kwargs):#获取当前窗口句柄
+        @self.add_base
+        def find(browser, num, name, *args, **kwargs):
+            nonlocal self
+            if browser == None:browser = self.browser
+            self.element_dict[f'{name}[{num}]'] = [browser.current_window_handle]#获得当前窗口句柄
+        self.add_func(f'get_now_window',find)#添加func
+
+    def switch_to_windwos(self,element_value,index=0,**kwargs):#切换窗口
+        @self.add_base
+        def action(*args, **kwargs):
+            nonlocal self
+            self.browser.switch_to.window(self.element_dict[element_value][index])
+        self.add_func(f'switch_to_window>{element_value}[{index}]', action)  # 添加func
+
+    def Element_interaction(self,update_func=lambda *args:None):#元素交互
+        func_list = self.func_list
+        status = None
+        self.log.write(f'{"*"*5}url:{self.now_url}{"*"*5}')
+        def update(func_name):
+            nonlocal status,self
+            if status:
+                success_code = 'Success to run'
+            elif status == None:
+                success_code = 'No status'
+            else:
+                success_code = 'Wrong to run'
+            self.log.write(f'last:[{success_code}];now:[{func_name}];url:{self.now_url} [END]')
+            value_box = []
+            for i in self.element_dict:
+                try:
+                    value_box.append(f'{i}[{len(i)}] = {self.element_dict[i]}')
+                except:
+                    value_box.append(f'{i} = {self.element_dict[i]}')
+            update_func(func_name, success_code, value_box)  # 信息更新系统
+        update('start')
+        for func_num in range(len(func_list)):
+            func_name = func_list[func_num]
+            update(func_name)
+            status = self.func_dict[func_name](num=f'{func_num}',name='var')
+        update('Finish')

+ 86 - 0
Crawler/Information_storage.py

@@ -0,0 +1,86 @@
+import os
+import time
+
+class Database:
+    def __init__(self,name):
+        self.dir = rf'{os.getcwd()}/Database_dir/{name}.cotanDB'#创建DB文件
+        self.file = open(self.dir,'r+' if os.path.exists(self.dir) else 'w+')
+        self.id = 0
+        self.name = name
+        for _ in self.file.readlines():
+            self.id += 1
+
+    def __str__(self):
+        return self.name
+
+    def close(self):
+        try:
+            self.file.close()
+        except:
+            pass
+
+    def add_new(self,data):
+        data_str = str(self.id)
+        for i in data:
+            data_str += ',' + str(i)
+        data_str += '\n'
+        self.file.write(data_str)
+        self.file.flush()
+        self.id += 1
+
+    def remove(self):
+        self.file.close()
+        os.remove(self.dir)
+
+    def out_file(self,out_dir):
+        with open(out_dir + fr'/{self.name}.contanDB','w') as f:
+            with open(self.dir) as g:
+                f.write(g.read())
+
+class DataBase_Home:# data base控制器
+    def __init__(self):
+        self.database = {}
+
+    def add_DataBase(self,name):# 添加数据表
+        self.database[name] = Database(name)
+
+    def add_new(self,name,data):# 添加新内容
+        database = self.database.get(name)
+        if database == None:
+            self.add_DataBase(name)
+            database = self.database.get(name)
+        database.add_new(data)
+
+    def close(self,name):# 关闭数据表
+        try:
+            self.database[name].close()
+            del self.database[name]
+        except:
+            pass
+
+    def close_all(self):# 关闭所有数据表
+        for i in self.database:
+            self.database[i].close()
+        self.database = {}
+
+    def rm_dataBase(self,name):# 删除数据表
+        self.database[name].remove()
+        del self.database[name]
+
+    def out(self,name,dir):# 输出数据表
+        self.database[name].out_file(dir)
+
+    def return_database(self):
+        return list(self.database.keys())
+
+class log:
+    def __init__(self,log_dir):
+        self.log_dir = log_dir
+        self.log_file = open(log_dir + '/log.coTanLog','r+' if os.path.exists(log_dir + 'log.coTanLog') else 'w+')
+
+    def write(self,data):
+        self.log_file.write(f"[{time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))}] " + data + '\n')
+        self.log_file.flush()
+
+    def close(self):
+        self.log_file.close()

+ 959 - 0
Crawler/Web_Crawler.py

@@ -0,0 +1,959 @@
+from Crawler import Crawler_controller
+import os
+import tkinter
+from tkinter.filedialog import askdirectory
+import re
+import threading
+
+
+def Main():
+    global top,Git,PATH,bg,bbg,fg,cookies_list,Attributes_Dict,DataBase_list
+    DataBase_list = []
+    Attributes_Dict = {}
+    PATH = os.getcwd()
+    top = tkinter.Tk()
+    cookies_list = []
+    bg = '#FFFAFA'  # 主颜色
+    bbg = '#FFFAFA'  # 按钮颜色
+    fg = '#000000'  # 文字颜色
+    top["bg"] = bg
+    FONT = ('黑体', 11)  # 设置字体
+    top.title('CoTan自动化网页')
+    top.resizable(width=False, height=False)
+    top.geometry('+10+10')  # 设置所在位置
+
+    width_B = 13  # 标准宽度
+    height_B = 2
+    a_y = 0
+    a_x = 0
+
+    tkinter.Button(top, bg=bbg, fg=fg, text='添加url对象',command=add_url , font=FONT, width=width_B,
+                   height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='删除url对象',command=del_url , font=FONT, width=width_B,
+                   height=height_B).grid(column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='应用过滤机制', font=FONT, width=width_B,
+                   height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    global URL_BOX,URL_Input,Func_BOX
+    a_y += 1
+    tkinter.Label(top, text='添加url:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    URL_Input = tkinter.Entry(top, width=width_B * 2)
+    URL_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    global URL_ARGS,UA_Input,use_Cookies_Input,FUNC_Input,DATA_Input,TimeOut_Input
+    a_y += 1
+    URL_ARGS = []
+    lable = ['不加载js','不加载java','不加载插件']#复选框
+    for i in range(3):
+        URL_ARGS.append(tkinter.IntVar())
+        tkinter.Checkbutton(top,bg = bg,fg = fg,activebackground=bg,activeforeground=fg,selectcolor=bg, text=lable[i],
+                            variable=URL_ARGS[-1]).grid(column=a_x+i, row=a_y, sticky=tkinter.W)
+
+    a_y += 1
+    lable = ['第一次启动','隐藏网页','不加载图片']#复选框
+    for i in range(3):
+        URL_ARGS.append(tkinter.IntVar())
+        tkinter.Checkbutton(top,bg = bg,fg = fg,activebackground=bg,activeforeground=fg,selectcolor=bg, text=lable[i],
+                            variable=URL_ARGS[-1]).grid(column=a_x+i, row=a_y, sticky=tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='UA设置:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    UA_Input = tkinter.Entry(top, width=width_B * 2)
+    UA_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='DATA:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    DATA_Input = tkinter.Entry(top, width=width_B * 2)
+    DATA_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='请求方式:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    FUNC_Input = tkinter.Entry(top, width=width_B * 2)
+    FUNC_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='请求超时:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    TimeOut_Input = tkinter.Entry(top, width=width_B * 2)
+    TimeOut_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='Cookies:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    use_Cookies_Input = tkinter.Entry(top, width=width_B)
+    use_Cookies_Input.grid(column=a_x + 1, row=a_y, sticky=tkinter.E + tkinter.W)
+    URL_ARGS.append(tkinter.IntVar())
+    tkinter.Checkbutton(top, bg=bg, fg=fg, activebackground=bg, activeforeground=fg, selectcolor=bg, text='新启动网页',
+                        variable=URL_ARGS[-1]).grid(column=a_x + 2, row=a_y, sticky=tkinter.W)
+
+    a_y += 1
+    URL_BOX = tkinter.Listbox(top, width=width_B * 3, height=height_B * 4)
+    URL_BOX.grid(column=a_x, row=a_y, columnspan=3, rowspan=4, sticky=tkinter.E + tkinter.W + tkinter.S + tkinter.N)
+
+    a_y += 4
+    tkinter.Button(top, bg=bbg, fg=fg, text='HTTPS过滤器',command=add_filter_func_HTTPS, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='WWW过滤器',command=add_filter_func_WWW, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='删除过滤器',command=del_func, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='自定义过滤器',command=add_filter_func_HTTPS, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y,columnspan=2, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='清空过滤器', font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    global Func_BOX,cookies_fixed
+    a_y += 1
+    Func_BOX = tkinter.Listbox(top, width=width_B * 3, height=height_B * 3)
+    Func_BOX.grid(column=a_x, row=a_y, columnspan=3, rowspan=3, sticky=tkinter.E + tkinter.W + tkinter.S + tkinter.N)
+
+    global wait_Func_BOX,Wait_Input,cookies_BOX
+    a_y += 3
+    tkinter.Button(top, bg=bbg, fg=fg, text='单点爬虫运行',command=startDownloader, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='爬虫运行',command=Crawler_Run, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='单点爬虫停止',command=Crawler_Stop, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    cookies_fixed = tkinter.Variable()
+    tkinter.Label(top, text='【曲奇监视】', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(
+        column=a_x+1,row=a_y,sticky=tkinter.E + tkinter.W + tkinter.W + tkinter.S + tkinter.N)  # 设置说明
+    tkinter.Checkbutton(top, bg=bg, fg=fg, activebackground=bg, activeforeground=fg, selectcolor=bg, text='固定曲奇',
+                        variable=cookies_fixed).grid(column=a_x + 2, row=a_y, sticky=tkinter.W)
+    cookies_fixed.set('0')
+
+    a_y += 1
+    cookies_BOX = tkinter.Listbox(top, width=width_B * 3, height=height_B * 3)
+    cookies_BOX.grid(column=a_x, row=a_y, columnspan=3, rowspan=3, sticky=tkinter.E + tkinter.W + tkinter.S + tkinter.N)
+
+    a_y += 3
+    tkinter.Button(top, bg=bbg, fg=fg, text='清空曲奇',command=Tra_cookies, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='更新曲奇',command=Update_cookies, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='删除曲奇',command=Del_cookies, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    global cookies_Input,PAGE_BOX
+    a_y += 1
+    cookies_Input = tkinter.Entry(top, width=width_B * 3)
+    cookies_Input.grid(column=a_x, row=a_y, columnspan=3, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='添加曲奇',command=Add_cookies, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_x += 3
+    tkinter.Label(top, text='', bg=bg, fg=fg, font=FONT, width=1).grid(column=a_x, row=a_y)  # 设置说明
+    a_x += 1
+    a_y = 0
+
+    tkinter.Button(top, bg=bbg, fg=fg, text='根据id搜查',command=lambda :Page_Parser_addFindFunc('id'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='根据name搜查',command=lambda :Page_Parser_addFindFunc('name'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='根据class搜查',command=lambda :Page_Parser_addFindFunc('class'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='根据xpath搜查',command=lambda :Page_Parser_addFindFunc('xpath'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='根据css搜查',command=lambda :Page_Parser_addFindFunc('css'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='根据元素名搜查',command=lambda :Page_Parser_addFindFunc('tag'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    global search_all,search_Input,Parser_Func_BOX
+    a_y += 1
+    search_all = tkinter.Variable()
+    tkinter.Button(top, bg=bbg, fg=fg, text='根据link搜查',command=lambda :Page_Parser_addFindFunc('link'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='link模糊搜查',command=lambda :Page_Parser_addFindFunc('partial_link'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Checkbutton(top, bg=bg, fg=fg, activebackground=bg, activeforeground=fg, selectcolor=bg, text='匹配全部',
+                        variable=search_all).grid(column=a_x + 2, row=a_y, sticky=tkinter.W)
+    search_all.set('0')
+
+    a_y += 1
+    tkinter.Label(top, text='搜查参数:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    search_Input = tkinter.Entry(top, width=width_B * 2)
+    search_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='删除方法',command=Del_Parser_Func, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y,columnspan=2 , sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='清空方法',command=Tra_Parser_Func, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    Parser_Func_BOX = tkinter.Listbox(top, width=width_B * 3, height=height_B * 5)
+    Parser_Func_BOX.grid(column=a_x, row=a_y, columnspan=3, rowspan=5, sticky=tkinter.E + tkinter.W + tkinter.S + tkinter.N)
+
+    global Var_Input,VarIndex_Input,Send_Input,UserPW_Input,SELE_Input,JS_Input,Time_Input
+    a_y += 5
+    tkinter.Label(top, text='操作元素:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    Var_Input = tkinter.Entry(top, width=width_B * 2)
+    Var_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='操作索引:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    VarIndex_Input = tkinter.Entry(top, width=width_B * 2)
+    VarIndex_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='发送信息:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    Send_Input = tkinter.Entry(top, width=width_B * 2)
+    Send_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='认证用户名:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    UserName_Input = tkinter.Entry(top, width=width_B * 2)
+    UserName_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='认证密码:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    UserPW_Input = tkinter.Entry(top, width=width_B * 2)
+    UserPW_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='选择参数:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    SELE_Input = tkinter.Entry(top, width=width_B * 2)
+    SELE_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='等待时间:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    Time_Input = tkinter.Entry(top, width=width_B * 2)
+    Time_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='JavaScript:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    JS_Input = tkinter.Entry(top, width=width_B * 2)
+    JS_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='发送字符',command=lambda :Page_Parser_addActionFunc('send_keys'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='清空字符',command=lambda :Page_Parser_addActionFunc('clear'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='提交表单',command=lambda :Page_Parser_addActionFunc('submit'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='点击按钮',command=lambda :Page_Parser_addActionFunc('click'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='取得源代码',command=lambda :Page_Parser_addActionFunc('get_Page'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='输出HTML',command=lambda :Page_Parser_addActionFunc('out'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='切换Frame(id)',command=Page_Parser_addFrameFunc_id, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='切换Frame',command=lambda :Page_Parser_addFindFunc('frame'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='定位焦点元素',command=lambda :Page_Parser_addFindFunc('active_element'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='捕获弹窗',command=lambda :Page_Parser_addFindFunc('alert'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='回到主Frame',command=lambda :Page_Parser_addFrameFunc_FP(False), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='回到父Frame',command=lambda :Page_Parser_addFrameFunc_FP(True), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='弹出框认证',command=lambda :Page_Parser_addActionFunc('User_Passwd'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='弹出框确定',command=lambda :Page_Parser_addActionFunc('accept'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='弹出框取消',command=lambda :Page_Parser_addActionFunc('dismiss'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='取消选择index',command=lambda :Page_Parser_addActionFunc('deselect_by_index'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='取消选择text',command=lambda :Page_Parser_addActionFunc('deselect_by_text'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='取消选择value',command=lambda :Page_Parser_addActionFunc('deselect_by_value'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='选择index',command=lambda :Page_Parser_addActionFunc('select_by_index'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='选择text',command=lambda :Page_Parser_addActionFunc('select_by_text'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='选择value',command=lambda :Page_Parser_addActionFunc('select_by_value'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_x += 3
+    tkinter.Label(top, text='', bg=bg, fg=fg, font=FONT, width=1).grid(column=a_x, row=a_y)  # 设置说明
+    a_x += 1
+    a_y = 0
+
+    global Func_Output,Status_Output,FuncValue_BOX
+    Func_Output = tkinter.StringVar()
+    Status_Output = tkinter.StringVar()
+    tkinter.Label(top, text='正在执行:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    tkinter.Entry(top, width=width_B * 2, state=tkinter.DISABLED,textvariable=Func_Output).grid(
+        column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='上一次状态:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    tkinter.Entry(top, width=width_B * 2, state=tkinter.DISABLED,textvariable=Status_Output).grid(
+        column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    FuncValue_BOX = tkinter.Listbox(top, width=width_B * 3, height=height_B * 5)
+    FuncValue_BOX.grid(column=a_x, row=a_y, columnspan=3, rowspan=5, sticky=tkinter.E + tkinter.W + tkinter.S + tkinter.N)
+
+    global CookiesName_Input,Cookies_Input,Tag_Input,AttributesName_Input,AttributesValue_Input
+    global FindAllText_Input,text_re,attribute_re,limit_Input,recursive_Input,FindAllPATH_Input,Attributes_BOX
+
+    a_y += 5
+    tkinter.Label(top, text='cookies名:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    CookiesName_Input = tkinter.Entry(top, width=width_B * 2)
+    CookiesName_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='cookies:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    Cookies_Input = tkinter.Entry(top, width=width_B * 2)
+    Cookies_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='定位标签:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,
+                                                                                                      row=a_y)
+    Tag_Input = tkinter.Entry(top, width=width_B * 2)
+    Tag_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='定位属性名:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,
+                                                                                                      row=a_y)
+    AttributesName_Input = tkinter.Entry(top, width=width_B * 2)
+    AttributesName_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    attribute_re = tkinter.IntVar()
+    a_y += 1
+    tkinter.Label(top, text='定位属性值:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,
+                                                                                                      row=a_y)
+    AttributesValue_Input = tkinter.Entry(top, width=width_B)
+    AttributesValue_Input.grid(column=a_x + 1,columnspan=2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='添加属性',command=add_Attributes, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='删除属性',command=del_Attributes, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='清空属性',command=tra_Attributes, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    Attributes_BOX = tkinter.Listbox(top, width=width_B * 3, height=height_B * 3)
+    Attributes_BOX.grid(column=a_x, row=a_y, columnspan=3, rowspan=3, sticky=tkinter.E + tkinter.W + tkinter.S + tkinter.N)
+
+    a_y += 3
+    tkinter.Label(top, text='定位文本:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,
+                                                                                                      row=a_y)
+    FindAllText_Input = tkinter.Entry(top, width=width_B)
+    FindAllText_Input.grid(column=a_x + 1,columnspan=2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    recursive_Input = tkinter.IntVar()
+    text_re = tkinter.IntVar()
+    a_y += 1
+    tkinter.Checkbutton(top, bg=bg, fg=fg, activebackground=bg, activeforeground=fg, selectcolor=bg, text='递归查找',
+                        variable=recursive_Input).grid(column=a_x, row=a_y, sticky=tkinter.W)
+    tkinter.Checkbutton(top, bg=bg, fg=fg, activebackground=bg, activeforeground=fg, selectcolor=bg, text='文本使用正则',
+                        variable=text_re).grid(column=a_x + 1, row=a_y, sticky=tkinter.W)
+    tkinter.Checkbutton(top, bg=bg, fg=fg, activebackground=bg, activeforeground=fg, selectcolor=bg, text='属性值使用正则',
+                        variable=attribute_re).grid(column=a_x + 2, row=a_y, sticky=tkinter.W)
+    attribute_re.set(1)
+    text_re.set('1')
+    recursive_Input.set('1')
+
+    a_y += 1
+    tkinter.Label(top, text='查找个数:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,
+                                                                                                      row=a_y)
+    limit_Input = tkinter.Entry(top, width=width_B * 2)
+    limit_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='定位路径:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,
+                                                                                                      row=a_y)
+    FindAllPATH_Input = tkinter.Entry(top, width=width_B * 2)
+    FindAllPATH_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='删除所有曲奇',command=lambda :Page_Parser_addActionFunc2('del_all_cookies'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='删除指定曲奇',command=lambda :Page_Parser_addActionFunc2('del_cookies'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='添加新的曲奇',command=lambda :Page_Parser_addActionFunc2('add_cookies'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='更新指定曲奇',command=lambda :Page_Parser_addActionFunc2('update_cookies'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='获得所有曲奇',command=lambda :Page_Parser_addActionFunc2('get_cookies'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='获得指定曲奇',command=lambda :Page_Parser_addActionFunc2('get_all_cookies'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='解析网页',command=lambda :Page_Parser_addActionFunc2('make_bs'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='根据标签定位',command=lambda :Page_Parser_addActionFunc2('findAll'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='根据文本定位',command=lambda :Page_Parser_addActionFunc2('findAll_by_text'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='获得子标签',command=lambda :Page_Parser_addActionFunc2('get_children'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='获得后代标签',command=lambda :Page_Parser_addActionFunc2('get_offspring'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='获得弟标签',command=lambda :Page_Parser_addActionFunc2('get_down'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='获得兄标签',command=lambda :Page_Parser_addActionFunc2('get_up'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='获得兄弟标签',command=lambda :Page_Parser_addActionFunc2('brothers'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='路径定位',command=lambda :Page_Parser_addActionFunc2('get_by_path'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_x += 3
+    tkinter.Label(top, text='', bg=bg, fg=fg, font=FONT, width=1).grid(column=a_x, row=a_y)  # 设置说明
+    a_x += 1
+    a_y = 0
+
+    tkinter.Label(top, text='【数据库操作】', bg=bg, fg=fg, font=FONT).grid(column=a_x, row=a_y,columnspan=3)  # 设置说明
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='元素式存入',command=lambda :to_Database(True), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='正则式存入',command=lambda :to_Database(False), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='新增数据表',command=add_DataBase, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='删除数据表',command=remove_DataBase, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='导出数据表',command=out, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='关闭数据表', command=close, font=FONT,
+                   width=width_B, height=height_B).grid(column=a_x + 2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    global Data_Input,DataBase_BOX,DataName_Input,URLTAG_Input
+    a_y += 1
+    tkinter.Label(top, text='数据存入格式:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    Data_Input = tkinter.Entry(top, width=width_B * 2)
+    Data_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='数据表名字:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    DataName_Input = tkinter.Entry(top, width=width_B * 2)
+    DataName_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    DataBase_BOX = tkinter.Listbox(top, width=width_B * 3, height=height_B * 5)
+    DataBase_BOX.grid(column=a_x, row=a_y, columnspan=3, rowspan=5, sticky=tkinter.E + tkinter.W + tkinter.S + tkinter.N)
+
+    a_y += 5
+    tkinter.Label(top, text='URL标签:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    URLTAG_Input = tkinter.Entry(top, width=width_B * 2)
+    URLTAG_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='导出页面快照',command=lambda :Page_Parser_addActionFunc2('png'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='回调添加URL',command=add_url_from_tag, font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='解析为json', command=lambda :Page_Parser_addActionFunc2('to_json'), font=FONT,
+                   width=width_B, height=height_B).grid(column=a_x + 2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    global Special_keys,Chains_Input,element_value2_Input,index2_Input,run_time,key_Input
+
+    a_y += 1
+    tkinter.Label(top, text='操作动作链:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    Chains_Input = tkinter.Entry(top, width=width_B * 2)
+    Chains_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='拽拖至元素:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    element_value2_Input = tkinter.Entry(top, width=width_B * 2)
+    element_value2_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='拽拖索引:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    index2_Input = tkinter.Entry(top, width=width_B * 2)
+    index2_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='键入值:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    key_Input = tkinter.Entry(top, width=width_B * 2)
+    key_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Label(top, text='运行时长:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
+    run_time = tkinter.Entry(top, width=width_B * 2)
+    run_time.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='点击左键',command=lambda :Page_Parser_addActionFunc3('click'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='双击左键',command=lambda :Page_Parser_addActionFunc3('double_click'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='点击右键', command=lambda :Page_Parser_addActionFunc3('click_right'), font=FONT,
+                   width=width_B, height=height_B).grid(column=a_x + 2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='按住左键',command=lambda :Page_Parser_addActionFunc3('click_and_hold'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='松开左键',command=lambda :Page_Parser_addActionFunc3('release'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='拽托元素', command=lambda :Page_Parser_addActionFunc2('drag_and_drop'), font=FONT,
+                   width=width_B, height=height_B).grid(column=a_x + 2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='移动鼠标',command=lambda :Page_Parser_addActionFunc3('move'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='按下按键',command=lambda :Page_Parser_addActionFunc3('key_down'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='抬起按键', command=lambda :Page_Parser_addActionFunc3('key_up'), font=FONT,
+                   width=width_B, height=height_B).grid(column=a_x + 2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    Special_keys = tkinter.IntVar()
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='发送文本到焦点',command=lambda :Page_Parser_addActionFunc3('send_keys'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='发送文本',command=lambda :Page_Parser_addActionFunc3('send_keys_to_element'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Checkbutton(top, bg=bg, fg=fg, activebackground=bg, activeforeground=fg, selectcolor=bg, text='转换为特殊按钮',
+                        variable=Special_keys).grid(column=a_x + 2, row=a_y, sticky=tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='生成动作链',command=lambda :Page_Parser_addActionFunc3('make_ActionChains'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='运行动作链',command=lambda :Page_Parser_addActionFunc3('ActionChains_run'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1,columnspan=2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='获取当前窗口',command=lambda :Page_Parser_addActionFunc('get_now_windows'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='获取所有窗口',command=lambda :Page_Parser_addActionFunc('get_all_windows'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='切换窗口', command=lambda :Page_Parser_addActionFunc('switch_to_windwos'), font=FONT,
+                   width=width_B, height=height_B).grid(column=a_x + 2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='暴力等待',command=lambda :Page_Parser_addActionFunc('wait_sleep'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='元素检查等待',command=lambda :Page_Parser_addActionFunc('set_wait'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='运行js',command=lambda :Page_Parser_addActionFunc('run_JS'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+    a_y += 1
+    tkinter.Button(top, bg=bbg, fg=fg, text='页面后退',command=lambda :Page_Parser_addActionFunc('back'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='页面刷新',command=lambda :Page_Parser_addActionFunc('refresh'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
+    tkinter.Button(top, bg=bbg, fg=fg, text='页面前进',command=lambda :Page_Parser_addActionFunc('forward'), font=FONT, width=width_B,height=height_B).grid(
+        column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
+
+
+    top.update()#要预先update一下,否则会卡住
+    global url,loader,Page_Parser,DataBase,save_dir
+    save_dir = askdirectory(title='选择项目位置')#项目位置
+    url = Crawler_controller.url(save_dir, save_dir)#url管理器
+    loader = Crawler_controller.Page_Downloader(url, save_dir)#页面下载器
+    Page_Parser = Crawler_controller.Page_Parser(loader)#页面解析器
+    DataBase = Crawler_controller.data_base#数据库
+
+    top.mainloop()
+    #关闭操作
+    loader.stop()
+    DataBase.close_all()
+    url.close()
+    loader.close()
+
+def to_Database(is_tag=True):
+    global VarIndex_Input,Var_Input,Data_Input,Page_Parser
+    try:
+        index = eval(VarIndex_Input.get(),{})
+    except:
+        index = slice(None,None)
+    if is_tag:
+        func = Page_Parser.to_Database
+    else:
+        func = Page_Parser.to_Database_by_re
+    func(element_value=Var_Input.get(),index=index,data = Data_Input.get(),dataBase_name=get_DataBase_Name())
+    Update_Parser_Func_BOX()
+
+def close():
+    global DataBase
+    name = get_DataBase_Name()
+    DataBase.close(name)
+    update_DataBase_BOX()
+
+def out():
+    global save_dir,DataBase
+    name = get_DataBase_Name()
+    DataBase.out(name,save_dir)
+    update_DataBase_BOX()
+
+def remove_DataBase():
+    global DataBase
+    name = get_DataBase_Name()
+    DataBase.rm_dataBase(name)
+    update_DataBase_BOX()
+
+def add_DataBase():
+    global DataName_Input,DataBase
+    name = DataName_Input.get()
+    DataBase.add_DataBase(name)
+    update_DataBase_BOX()
+
+def get_DataBase_Name():
+    global DataBase_BOX,DataBase_list
+    try:
+        return DataBase_list[DataBase_BOX.curselection()[0]]
+    except:
+        try:
+            return DataBase_list[0]
+        except:
+            return None
+
+def update_DataBase_BOX():
+    global DataBase_BOX,DataBase_list
+    DataBase_list = DataBase.return_database()
+    DataBase_BOX.delete(0,tkinter.END)
+    DataBase_BOX.insert(tkinter.END,*DataBase_list)
+
+def update_Status(now_func,status,Value_BOX):
+    global Func_Output,Status_Output,FuncValue_BOX
+    Func_Output.set(now_func)
+    Status_Output.set(status)
+    FuncValue_BOX.delete(0,tkinter.END)
+    FuncValue_BOX.insert(0,*Value_BOX)
+
+def tra_Attributes():
+    global Attributes_Dict
+    Attributes_Dict = {}
+    update_Attributes_BOX()
+
+def del_Attributes():
+    global Attributes_BOX, Attributes_Dict
+    del Attributes_Dict[list(Attributes_Dict.keys())[Attributes_BOX.curselection()[0]]]
+    update_Attributes_BOX()
+
+def add_Attributes():
+    global AttributesName_Input,AttributesValue_Input,attribute_re,Attributes_Dict
+    name = AttributesName_Input.get()
+    value = AttributesValue_Input.get()
+    if name == '' or value == '': return False
+    value = re.compile(value) if bool(attribute_re.get()) else value
+    Attributes_Dict[name] = value
+    update_Attributes_BOX()
+
+def update_Attributes_BOX():
+    global Attributes_BOX,Attributes_Dict
+    show = []
+    for i in Attributes_Dict:
+        show.append(f'{i} -> {Attributes_Dict[i]}')
+    Attributes_BOX.delete(0, tkinter.END)
+    Attributes_BOX.insert(tkinter.END,*show)
+
+def Func_Args3():#方法args统一转换(第三栏目)
+    global Special_keys, Chains_Input, element_value2_Input, index2_Input, run_time,Var_Input,VarIndex_Input,key_Input
+    try:
+        index = int(VarIndex_Input.get())
+    except:
+        index = 0
+    try:
+        index2 = int(index2_Input.get())
+    except:
+        index2 = 0
+    try:
+        time = int(run_time.get())
+    except:
+        time = 1
+    return dict(Chains=Chains_Input.get(),element_value=Var_Input.get(),index=index,element_value2=element_value2_Input.get(),
+                index2=index2,run_time=time,is_special_keys = bool(Special_keys.get()),key=key_Input.get())
+
+def Func_Args2():#方法args统一转换(第二栏目)
+    global CookiesName_Input,Cookies_Input,Tag_Input,Attributes_Dict,Var_Input,VarIndex_Input
+    global FindAllText_Input,text_re,limit_Input,recursive_Input,FindAllPATH_Input
+    try:
+        index = eval(VarIndex_Input.get(),{})
+    except:
+        index = slice(None,None)
+    try:
+        cookies = eval(Cookies_Input.get(),{})
+    except:
+        cookies = {}
+    return dict(element_value=Var_Input.get(),index=index,cookies_name=CookiesName_Input.get(),cookies=cookies,tag=Tag_Input.get().split(','),
+             attribute=Attributes_Dict,text=re.compile(FindAllText_Input.get()) if bool(text_re.get()) else FindAllText_Input.get(),
+             limit=limit_Input.get(),recursive=bool(recursive_Input.get()),path=FindAllPATH_Input.get())
+
+def Func_Args():#方法args统一转换(不支持Frame)
+    global Var_Input, VarIndex_Input, Send_Input, UserPW_Input, SELE_Input, JS_Input, Time_Input
+    try:
+        time = int(Time_Input.get())
+    except:
+        time = 2
+    try:
+        index = int(VarIndex_Input.get())
+    except:
+        index = 0
+    return dict(
+    element_value = Var_Input.get(),
+    index = index,
+    text = Send_Input.get(),
+    User = UserPW_Input.get(),
+    Passwd = UserPW_Input.get(),
+    deselect = SELE_Input.get(),
+    JS = JS_Input.get(),
+    time=time
+    )
+
+def Page_Parser_addActionFunc3(func):
+    global Page_Parser
+    args = Func_Args3()
+    FUNC = {'make_ActionChains':Page_Parser.make_ActionChains,'click':Page_Parser.ActionChains_click,
+            'double_click':Page_Parser.ActionChains_double_click,
+            'click_right':Page_Parser.ActionChains_click_right,'click_and_hold':Page_Parser.ActionChains_click_and_hold,
+            'release':Page_Parser.ActionChains_release,'drag_and_drop':Page_Parser.ActionChains_drag_and_drop,
+            'move':Page_Parser.ActionChains_move,'key_down':Page_Parser.ActionChains_key_down,
+            'key_up':Page_Parser.ActionChains_key_up,'send_keys_to_element':Page_Parser.ActionChains_send_keys_to_element,
+            'send_keys':Page_Parser.ActionChains_send_keys,'ActionChains_run':Page_Parser.ActionChains_run}.get(
+        func,Page_Parser.make_ActionChains)
+    FUNC(**args)
+    Update_Parser_Func_BOX()
+
+def Page_Parser_addActionFunc2(func):
+    global Page_Parser
+    args = Func_Args2()
+    FUNC = {'del_all_cookies':Page_Parser.del_all_cookies,'del_cookies':Page_Parser.del_cookies,'add_cookies':Page_Parser.add_cookies,
+            'update_cookies':Page_Parser.update_cookies,'get_cookies':Page_Parser.get_cookies,'get_all_cookies':Page_Parser.get_all_cookies,
+            'make_bs':Page_Parser.make_bs,'findAll':Page_Parser.findAll,'findAll_by_text':Page_Parser.findAll_by_text,
+            'get_children':Page_Parser.get_children,'get_offspring':Page_Parser.get_offspring,'get_up':Page_Parser.get_up,
+            'get_down':Page_Parser.get_down,'get_by_path':Page_Parser.get_by_path,'brothers':Page_Parser.get_brothers,
+            'png':Page_Parser.Webpage_snapshot,'to_json':Page_Parser.to_json}.get(func,Page_Parser.make_bs)
+    FUNC(**args)
+    Update_Parser_Func_BOX()
+
+def Page_Parser_addActionFunc(func):
+    global Page_Parser
+    args = Func_Args()
+    FUNC = {'send_keys':Page_Parser.send_keys,'clear':Page_Parser.clear,'click':Page_Parser.click,'User_Passwd':Page_Parser.User_Passwd,
+            'accept':Page_Parser.accept,'dismiss':Page_Parser.dismiss,'submit':Page_Parser.submit,'deselect_by_index':Page_Parser.deselect_by_index,
+            'deselect_by_value':Page_Parser.deselect_by_value,'deselect_by_text':Page_Parser.deselect_by_text,'select_by_index':Page_Parser.select_by_index,
+            'select_by_value':Page_Parser.select_by_value,'select_by_text':Page_Parser.select_by_text,'back':Page_Parser.back,'forward':Page_Parser.forward,
+            'refresh':Page_Parser.refresh,'wait_sleep':Page_Parser.wait_sleep,'set_wait':Page_Parser.set_wait,'run_JS':Page_Parser.run_JS,
+            'out':Page_Parser.out_html,'get_Page':Page_Parser.to_text,'get_all_windows':Page_Parser.get_all_windows,
+            'get_now_windows':Page_Parser.get_now_windows,'switch_to_windwos':Page_Parser.switch_to_windwos
+            }.get(func,Page_Parser.send_keys)
+    FUNC(**args)
+    Update_Parser_Func_BOX()
+
+def Page_Parser_addFrameFunc_FP(F=True):
+    global Page_Parser, search_Input
+    search = None if F else ''
+    Page_Parser.find_switch_to_frame(search,True)
+    Update_Parser_Func_BOX()
+
+def Page_Parser_addFrameFunc_id():
+    global Page_Parser, search_Input
+    search = search_Input.get()
+    Page_Parser.find_switch_to_frame(search,True)
+    Update_Parser_Func_BOX()
+
+def Page_Parser_addFindFunc(func):
+    global search_all, search_Input,Page_Parser
+    not_all = not(bool(search_all.get()))
+    search = search_Input.get()
+    FUNC = {'id':Page_Parser.find_ID,'name':Page_Parser.find_name,'class':Page_Parser.find_class,
+            'xpath':Page_Parser.find_xpath,'css':Page_Parser.find_css,'tag':Page_Parser.find_tag_name,
+            'link':Page_Parser.find_link_text,'partial_link':Page_Parser.find_partial_link_text,
+            'alert':Page_Parser.find_switch_to_alert,'active_element':Page_Parser.find_switch_to_active_element,
+            'frame':Page_Parser.find_switch_to_frame}.get(func,Page_Parser.find_ID)
+    FUNC(search,not_all=not_all)
+    Update_Parser_Func_BOX()
+
+def Del_Parser_Func():
+    global Page_Parser
+    try:
+        index = Parser_Func_BOX.curselection()[0]
+        Page_Parser.del_func(index,True)
+        Update_Parser_Func_BOX()
+    except:
+        pass
+
+def Tra_Parser_Func():
+    global Page_Parser
+    try:
+        Page_Parser.tra_func()
+        Update_Parser_Func_BOX()
+    except:
+        pass
+
+def Update_Parser_Func_BOX():
+    global Parser_Func_BOX,Page_Parser
+    Parser_Func_BOX.delete(0,tkinter.END)
+    Parser_Func_BOX.insert(tkinter.END, *Page_Parser.return_func(False)[::-1])
+
+def Update_cookies():
+    global cookies_BOX,cookies_list,cookies_Input
+    cookies = eval(cookies_Input.get(),{})
+    if cookies_fixed.get() == '0':return False
+    try:
+        name = cookies_list[cookies_BOX.curselection()[0]].get('name')
+        loader.update_cookies(name,cookies)
+        cookies_fixed.set('0')
+    except:
+        pass
+
+def Add_cookies():
+    global cookies_BOX,cookies_list,cookies_Input
+    cookies = eval(cookies_Input.get(),{})
+    if cookies_fixed.get() == '0':return False
+    try:
+        loader.Add_cookies(cookies)
+        cookies_fixed.set('0')
+    except:
+        raise
+
+def Tra_cookies():
+    global cookies_BOX,cookies_list
+    if cookies_fixed.get() == '0':return False
+    try:
+        loader.Tra_cookies()
+        cookies_fixed.set('0')
+    except:
+        pass
+
+def Del_cookies():
+    global cookies_BOX,cookies_list
+    if cookies_fixed.get() == '0':return False
+    try:
+        name = cookies_list[cookies_BOX.curselection()[0]].get('name')
+        print(name)
+        loader.Del_cookies(name)
+        cookies_fixed.set('0')
+    except:
+        pass
+
+def cookies_BOX_Update(cookies):
+    global cookies_BOX,cookies_list
+    if cookies_fixed.get() == '0':
+        cookies_list = cookies
+        cookies_BOX.delete(0,tkinter.END)
+        cookies_BOX.insert(0,*cookies)
+
+def Crawler_Stop():
+    global startLoader_Stop
+    startLoader_Stop = False
+    loader.stop()
+
+def Crawler_Run():
+    global startLoader_Stop
+    def startLoader():
+        global loader,Page_Parser,url,startLoader_Stop
+        loader.stop()#把之前的停止
+        while startLoader_Stop:
+            if url.finish():break
+            loader.strat_urlGet(func_cookie=cookies_BOX_Update)
+            update_URLBOX()
+            Page_Parser.Element_interaction(update_Status)
+        loader.stop()
+
+    startLoader_Stop = True
+    new = threading.Thread(target=startLoader)
+    new.start()
+    update_URLBOX()
+
+def startDownloader():
+    def startLoader():
+        global loader,Page_Parser
+        loader.strat_urlGet(func_cookie=cookies_BOX_Update)
+        update_URLBOX()
+        Page_Parser.Element_interaction(update_Status)
+        loader.stop()
+
+    new = threading.Thread(target=startLoader)
+    new.start()
+
+def add_filter_func_HTTPS():
+    global url
+    url.Add_func(lambda url:re.match(re.compile('^https://'),url),'HTTPS过滤')
+    update_Func_BOX()
+
+def add_filter_func_WWW():
+    global url
+    url.Add_func(lambda url:re.match(re.compile('.*www\.'),url),'www过滤')
+    update_Func_BOX()
+
+def del_func():
+    global URL_BOX
+    index = Func_BOX.curselection()[0]
+    url.Del_func(index)
+    update_Func_BOX()
+
+def update_Func_BOX():
+    global url,Func_BOX
+    Func_BOX.delete(0,tkinter.END)
+    Func_BOX.insert(tkinter.END,*url.return_func())
+
+def del_url():
+    global URL_BOX
+    index = URL_BOX.curselection()[0]
+    url.del_url(index)
+    update_URLBOX()
+
+def add_args():
+    global URL_ARGS, UA_Input, use_Cookies_Input,FUNC_Input,DATA_Input,TimeOut_Input
+    try:
+        data = eval(DATA_Input.get(),{})
+    except:
+        data = {}
+    try:
+        TimeOut = int(TimeOut_Input.get())
+    except:
+        TimeOut = 5
+    re = dict(
+        func = FUNC_Input.get(),
+        UA = UA_Input.get(),
+        cookies = use_Cookies_Input.get(),
+        data=data,
+        time_out=TimeOut
+        )
+    name = ['no_js','no_java','no_plugins','first_run','head','no_img','new']
+    for i in range(len(name)):
+        re[name[i]] = bool(URL_ARGS[i].get())
+    return re
+
+def add_url():
+    global URL_Input,url
+    args = add_args()
+    new_url = URL_Input.get()
+    if new_url == '':return
+    url.add_url(new_url,**args)
+    update_URLBOX()
+
+def add_url_from_tag():
+    global URLTAG_Input,Page_Parser,Var_Input
+    try:
+        index = eval(VarIndex_Input.get(),{})
+    except:
+        index = slice(None,None)
+    Page_Parser.add_url(element_value=Var_Input.get(),index=index,url_name=URLTAG_Input.get(),update_func=update_URLBOX,
+                        url_args=add_args())
+    Update_Parser_Func_BOX()
+
+def update_URLBOX():
+    global url,URL_BOX
+    URL_BOX.delete(0,tkinter.END)
+    URL_BOX.insert(tkinter.END,*url.return_url())

+ 2 - 0
Crawler/__init__.py

@@ -0,0 +1,2 @@
+from Crawler.Web_Crawler import Main
+print('自动化网页加载完成')

+ 0 - 45
Crawler_controller.py

@@ -1,45 +0,0 @@
-from selenium import webdriver
-
-class url:
-    num = 0#url处理器个数
-    def __init__(self,dic=f'',dic_run=f'',add_func=lambda url:True,change_url=lambda url:url):
-        url.num += 1
-        if dic == '':dic = f'url[{url.num}].cot_url'
-        if dic_run == '':dic = f'url_run[{url.num}].cot_url'
-        self.dir = dic
-        self.dir_run = dic_run
-        self.file = open(dic,'a')#写入url_history的文件
-        self.file_run = open(dic_run,'a')#写入已读url文件
-        self.url_list = []#待读url
-        self.add_func = add_func#url添加过滤方法
-        self.change_url = change_url#url更正方法
-        self.url_history = []#url历史
-
-    def add_url(self,url):
-        url = self.change_url(url)#url更正,比如http替换https
-        if url not in self.url_history and self.add_func(url):#1.url不存在历史,2.url满足筛选条件
-            self.url_list.append(url)
-            self.url_history.append(url)
-            self.__out_url(url)
-            return True#写入成功
-        return False#写入失败
-
-    def get_url(self):
-        url = self.url_list[0]
-        self.__out_url_run(url)
-        del self.url_list[0]
-        return url
-
-    def __out_url(self,url):#输出url
-        self.file.write(f'{url}\n')
-        self.file.flush()
-
-    def __out_url_run(self,url):#输出url
-        self.file_run.write(f'{url}\n')
-        self.file_run.flush()
-
-    def return_url(self):
-        return self.url_list.copy()
-
-    def return_url_history(self):
-        return self.url_history.copy()

+ 5 - 5
Git_controller/GIT.py

@@ -213,7 +213,7 @@ def Main():
     tkinter.Button(top, bg=bbg, fg=fg, text='合并分支', command=switch_Branch, font=FONT, width=width_B,
                    height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
 
-    no_ff = tkinter.Variable()
+    no_ff = tkinter.IntVar()
     a_y += 1
     tkinter.Button(top, bg=bbg, fg=fg, text='合并分支', command=merge_Branch, font=FONT, width=width_B,
                    height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
@@ -231,8 +231,8 @@ def Main():
     tkinter.Button(top, bg=bbg, fg=fg, text='从远程仓库抓取', command=lambda :Pull_Push_remote(0), font=FONT, width=width_B,
                    height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
 
-    push_bind = tkinter.Variable()
-    allow_history = tkinter.Variable()
+    push_bind = tkinter.IntVar()
+    allow_history = tkinter.IntVar()
     a_y += 1
     tkinter.Button(top, bg=bbg, fg=fg, text='分支绑定', command=Bind_remote, font=FONT, width=width_B,
                    height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
@@ -294,8 +294,8 @@ def Main():
 
     global Customize_Input, th_do, wait_do
     a_y += 1
-    th_do = tkinter.Variable()
-    wait_do = tkinter.Variable()
+    th_do = tkinter.IntVar()
+    wait_do = tkinter.IntVar()
     tkinter.Checkbutton(top, bg=bg, fg=fg, activebackground=bg, activeforeground=fg, selectcolor=bg, text='多进程刷新',
                         variable=th_do).grid(column=0, row=a_y, sticky=tkinter.W)
     tkinter.Checkbutton(top, bg=bg, fg=fg, activebackground=bg, activeforeground=fg, selectcolor=bg, text='异步显示',

+ 17 - 7
Hello.py

@@ -50,7 +50,7 @@ def Machine_Learning():
     Main()
 
 def MLA():
-    global top, DsGC
+    global top, Mla
     Mla = Process(target=Machine_Learning)
     Mla.start()
 
@@ -63,6 +63,16 @@ def GIT_Ctrl():
     Git = Process(target=Git_Ctrl)
     Git.start()
 
+def Crawler_Main():
+    from Crawler import Main
+    Main()
+
+def Crawlef_Run():
+    global top, crawlef
+    crawlef = Process(target=Crawler_Main)
+    crawlef.start()
+
+
 def Main():
     global top
     import tkinter
@@ -92,12 +102,12 @@ def Main():
     bg = '#FFFFFF'
     bc = 'tcross'
     #标题
-    tkinter.Label(F1, text='CoTan~NOTE', width=20,bg='#FFFFFF', font=ft).grid(column=0, row=0,sticky=tkinter.N)  # 设置说明
-    tkinter.Label(F1, text='私人笔记',bg=abg,font=ft1).grid(column=0, row=1,sticky=tkinter.W + tkinter.E)
-    tkinter.Button(F1,text='Git仓库控制器',cursor=bc,command=GIT_Ctrl,height=2,font=ft2,bg=bg,activebackground=abg,bd=0,justify=tkinter.LEFT).grid(column =0,row = 2,sticky=tkinter.N + tkinter.E + tkinter.W)
-    tkinter.Button(F1, text='画图板',cursor=bc,command=Draw, height=2, font=ft2, bg=bg,activebackground=abg, bd=0, justify=tkinter.LEFT).grid(column=0, row=3,sticky=tkinter.N + tkinter.E + tkinter.W)
-    tkinter.Button(F1, text='爬虫系统',cursor=bc, height=1, font=ft2, bg=bg,activebackground=abg, bd=0, justify=tkinter.LEFT).grid(column=0, row=4,sticky=tkinter.N + tkinter.E + tkinter.W)
-    tkinter.Button(F1, text='我的寄忆',cursor=bc, height=1, font=ft2, bg=bg,activebackground=abg, bd=0, justify=tkinter.LEFT).grid(column=0, row=5,sticky=tkinter.N + tkinter.E + tkinter.W)
+    tkinter.Label(F1, text='CoTan~科学计算', width=20,bg='#FFFFFF', font=ft).grid(column=0, row=0,sticky=tkinter.N)  # 设置说明
+    tkinter.Label(F1, text='寄忆学术',bg=abg,font=ft1).grid(column=0, row=1,sticky=tkinter.W + tkinter.E)
+    tkinter.Button(F1,text='我的寄忆',cursor=bc,height=2,font=ft2,bg=bg,activebackground=abg,bd=0,justify=tkinter.LEFT).grid(column =0,row = 2,sticky=tkinter.N + tkinter.E + tkinter.W)
+    tkinter.Button(F1, text='寄忆草稿版',cursor=bc,command=Draw, height=2, font=ft2, bg=bg,activebackground=abg, bd=0, justify=tkinter.LEFT).grid(column=0, row=3,sticky=tkinter.N + tkinter.E + tkinter.W)
+    tkinter.Button(F1, text='自动化网页',cursor=bc,command=Crawlef_Run, height=1, font=ft2, bg=bg,activebackground=abg, bd=0, justify=tkinter.LEFT).grid(column=0, row=4,sticky=tkinter.N + tkinter.E + tkinter.W)
+    tkinter.Button(F1, text='Git仓库控制器',cursor=bc,command=GIT_Ctrl, height=1, font=ft2, bg=bg,activebackground=abg, bd=0, justify=tkinter.LEFT).grid(column=0, row=5,sticky=tkinter.N + tkinter.E + tkinter.W)
 
     abg = '#FFFAFA'
     tkinter.Label(F1, text='数学系统', bg=abg, font=ft1).grid(column=0, row=6,sticky=tkinter.W + tkinter.E)

+ 0 - 0
Information_storage.py


+ 2 - 1
README.md

@@ -6,7 +6,8 @@ CoTan是基于python3x的一款用于数据科学等多方面的数理化系统
 * 初等数学的代数运算,如:解线性方程、函数绘制、函数求解等
 * 数据处理,如:特征工程、曲线拟合、机器学习以及数据可视化等
 * 基于git的数据管理可视化系统
-* 数据收集,如:数据共享、网络爬虫等 **未来实现**
+* 自动化网页控制系统、爬虫系统
+* 数据收集,如:数据共享、数据存储 **未来实现**
 * 物理仿真,如:受力分析,运动分析等 **未来实现**
 * 化学反应推理,如:反应计算,反应方程配平,反应机理预测 **未来实现**
 * 高等数学,如:微分、线性代数等 **未来实现**

+ 0 - 1
Web_Crawler.py

@@ -1 +0,0 @@
-from selenium import webdriver

+ 141 - 0
依赖信息/pip.txt

@@ -0,0 +1,141 @@
+Package               Version
+--------------------- -----------
+APScheduler           3.6.3
+astroid               2.3.3
+astropy               4.0
+atomicwrites          1.3.0
+attr                  0.3.1
+attrs                 19.3.0
+backcall              0.1.0
+beautifulsoup4        4.8.2
+beeprint              2.4.10
+bleach                3.1.1
+bs4                   0.0.1
+certifi               2019.11.28
+chardet               3.0.4
+Click                 7.0
+colorama              0.4.3
+confuse               1.0.0
+cqhttp                1.3.1
+curses                2.2.1+utf8
+cycler                0.10.0
+decorator             4.4.1
+defusedxml            0.6.0
+entrypoints           0.3
+Flask                 1.1.1
+future                0.18.2
+gitdb                 4.0.2
+GitPython             3.1.0
+html5lib              1.0.1
+htmlmin               0.1.12
+idna                  2.8
+imageio               2.6.1
+importlib-metadata    1.5.0
+ipykernel             5.1.4
+ipython               7.13.0
+ipython-genutils      0.2.0
+ipywidgets            7.5.1
+isort                 4.3.21
+itsdangerous          1.1.0
+jedi                  0.16.0
+Jinja2                2.11.1
+joblib                0.14.1
+jsonschema            3.2.0
+jupyter-client        5.3.4
+jupyter-core          4.6.1
+kaggle                1.5.6
+kamene                0.32
+kiwisolver            1.1.0
+lazy-object-proxy     1.4.3
+llvmlite              0.31.0
+lxml                  4.5.0
+MarkupSafe            1.1.1
+matplotlib            3.1.2
+mccabe                0.6.1
+mglearn               0.1.7
+missingno             0.4.2
+mistune               0.8.4
+more-itertools        8.2.0
+mpmath                1.1.0
+mysqlclient           1.4.6
+nbconvert             5.6.1
+nbformat              5.0.4
+networkx              2.4
+notebook              6.0.3
+numba                 0.48.0
+numpy                 1.18.1
+packaging             20.3
+pandas                0.25.3
+pandas-profiling      2.5.0
+pandocfilters         1.4.2
+parso                 0.6.2
+peewee                3.13.1
+pexpect               4.8.0
+phik                  0.9.9
+pickleshare           0.7.5
+Pillow                7.0.0
+pip                   20.0.2
+pluggy                0.13.1
+prettytable           0.7.2
+prometheus-client     0.7.1
+prompt-toolkit        3.0.3
+ptyprocess            0.6.0
+py                    1.8.1
+pyecharts             1.6.2
+pygame                1.9.6
+Pygments              2.5.2
+pylint                2.4.4
+PyMouse               1.0
+PyMySQL               0.9.3
+pynput                1.6.5
+pyparsing             2.4.6
+PyQt5-sip             12.7.1
+pyrsistent            0.15.7
+pytest                5.3.5
+pytest-pylint         0.14.1
+python-dateutil       2.8.1
+python-dotenv         0.10.3
+python-slugify        4.0.0
+pytz                  2019.3
+pywin32               227
+pywinpty              0.5.7
+PyYAML                5.3
+pyzmq                 18.1.1
+rarfile               3.1
+redis                 3.3.11
+requests              2.22.0
+scapy                 2.4.2
+scapy-python3         0.26
+scikit-learn          0.22
+scipy                 1.4.1
+seaborn               0.10.0
+selenium              3.141.0
+Send2Trash            1.5.0
+setuptools            45.2.0
+simplejson            3.17.0
+six                   1.13.0
+smmap                 3.0.1
+snapshot-selenium     0.0.2
+soupsieve             1.9.5
+sympy                 1.5.1
+tangled-up-in-unicode 0.0.3
+terminado             0.8.3
+testpath              0.4.4
+text-unidecode        1.3
+tornado               6.0.3
+tqdm                  4.42.0
+traitlets             4.3.3
+typed-ast             1.4.1
+tzlocal               2.0.0
+unrar                 0.4
+urllib3               1.24.3
+urwid                 2.1.0
+visions               0.2.2
+wcwidth               0.1.8
+webencodings          0.5.1
+Werkzeug              1.0.0
+widgetsnbextension    3.5.1
+wrapt                 1.11.1
+wxPython              4.0.7.post2
+yellowbrick           1.0.1
+zipp                  2.1.0