ソースを参照

完成了页面分析器的:CSV数据库交互、页面快照获取

Huan 5 年 前
コミット
f5040dca07
4 ファイル変更373 行追加83 行削除
  1. 84 24
      Crawler_controller.py
  2. 5 5
      Git_controller/GIT.py
  3. 73 0
      Information_storage.py
  4. 211 54
      Web_Crawler.py

+ 84 - 24
Crawler_controller.py

@@ -7,6 +7,9 @@ import hashlib
 from time import sleep
 import bs4
 import re as regular
+import Information_storage
+
+data_base = Information_storage.DataBase_Home()
 
 class URL_PAGE():
     def __init__(self,url,func='get'):
@@ -170,8 +173,11 @@ class Page_Parser:
         self.func_list.append(f'{name}[{n}]')
         self.func_dict[f'{name}[{n}]'] = func
 
-    def return_func(self):
-        return self.func_list.copy()
+    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
@@ -493,20 +499,50 @@ class Page_Parser:
         else:
             return self.element_dict[element_value][index]
 
-    def findAll(self, element_value,tag:(str,list),attribute:dict,limit,recursive,index:(slice,int)):#根据标签定位
+    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
-            if type(index) is int:
-                iter_list = [self.element_dict[element_value][index]]
-            else:
-                iter_list = self.element_dict[element_value][index]
+            iter_list = self.listSlicing(index,element_value)
             paser_list = []
             for bs in iter_list:
                 try:
-                    re = bs.findAll(tag,attribute,limit=limit,recursive=recursive)
+                    re = bs.find_all(tag,attribute,limit=limit,recursive=recursive)
                 except:
                     try:
                         if str(bs.name) not in tag:raise Exception
@@ -521,9 +557,13 @@ class Page_Parser:
                         re = []
                 paser_list += re
             self.element_dict[f'{name}[{num}]'] = paser_list
-        self.add_func(f'findAll:{element_value}', action)  # 添加func
+        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)):#根据text定位
+    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
@@ -531,7 +571,7 @@ class Page_Parser:
             paser_list = []
             for bs in iter_list:
                 try:
-                    re = bs.findAll(text=text,limit=limit,recursive=recursive)
+                    re = bs.find_all(text=text,limit=limit,recursive=recursive)
                 except:
                     try:
                         if type(text) is str:
@@ -543,33 +583,40 @@ class Page_Parser:
                         re = []
                 paser_list += re
             self.element_dict[f'{name}[{num}]'] = paser_list
-        self.add_func(f'findAll_by_text:{element_value}', action)  # 添加func
+        self.add_func(f'findAll_by_text:{element_value}[{index}]', action)  # 添加func
 
-    def __get_other_base(self,element_value,index:(slice,int),who='children'):#获得子、后代、兄弟标签的基类
+    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:
-                paser_list += {'children':bs.children,'offspring':bs.descendants,'down':bs.next_siblings,
-                               'up':bs.previous_siblings}.get(who,bs.children)
-            self.element_dict[f'{name}[{num}]'] = paser_list
-        self.add_func(f'get_{who}:{element_value}', action)  # 添加func
-
-    def get_children(self,element_value,index:(slice,int)):
+                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)):
+    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)):
+    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)):
+    def get_down(self,element_value,index:(slice,int),**kwargs):
         return self.__get_other_base(element_value,index,'down')
 
-    def get_by_path(self,element_value,index:(slice,int),path):#根据bs4的目录选择
+    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
@@ -583,7 +630,20 @@ class Page_Parser:
                 except:
                     pass
             self.element_dict[f'{name}[{num}]'] = paser_list
-        self.add_func(f'get>{path}:{element_value}', action)  # 添加func
+        self.add_func(f'get>{path}:{element_value}[{index}]', action)  # 添加func
+
+    def Webpage_snapshot(self,**kwargs):
+        @self.add_base
+        def action(num, name, *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 Element_interaction(self,update_func=lambda *args:None):#元素交互
         func_list = self.func_list

+ 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='异步显示',

+ 73 - 0
Information_storage.py

@@ -0,0 +1,73 @@
+import os
+
+class Database:
+    def __init__(self,name):
+        self.dir = rf'{os.getcwd()}/Database_dir/{name}.cotanDB'#创建保存文件
+        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())

+ 211 - 54
Web_Crawler.py

@@ -7,7 +7,9 @@ import threading
 import time
 
 def Main():
-    global top,Git,PATH,bg,bbg,fg,cookies_list
+    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 = []
@@ -271,126 +273,229 @@ def Main():
     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)
-    ValueName_Input = tkinter.Entry(top, width=width_B * 2)
-    ValueName_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+    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)
-    ValueName_Input = tkinter.Entry(top, width=width_B * 2)
-    ValueName_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+    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)
-    ValueName_Input = tkinter.Entry(top, width=width_B * 2)
-    ValueName_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+    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)
-    ValueName_Input = tkinter.Entry(top, width=width_B * 2)
-    ValueName_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+    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.Variable()
+    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)
-    ValueName_Input = tkinter.Entry(top, width=width_B)
-    ValueName_Input.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=attribute_re).grid(column=a_x + 2, row=a_y, sticky=tkinter.W)
-    attribute_re.set('1')
+    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=lambda :Page_Parser_addActionFunc('wait_sleep'), font=FONT, width=width_B,height=height_B).grid(
+    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=lambda :Page_Parser_addActionFunc('set_wait'), font=FONT, width=width_B,height=height_B).grid(
+    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=lambda :Page_Parser_addActionFunc('run_JS'), font=FONT, width=width_B,height=height_B).grid(
+    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
-    Solve_BOX = tkinter.Listbox(top, width=width_B * 3, height=height_B * 3)
-    Solve_BOX.grid(column=a_x, row=a_y, columnspan=3, rowspan=3, sticky=tkinter.E + tkinter.W + tkinter.S + tkinter.N)
+    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)
 
-    text_re = tkinter.Variable()
     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)
-    ValueName_Input = tkinter.Entry(top, width=width_B)
-    ValueName_Input.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=text_re).grid(column=a_x + 2, row=a_y, sticky=tkinter.W)
+    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)
-    ValueName_Input = tkinter.Entry(top, width=width_B * 2)
-    ValueName_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+    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,
+    tkinter.Label(top, text='定位路径:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,
                                                                                                       row=a_y)
-    ValueName_Input = tkinter.Entry(top, width=width_B * 2)
-    ValueName_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+    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.Label(top, text='定位路径:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,
-                                                                                                      row=a_y)
-    ValueName_Input = tkinter.Entry(top, width=width_B * 2)
-    ValueName_Input.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
+    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_addActionFunc('wait_sleep'), font=FONT, width=width_B,height=height_B).grid(
+    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_addActionFunc('set_wait'), font=FONT, width=width_B,height=height_B).grid(
+    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_addActionFunc('run_JS'), font=FONT, width=width_B,height=height_B).grid(
+    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_addActionFunc('wait_sleep'), font=FONT, width=width_B,height=height_B).grid(
+    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_addActionFunc('set_wait'), font=FONT, width=width_B,height=height_B).grid(
+    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_addActionFunc('run_JS'), font=FONT, width=width_B,height=height_B).grid(
+    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_addActionFunc('wait_sleep'), font=FONT, width=width_B,height=height_B).grid(
+    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_addActionFunc('set_wait'), font=FONT, width=width_B,height=height_B).grid(
+    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_addActionFunc('run_JS'), font=FONT, width=width_B,height=height_B).grid(
+    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_addActionFunc('wait_sleep'), font=FONT, width=width_B,height=height_B).grid(
+    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_addActionFunc('set_wait'), font=FONT, width=width_B,height=height_B).grid(
+    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_addActionFunc('run_JS'), font=FONT, width=width_B,height=height_B).grid(
+    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 :Page_Parser_addActionFunc('wait_sleep'), font=FONT, width=width_B,height=height_B).grid(
+    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 :Page_Parser_addActionFunc('set_wait'), font=FONT, width=width_B,height=height_B).grid(
+    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=lambda :Page_Parser_addActionFunc('run_JS'), font=FONT, width=width_B,height=height_B).grid(
+    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
+    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 * 3)
+    DataBase_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=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='NONE',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='NONE', command=close, 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
+    global url,loader,Page_Parser,DataBase,save_dir
     save_dir = askdirectory(title='选择项目位置')#项目位置
     url = Crawler_controller.url(save_dir,save_dir)
     loader = Crawler_controller.Page_Downloader(url,save_dir)
     Page_Parser = Crawler_controller.Page_Parser(loader)
+    DataBase = Crawler_controller.data_base
     top.mainloop()
 
+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)
@@ -398,6 +503,48 @@ def update_Status(now_func,status,Value_BOX):
     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_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:
@@ -419,6 +566,18 @@ def Func_Args():#方法args统一转换(不支持Frame)
     time=time
     )
 
+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}.get(func,Page_Parser.make_bs)
+    FUNC(**args)
+    Update_Parser_Func_BOX()
+
 def Page_Parser_addActionFunc(func):
     global Page_Parser
     args = Func_Args()
@@ -427,9 +586,7 @@ def Page_Parser_addActionFunc(func):
             '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(
-        func,Page_Parser.send_keys
-    )
+            'out':Page_Parser.out_html,'get_Page':Page_Parser.to_text}.get(func,Page_Parser.send_keys)
     FUNC(**args)
     Update_Parser_Func_BOX()
 
@@ -460,7 +617,7 @@ def Page_Parser_addFindFunc(func):
 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())
+    Parser_Func_BOX.insert(tkinter.END, *Page_Parser.return_func(False)[::-1])
 
 def Update_cookies():
     global cookies_BOX,cookies_list,cookies_Input