Python3 文件内容搜索工具(txt/xml/csv/Excel/xlsx/xls/Word/docx/doc/pptx/pdf/zip)

## 源代码运行,需要先安装第三方模块

## Excel 格式,需要先安装模块,安装命令 pip install xlrd
## Word docx 格式,需要先安装模块,安装命令 pip install python-docx
## Word doc 格式,需要先安装模块,安装命令 pip install pypiwin32
## pdf 格式,需要先安装模块,python3安装命令 pip install pdfminer3k
## pptx 格式,需要先安装模块,安装命令 pip install python-pptx

 

## 打包成exe格式运行

## 先安装第三方依赖模块

## 再安装打包工具
pip install PyInstaller -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com

【注意】
源代码开头要有字符集
源代码文件名只能有ASCII字符集内字符
# -*- coding: UTF8 -*-

## 打开CMD
cd 到源代码所在目录


## 如果是GUI图形界面程序,可以加 -w 去掉黑框后台显示
pyinstaller -w -F 源代码.py

-F 表示生成单个可执行文件
-w 表示去掉控制台窗口,这在GUI界面时非常有用。不过如果是命令行程序的话那就把这个选项删除吧!
-p 表示你自己自定义需要加载的类路径,一般情况下用不到
-i 表示可执行文件的图标

## 如果一切顺利,在源代码目录中会出现dist文件夹,里面有一个同名exe文件,这个文件可以在别的无python的环境下直接运行(在32位系统上打包的程序可以在32位和64位运行,在64位打包的程序只能在64位环境运行)

 

# -*- coding: UTF8 -*-
## 递归遍历目录,根据扩展名找出需要的搜索内容的文件生成文件列表,根据扩展名用关键字或者RE正则表达式逐个搜索文件内容
## V 1.0
## V 1.1 增加 pptx 格式
## V 1.2 使用线程,防止搜索大文件时图形界面被卡住

import threading    # 多线程
import os
import chardet      # 判断文本文件的字符编码 pip install chardet
import re

import csv                          ## CSV 格式
import zipfile                      ## ZIP 格式
import xlrd                         ## Excel 格式,需要先安装模块,安装命令 pip install xlrd
from docx import Document           ## Word docx 格式,需要先安装模块,安装命令 pip install python-docx
from win32com import client as wc   ## Word doc 格式,需要先安装模块,安装命令 pip install pypiwin32
from pptx import Presentation       ## pptx 格式,需要先安装模块,安装命令 pip install python-pptx

## pdf 格式,需要先安装模块,python3安装命令 pip install pdfminer3k
from pdfminer.pdfparser import PDFParser, PDFDocument
from pdfminer.pdfinterp import PDFTextExtractionNotAllowed
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LAParams, LTTextBox

# 递归遍历目录
def DEF_目录_递归遍历(D):
    try:
        L = os.listdir(D)                           # 获取目录里面的内容列表(可能会遇到权限问题)
    except Exception as e:
        ERROR = f'【错误】读取目录失败 {e}'
        Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
    else:
        if L != []:                                                # 如果目录不空
            for i in L:                                            # 遍历目录里面的内容
                FullFileName = D + '\\' + i                        
                if os.path.isdir(D + '\\' + i):                    # 如果还是目录
                    DEF_目录_递归遍历(D + '\\' + i)                # 循环递归进入目录
                else:                                              # 不是目录就是文件
                    文件名, 扩展名 = os.path.splitext(i)           # 分割文件名和扩展名,返回元组,无扩展名扩展名部分为空字符串
                    if IV_忽略文件扩展名大小写.get() == 1:
                        扩展名 = 扩展名.lower()                    # 扩展名转成小写
                    if 扩展名 in 扩展名集合:                       ## 全局变量 扩展名集合
                        文件列表.append((FullFileName, 扩展名))    ## 全局变量 文件列表:保存路径和文件全名扩展名
        else:
            WARNING = f'【注意】空目录 {D}'
            Text_搜索日志文本.insert('end', WARNING+'\n', 'tag_warning')


# 初始化目录
def DIR_init(目录):
    DEBUG = f'【调试】初始化 {目录}'
    Text_搜索日志文本.insert('end', DEBUG+'\n')
    if os.path.isdir(目录):           # 判断是否是目录
        DEF_目录_递归遍历(目录)
    else:
        ERROR = f'【错误】非目录 {目录}'
        Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')


## 根据文件后缀名进行不同的操作
def 根据文件后缀名选择操作(T, 正则表达式):
    FullFileName, FileNameExt = T
    if FileNameExt.lower() in ['.txt', '.xml', '.json']:
        F_TEXT(FullFileName, 正则表达式)
    elif FileNameExt.lower() == '.csv':
        F_CSV(FullFileName, 正则表达式)
    elif FileNameExt.lower() in ['.xlsx', '.xls']:
        F_EXCEL(FullFileName, 正则表达式)
    elif FileNameExt.lower() == '.docx':
        F_DOCX(FullFileName, 正则表达式)
    elif FileNameExt.lower() == '.doc':
        F_DOC(FullFileName, 正则表达式)
    elif FileNameExt.lower() == '.pptx':
        F_PPTX(FullFileName, 正则表达式)
    elif FileNameExt.lower() == '.pdf':
        F_PDF(FullFileName, 正则表达式)
    elif FileNameExt.lower() == '':
        F_X(FullFileName, 正则表达式)
    elif FileNameExt.lower() == '.zip':
        F_ZIP(FullFileName, 正则表达式)
    else:
        WARNING = f'【注意】暂不支持 {FileNameExt}'
        Text_搜索日志文本.insert('end', WARNING+'\n', 'tag_warning')


## 搜索文件内文本内容查找含有关键字的那行内容
def DEF_RE(TEXT, 正则表达式, 显示信息):
    if IV_忽略搜索关键字大小写.get() == 1:
        RE_fi = re.finditer(正则表达式, TEXT, re.I)    # 返回迭代器
    else:
        RE_fi = re.finditer(正则表达式, TEXT)          # 返回迭代器
    L_re = [i.group() for i in RE_fi]
    if L_re != []:
        INFO = f'【信息】{显示信息}匹配【{len(L_re)}】次'
        Text_搜索结果文本.insert('end', INFO+'\n')
        Text_搜索日志文本.insert('end', INFO+'\n')
        for i in L_re:
            INFO = f'\t{i}'
            Text_搜索日志文本.insert('end', INFO+'\n')


## TEXT 文本文件
def F_TEXT(FullFileName, 正则表达式):
    try:
        f = open(FullFileName, 'rb')
    except Exception as e:
        ERROR = f'【错误】【TEXT】{FullFileName} 打开失败 {e}'
        Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
    else:
        DATA = f.read()
        f.close()
        编码 = chardet.detect(DATA)['encoding']
        if 编码 == None:
            ERROR = f'【错误】【TEXT】【无编码信息,无法打开】{FullFileName}'
            Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
        else:
            try:
                TEXT = DATA.decode(编码)
            except Exception as e:
                ERROR = f'【错误】【TEXT】{FullFileName} 尝试编码【{编码}】失败 {e}'
                Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
            else:
                DEF_RE(TEXT, 正则表达式, FullFileName)

## ZIP压缩文件中的 TEXT 文本格式文件
def ZIP_TEXT(DATA_Bytes, 正则表达式, 显示信息):
    编码 = chardet.detect(DATA_Bytes)['encoding']
    if 编码 == None:
        ERROR = f'【错误】【TEXT】【无编码信息,无法打开】{显示信息}'
        Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
    else:
        try:
            TEXT = DATA_Bytes.decode(编码)
        except Exception as e:
            ERROR = f'【错误】【TEXT】{显示信息} 尝试编码【{编码}】失败 {e}'
            Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
        else:
            DEF_RE(TEXT, 正则表达式, 显示信息)

## CSV 格式
def F_CSV(FullFileName, 正则表达式):
    try:
        f = open(FullFileName)
        X = csv.reader(f)
        ## 做成一个单元格一行的文件,方便按行匹配,防止跨行匹配(如需跨行匹配,可以使用自定义正则模式匹配)
        L = ['\n'.join(i) for i in X]
        TEXT = '\n'.join(L)
        f.close()
    except Exception as e:
        ERROR = f'【错误】【CSV】{FullFileName} 打开失败 {e}'
        Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
    else:
        print("CSV TEXT", TEXT)
        DEF_RE(TEXT, 正则表达式, FullFileName)

## Excel 格式
def F_EXCEL(FullFileName, 正则表达式):
    try:
        E = xlrd.open_workbook(filename=FullFileName)   # 打开文件
    except Exception as e:
        ERROR = f'【错误】【Excel】{FullFileName} 打开失败 {e}'
        Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
    else:
        for 工作表名 in E.sheet_names():                # 遍历工作表名 ['Sheet1', 'Sheet2']
            工作表 = E.sheet_by_name(工作表名)
            行数 = 工作表.nrows
            L = []                                      # 以单元格为元素把Excel中一个Sheet做成一个列表
            for i in range(0, 行数):
                L += 工作表.row_values(i)
            L_str = [str(i) for i in L]                 # Excel单元格值会有非字符串类型,需要转换为字符串类型
            TEXT = '\n'.join(L_str)                     # 一个单元格拼接一个换行符,方便re以行为单位匹配
            
            显示信息 = f'【Excel】{FullFileName}【Sheet】{工作表名}'
            DEF_RE(TEXT, 正则表达式, 显示信息)

## Word docx 格式
def F_DOCX(FullFileName, 正则表达式):
    try:
        doc = Document(FullFileName)
    except Exception as e:
        ERROR = f'【错误】【docx】{FullFileName} 打开失败 {e}'
        Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
    else:
        ## 按段落拼接Word中的文本内容
        TEXT = ''
        for para in doc.paragraphs:
            TEXT += para.text + '\n'
        #print("TEXT", TEXT)
        显示信息 = f'【Word】{FullFileName}【文本内容】'
        DEF_RE(TEXT, 正则表达式, 显示信息)
        
        ## Word中的表格内容,按每个单元格一行拼接成文本
        L = []
        for 表格 in doc.tables:
            for 行 in 表格.rows:
                for 列 in 行.cells:
                    L.append(列.text)
        TEXT_TABLE = '\n'.join(L)
        #print("TEXT_TABLE", TEXT_TABLE)
        显示信息 = f'【Word】{FullFileName}【表格内容】'
        DEF_RE(TEXT_TABLE, 正则表达式, 显示信息)

## Word doc 格式
def F_DOC(FullFileName, 正则表达式):
    WARNING = '【注意】doc格式需要转换成docx格式,正在转换,请稍后...'
    Text_搜索日志文本.insert('end', WARNING+'\n', 'tag_warning')
    FullFileName_NEW = FullFileName + '转格式.docx'
    if os.path.exists(FullFileName_NEW):
        WARNING = f'【取消转换】已经存在文件或目录 {FullFileName_NEW}'
        Text_搜索日志文本.insert('end', WARNING+'\n', 'tag_warning')
    else:
        word = wc.Dispatch("Word.Application")
        doc = word.Documents.Open(FullFileName)
        doc.SaveAs(FullFileName_NEW, 12)            # 12代表docx
        doc.Close()
        word.Quit()
        WARNING = f'【转换完成】另存为新文件 {FullFileName_NEW}'
        Text_搜索日志文本.insert('end', WARNING+'\n', 'tag_warning')
        F_DOCX(FullFileName_NEW, 正则表达式)

## pptx 格式
def F_PPTX(FullFileName, 正则表达式):
    try:
        PY_PPTX = Presentation(FullFileName)
    except Exception as e:
        ERROR = f'【错误】【pptx】{FullFileName} 打开失败 {e}'
        Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
    else:
        ## 按页拼接ppt中的文本内容
        页码 = 0
        for slide in PY_PPTX.slides:                            # 遍历每一张ppt
            页码 +=1
            PAGE_TEXT = ''
            for shape in slide.shapes:                          # 遍历页面上每一个元素块(文本框、图片等)
                if shape.has_text_frame:                        # 如果元素块内有文字
                    PAGE_TEXT += '\n' + shape.text_frame.text   # 拼接页面全部元素块内文本,以换行符合分格
            #print("页码", 页码, "PAGE_TEXT", PAGE_TEXT)
            显示信息 = f'【PPTX】{FullFileName}第【{页码}】页'
            DEF_RE(PAGE_TEXT, 正则表达式, 显示信息)

## pdf 格式
def F_PDF(FullFileName, 正则表达式):
    WARNING = '搜索大PDF文件比较耗时,请耐心等待...'
    Text_搜索日志文本.insert('end', WARNING+'\n', 'tag_warning')
    fp = open(FullFileName, 'rb')       # 以二进制读模式打开PDF文件
    praser = PDFParser(fp)              # 实例化pdf解析器,从文件流中获取PDF对象
    doc = PDFDocument()                 # 创建一个PDF文档
    praser.set_document(doc)            # 分析器关联文档对象
    doc.set_parser(praser)              # 文档对象关联分析器
    doc.initialize()                    # 文档初始化解密,如果没有密码就创建一个空的字符串
    
    # 判断是否可以将PDF文件转换成txt,不行就直接忽略
    if not doc.is_extractable:
        raise PDFTextExtractionNotAllowed

    rsrcmgr = PDFResourceManager()                          # 创建资源管理器,负责资源调度,有益于资源共享
    laparams = LAParams()                                   # 实例化默认参数空间
    device = PDFPageAggregator(rsrcmgr, laparams=laparams)  # 创建设备
    interpreter = PDFPageInterpreter(rsrcmgr, device)       # 创建解释器
    
    # 遍历
    页码 = 0
    for page in doc.get_pages():            # 遍历doc.get_pages()生成器,生成器对应了PDF每一页的数据源与解析器等配置
        页码 += 1
        interpreter.process_page(page)
        layout = device.get_result()        # 接收该页面的LTPage对象,里面存放着这个 page 解析出的各种对象
        TEXT = ''
        for x in layout:
            if isinstance(x, LTTextBox):
                TEXT += x.get_text()
        显示信息 = f'【PDF】{FullFileName}第【{页码}】页'
        DEF_RE(TEXT, 正则表达式, 显示信息)

## 无扩展名的文件,读取文件开头字节,尝试判断实际文件类型
def F_X(FullFileName, 正则表达式):
    print("【注意】【无扩展名的文件】", FullFileName)
    try:
        f = open(FullFileName, 'rb')
    except Exception as e:
        print("【错误】打开失败", e)
    else:
        DATA = f.read(4)
        f.close()
        print("F_X Bytes DATA")
        print(DATA)
        print("文件内容编码信息", chardet.detect(DATA))
        编码 = chardet.detect(DATA)['encoding']

## zip 格式
def F_ZIP(FullFileName, 正则表达式):
    if zipfile.is_zipfile(FullFileName):
        try:
            f = zipfile.ZipFile(FullFileName)
        except Exception as e:
            ERROR = f'【错误】【ZIP】打开失败{e}'
            Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
        else:
            for i in f.namelist():      # 遍历ZIP内文件
                if i.endswith('/'):     # 跳过目录
                    pass
                else:
                    文件名, 扩展名 = os.path.splitext(i)
                    print(文件名, 扩展名)
                    if IV_忽略文件扩展名大小写.get() == 1:
                        扩展名 = 扩展名.lower()                    # 扩展名转成小写
                    if 扩展名 in 扩展名集合:
                        try:
                            DATA_Bytes = f.open(i).read()
                        except Exception as e:
                            ERROR = f'【错误】【ZIP】中【{i}】打开失败{e}'
                            Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
                        else:
                            #print("DATA_Bytes", DATA_Bytes)
                            if 扩展名 == '.txt':
                                ZIP_TEXT(DATA_Bytes, 正则表达式, FullFileName+'中['+i+']文件')
                            else:
                                WARNING = f'暂不支持ZIP内{扩展名}格式直接搜索内容,请解压后再搜索'
                                Text_搜索日志文本.insert('end', WARNING+'\n', 'tag_warning')
    else:
        ERROR = f'【错误】【不是ZIP格式文件】{FullFileName}'
        Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')


def 关键词转正则表达式(关键字):
    正则表达式 = '(.*)'
    for i in 关键字:
        if i in ['^', '$', '.', '[', ']', '*', '+', '?', '{', '}', '|', '\\']:
            正则表达式 += '\\' + i
        else:
            正则表达式 += i
    正则表达式 += '(.*)'
    return(正则表达式)


# 运行
def RUN(正则表达式):
    ## 对符合要求的文件,根据文件后缀名进行相应的操作
    for i in 文件列表:
        根据文件后缀名选择操作(i, 正则表达式)
    INFO = '【信息】搜索结束'
    Text_搜索结果文本.insert('end', INFO+'\n')



## 使用图形界面
from tkinter import *
from tkinter import filedialog  # 选择文件用
from tkinter import ttk         # 下拉菜单控件在ttk中
import tkinter.messagebox       # 弹出提示对话框
import tkinter.simpledialog     # 弹出对话框,获取用户输入

top = Tk()                                          # 初始化Tk()
top.title('文件内容搜索工具V1.0')   # 设置标题
窗口宽 = 935
窗口高 = 550
# 获取屏幕尺寸以计算布局参数,使窗口居屏幕中央
屏幕宽 = top.winfo_screenwidth()
屏幕高 = top.winfo_screenheight()
主窗口显示位置 = '%dx%d+%d+%d' % (窗口宽, 窗口高, (屏幕宽-窗口宽)/2, (屏幕高-窗口高)/2)
top.geometry(主窗口显示位置)
top.resizable(width=True, height=True)      # 设置窗口是否可变长、宽(True:可变,False:不可变)

## 窗口布局 
Frame_扩展名框 = Frame(top, bg='#ADFF2F')
LF_搜索目录框 = LabelFrame(top, text='选择搜索文件夹')
Frame_搜索条件框 = Frame(top)
LF_搜索结果框 = LabelFrame(top, text='搜索结果') 
LF_搜索日志框 = LabelFrame(top, text='搜索日志及详细') 

## 框架的位置布局
Frame_扩展名框.grid(row=0, column=0, sticky='W')
LF_搜索目录框.grid(row=1, column=0, sticky='W')
Frame_搜索条件框.grid(row=2, column=0, sticky='W')
LF_搜索结果框.grid(row=3, column=0, sticky=S+W+E+N)

LF_搜索日志框.grid(row=0, column=1, sticky=S+W+E+N, rowspan=4)

WORD_扩展名 = LabelFrame(Frame_扩展名框, text='Word')
WORD_扩展名.grid(row=0, column=0, sticky='NW')

EXCEL_扩展名 = LabelFrame(Frame_扩展名框, text='Excel')
EXCEL_扩展名.grid(row=0, column=1, sticky='NW')

PPT_扩展名 = LabelFrame(Frame_扩展名框, text='PDF')
PPT_扩展名.grid(row=0, column=2, sticky='NW')

TEXT_扩展名 = LabelFrame(Frame_扩展名框, text='TEXT')
TEXT_扩展名.grid(row=0, column=3, sticky='NW')

Other_扩展名 = LabelFrame(Frame_扩展名框, text='其他扩展名')
Other_扩展名.grid(row=0, column=4, sticky='NW')

扩展名大小写 = LabelFrame(Frame_扩展名框, text='扩展名大小写')
扩展名大小写.grid(row=0, column=5, sticky='NW')






## Python全局变量
扩展名集合 = set()
文件列表 = []

## 图形全局变量
复选_TXT = IntVar()
复选_XML = IntVar()
复选_JSON = IntVar()
复选_CSV = IntVar()
复选_XLSX = IntVar()
复选_XLS = IntVar()
复选_DOC = IntVar()
复选_DOCX = IntVar()
复选_PPTX = IntVar()
复选_PPT = IntVar()
复选_PDF = IntVar()
复选_NULL = IntVar()
复选_ZIP = IntVar()

IV_忽略文件扩展名大小写 = IntVar()
IV_忽略文件扩展名大小写.set(1)        # 设置默认选择
IV_忽略搜索关键字大小写 = IntVar()

SV_搜索关键字 = StringVar()
SV_正则表达式 = StringVar()

搜索目录 = StringVar()


## 图形操作函数

def DEF_使用关键字搜索():
    扩展名集合.clear()  # 每次执行搜索前,先清空全局集合变量,防止累加
    if 复选_TXT.get() == 1:
        扩展名集合.add('.txt')
    if 复选_XML.get() == 1:
        扩展名集合.add('.xml')
    if 复选_JSON.get() == 1:
        扩展名集合.add('.json')
    if 复选_CSV.get() == 1:
        扩展名集合.add('.csv')
    if 复选_XLSX.get() == 1:
        扩展名集合.add('.xlsx')
    if 复选_XLS.get() == 1:
        扩展名集合.add('.xls')
    if 复选_DOC.get() == 1:
        扩展名集合.add('.doc')
    if 复选_DOCX.get() == 1:
        扩展名集合.add('.docx')
    if 复选_PPTX.get() == 1:
        扩展名集合.add('.pptx')
    if 复选_PDF.get() == 1:
        扩展名集合.add('.pdf')
    if 复选_NULL.get() == 1:
        扩展名集合.add('')
    if 复选_ZIP.get() == 1:
        扩展名集合.add('.zip')
    
    if 扩展名集合 == set():
        ERROR = '未选择扩展名'
        Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
    else:
        if SV_搜索关键字.get() == '':
            Text_搜索日志文本.delete(0.0, 'end')
            ERROR = '未设置搜索关键字'
            Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
        else:
            if 搜索目录.get() == '':
                Text_搜索日志文本.delete(0.0, 'end')
                ERROR = '未设置搜索文件夹'
                Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
            else:
                DEBUG = f'【调试】开始搜索目录{搜索目录.get()}'
                Text_搜索日志文本.insert('end', DEBUG+'\n')
                ## 初始化
                文件列表.clear()    # 每次执行搜索前,先清空全局列表变量,防止累加
                
                正则表达式 = 关键词转正则表达式(SV_搜索关键字.get())
                ## 清空两个文本框内容
                Text_搜索日志文本.delete(0.0, 'end')
                Text_搜索结果文本.delete(0.0, 'end')

                ## 搜索目录下所有文件,找出符合要求的文件列表
                DIR_init(搜索目录.get())
                if 文件列表 == []:
                    Text_搜索日志文本.delete(0.0, 'end')
                    Text_搜索结果文本.delete(0.0, 'end')
                    WARNING = '【注意】未找到相应扩展名的文件'
                    Text_搜索日志文本.insert('end', WARNING+'\n', 'tag_warning')
                else:
                    INFO = f'【信息】找到符合扩展名条件的文件【{len(文件列表)}】个'
                    Text_搜索日志文本.insert('end', INFO+'\n')
                    for 文件名, 扩展名 in 文件列表:
                        INFO = f'{扩展名}\t{文件名}'
                        Text_搜索日志文本.insert('end', INFO+'\n')
                    ## 对符合要求的文件,根据文件后缀名进行相应的操作
                    th=threading.Thread(target=RUN, args=(正则表达式,))
                    th.setDaemon(True)  # 守护线程
                    th.start()

def DEF_使用正则搜索():
    扩展名集合.clear()  # 每次执行搜索前,先清空全局集合变量,防止累加
    if 复选_TXT.get() == 1:
        扩展名集合.add('.txt')
    if 复选_XML.get() == 1:
        扩展名集合.add('.xml')
    if 复选_JSON.get() == 1:
        扩展名集合.add('.json')
    if 复选_CSV.get() == 1:
        扩展名集合.add('.csv')
    if 复选_XLSX.get() == 1:
        扩展名集合.add('.xlsx')
    if 复选_XLS.get() == 1:
        扩展名集合.add('.xls')
    if 复选_DOC.get() == 1:
        扩展名集合.add('.doc')
    if 复选_DOCX.get() == 1:
        扩展名集合.add('.docx')
    if 复选_PPTX.get() == 1:
        扩展名集合.add('.pptx')
    if 复选_PDF.get() == 1:
        扩展名集合.add('.pdf')
    if 复选_NULL.get() == 1:
        扩展名集合.add('')
    if 复选_ZIP.get() == 1:
        扩展名集合.add('.zip')
    
    if 扩展名集合 == set():
        ERROR = '未选择扩展名'
        Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
    else:
        if SV_正则表达式.get() == '':
            Text_搜索日志文本.delete(0.0, 'end')
            ERROR = '未设置正则表达式'
            Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
        else:
            if 搜索目录.get() == '':
                Text_搜索日志文本.delete(0.0, 'end')
                ERROR = '未设置搜索文件夹'
                Text_搜索日志文本.insert('end', ERROR+'\n', 'tag_error')
            else:
                DEBUG = f'【调试】开始搜索目录{搜索目录.get()}'
                Text_搜索日志文本.insert('end', DEBUG+'\n')
                ## 初始化
                文件列表.clear()    # 每次执行搜索前,先清空全局列表变量,防止累加
                
                正则表达式 = SV_正则表达式.get()
                ## 清空两个文本框内容
                Text_搜索日志文本.delete(0.0, 'end')
                Text_搜索结果文本.delete(0.0, 'end')

                ## 搜索目录下所有文件,找出符合要求的文件列表
                DIR_init(搜索目录.get())
                if 文件列表 == []:
                    Text_搜索日志文本.delete(0.0, 'end')
                    Text_搜索结果文本.delete(0.0, 'end')
                    WARNING = '【注意】未找到相应扩展名的文件'
                    Text_搜索日志文本.insert('end', WARNING+'\n', 'tag_warning')
                else:
                    INFO = f'【信息】找到符合扩展名条件的文件【{len(文件列表)}】个'
                    Text_搜索日志文本.insert('end', INFO+'\n')
                    for 文件名, 扩展名 in 文件列表:
                        INFO = f'{扩展名}\t{文件名}'
                        Text_搜索日志文本.insert('end', INFO+'\n')
                    ## 对符合要求的文件,根据文件后缀名进行相应的操作
                    th=threading.Thread(target=RUN, args=(正则表达式,))
                    th.setDaemon(True)  # 守护线程
                    th.start()

def DEF_按钮_选择目录():
    选择的目录 = filedialog.askdirectory()
    搜索目录.set(选择的目录)                   # 实时更新显示


## 图形控件
Checkbutton(WORD_扩展名,  text="docx    ", variable=复选_DOCX).grid(row=0, column=0, sticky='NW')
Checkbutton(WORD_扩展名,  text="doc     ", variable=复选_DOC).grid(row=1, column=0, sticky='NW')
Checkbutton(EXCEL_扩展名, text="xlsx    ", variable=复选_XLSX).grid(row=0, column=0, sticky='NW')
Checkbutton(EXCEL_扩展名, text="xls     ", variable=复选_XLS).grid(row=1, column=0, sticky='NW')
Checkbutton(EXCEL_扩展名, text="csv     ", variable=复选_CSV).grid(row=2, column=0, sticky='NW')
Checkbutton(PPT_扩展名,   text="pptx    ", variable=复选_PPTX).grid(row=0, column=0, sticky='NW')
XX = Checkbutton(PPT_扩展名, text="ppt  ", variable=复选_PPT)
XX.grid(row=1, column=0, sticky='NW')
XX.configure(state='disabled')
Checkbutton(TEXT_扩展名,  text="txt     ", variable=复选_TXT).grid(row=0, column=0, sticky='NW')
Checkbutton(TEXT_扩展名,  text="xml     ", variable=复选_XML).grid(row=1, column=0, sticky='NW')
Checkbutton(TEXT_扩展名,  text="json    ", variable=复选_JSON).grid(row=2, column=0, sticky='NW')
Checkbutton(Other_扩展名, text="无扩展名", variable=复选_NULL).grid(row=0, column=0, sticky='NW')
Checkbutton(Other_扩展名, text="zip",      variable=复选_ZIP).grid(row=1, column=0, sticky='NW')
Checkbutton(Other_扩展名, text="pdf     ", variable=复选_PDF).grid(row=2, column=0, sticky='NW')
Checkbutton(扩展名大小写, text="忽略大小写", variable=IV_忽略文件扩展名大小写).grid(row=0, column=0)

LF_关键字搜索框 = LabelFrame(Frame_搜索条件框, text='使用关键字搜索')
LF_正则表达式框 = LabelFrame(Frame_搜索条件框, text='使用正则搜索')
LF_关键字搜索框.grid(row=0, column=0, sticky='NW')
LF_正则表达式框.grid(row=0, column=1, sticky='NW')

Label(LF_关键字搜索框, text='搜索关键字').grid(row=0,column=0,sticky='NW')
Entry(LF_关键字搜索框, textvariable=SV_搜索关键字, width=32).grid(row=1, column=0, sticky='NW', columnspan=2)
Button(LF_关键字搜索框, text='开始搜索', command=DEF_使用关键字搜索).grid(row=3, column=0, sticky='W')
Checkbutton(LF_关键字搜索框,  text="忽略大小写  ", variable=IV_忽略搜索关键字大小写).grid(row=3, column=1, sticky='E')

Label(LF_正则表达式框, text='RE正则表达式').grid(row=0,column=0,sticky='NW')
Entry(LF_正则表达式框, textvariable=SV_正则表达式, width=32).grid(row=1, column=0, sticky='NW', columnspan=2)
Button(LF_正则表达式框, text='开始搜索', command=DEF_使用正则搜索).grid(row=3, column=0, sticky='W')
Checkbutton(LF_正则表达式框,  text="忽略大小写  ", variable=IV_忽略搜索关键字大小写).grid(row=3, column=1, sticky='E')

Button(LF_搜索目录框, text=' 选择 ', command=DEF_按钮_选择目录).grid(row=1, column=0, sticky='W')
Entry(LF_搜索目录框, textvariable=搜索目录, width=59).grid(row=1, column=1)


## LF_搜索结果框
Text_搜索结果文本 = Text(LF_搜索结果框, width=63, height=20, wrap='word')     # wrap='none' 不自动换行, wrap='word' 自动换行
Scrollbar_XX_列表_竖 = Scrollbar(LF_搜索结果框) 
Scrollbar_XX_列表_竖['command'] = Text_搜索结果文本.yview

#Scrollbar_XX_列表_横 = Scrollbar(LF_搜索结果框) 
#Scrollbar_XX_列表_横['command'] = Text_搜索结果文本.xview
#Scrollbar_XX_列表_横['orient'] = HORIZONTAL

Text_搜索结果文本.grid(row=0, column=0, sticky=S+W+E+N)
Scrollbar_XX_列表_竖.grid(row=0, column=1, sticky=S+W+E+N)
#Scrollbar_XX_列表_横.grid(row=1, column=0, sticky=S+W+E+N)

# 自动设置滚动条滑动幅度
Text_搜索结果文本['yscrollcommand'] = Scrollbar_XX_列表_竖.set
#Text_搜索结果文本.config(xscrollcommand=Scrollbar_XX_列表_横.set)


## LF_搜索日志框
Text_搜索日志文本 = Text(LF_搜索日志框, width=63, height=39, wrap='none')     # wrap='none' 不自动换行, wrap='word' 自动换行
Scrollbar_XXX_列表_竖 = Scrollbar(LF_搜索日志框) 
Scrollbar_XXX_列表_竖['command'] = Text_搜索日志文本.yview

Scrollbar_XXX_列表_横 = Scrollbar(LF_搜索日志框) 
Scrollbar_XXX_列表_横['command'] = Text_搜索日志文本.xview
Scrollbar_XXX_列表_横['orient'] = HORIZONTAL

Text_搜索日志文本.grid(row=0, column=0, sticky=S+W+E+N)
Scrollbar_XXX_列表_竖.grid(row=0, column=1, sticky=S+W+E+N)
Scrollbar_XXX_列表_横.grid(row=1, column=0, sticky=S+W+E+N)

# 自动设置滚动条滑动幅度
Text_搜索日志文本['yscrollcommand'] = Scrollbar_XXX_列表_竖.set
Text_搜索日志文本.config(xscrollcommand=Scrollbar_XXX_列表_横.set)

# 自定义文本格式
Text_搜索日志文本.tag_config('tag_error', backgroun='yellow', foreground='red')
Text_搜索日志文本.tag_config('tag_warning', backgroun='yellow')


## 进入消息循环
top.mainloop()

 

你可能感兴趣的:(python,搜索引擎,python,zip,csv,excel)