吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1062|回复: 44
上一主题 下一主题
收起左侧

[Windows] 划词搜索2.0-本地题库版

[复制链接]
跳转到指定楼层
楼主
Corvus 发表于 2024-11-21 17:17 回帖奖励
本帖最后由 Corvus 于 2024-11-21 17:31 编辑

为了能更广泛的支持多种题库内容方式,一个月间,测试了多种不同的思路。一开始,想把题目和答案都识别出来,分开显示,并且显示文本原本的颜色,因有些答案是标红显示的,但是都以失败告终,太天真。首先有的题库带选项,有的不带选项,甚至直接是括号里显示答案,并且python处理excel颜色文本,好像很复杂,需要加载多个库,固放弃。
最终,我采取懒人方法,直接从题目段落开始算起,一直往下共显示7个段落,这样大体都能包括了答案和题目在一起,带选项,不带选项,单选,多选,各种各样的杂乱题库。
本次取消了对txt,doc格式的支持,精简了代码,提高了部分效率,加大了字体显示。



帮助文档
1. 使用指南:
- 加载题库:点击'加载题库'按钮可以选择多个题库加载
- 开始监控:点击'开始监控'按钮以监控剪贴板内容。
2. 功能说明:
- 本程序用于文件内容搜索,题库支持docx,xls,xlsx
- 题库内容没有固定格式要求,设定为自题库内关键词所在段落,往下共显示7个段落内容。
- 剪贴板监控功能可自动检测并搜索新的剪贴板内容。
- 该程序自动置顶,可用于测试进行中不允许切换页面的程序。
- 关闭程序后,自动清空题库缓存,再次运行后,需要重新加载题库。


源码在二楼

下载:

https://pan.baidu.com/s/1Eb8pH2EQviARPcjc0FDvGQ?pwd=r9fj 提取码: r9fj 复制这段内容后打开百度网盘手机App,操作更方便哦


免费评分

参与人数 10吾爱币 +11 热心值 +9 收起 理由
一丝风 + 1 + 1 热心回复!
jh95wxg + 2 + 1 谢谢@Thanks!
Zzy985570612 + 1 + 1 我很赞同!
helh0275 + 2 + 1 谢谢@Thanks!
ali1 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
JQ1688 + 1 我很赞同!
jamesnow + 1 + 1 热心回复!
leger1210 + 1 谢谢@Thanks!
竹轩 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
zr2019 + 1 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
 楼主| Corvus 发表于 2024-11-21 17:20 |楼主
[Python] 纯文本查看 复制代码
import os  # 文件路径操作
import pyperclip  # 剪贴板操作
import re  # 正则表达式
import tkinter as tk  # GUI
from tkinter import filedialog, scrolledtext, messagebox  # GUI组件
from docx import Document  # 读取Word文档
import openpyxl  # 读取Excel文件
import xlrd  # 读取旧版Excel文件
import threading  # 线程操作
from concurrent.futures import ThreadPoolExecutor  # 线程池
import time  # 时间操作

# 全局变量
file_content = []  # 存储文件内容
monitoring = False  # 剪贴板监控状态
initial_clipboard_content = ''  # 初始剪贴板内容
root = tk.Tk()  # 创建Tkinter主窗口
text_display = None  # 显示结果的文本框
toggle_button = None  # 切换监控的按钮
keyword_var = tk.StringVar(root)  # 关键词的Tkinter变量
result = tk.StringVar(root)  # 状态信息的Tkinter变量
failed_files = []  # 存储加载失败的文件


def create_gui():
    """创建GUI界面"""
    global text_display, toggle_button
    root.title("划词搜索2.0-本地题库版")  # 窗口标题
    root.geometry("600x400")  # 窗口大小
    root.minsize(600, 400)  # 窗口最小大小
    root.attributes('-topmost', True)  # 窗口置顶

    tk.Label(root, text="当前剪贴板内容:").pack(pady=5)  # 剪贴板内容标签
    tk.Entry(root, textvariable=keyword_var, width=50).pack(pady=5)  # 输入框绑定关键词变量
    tk.Label(root, text="搜索结果:").pack(pady=5)  # 搜索结果标签
    text_display = scrolledtext.ScrolledText(root, wrap=tk.WORD, height=10, width=70, state=tk.DISABLED,
                                             font=("微软雅黑", 12))  # 创建滚动文本框
    text_display.pack(pady=5)  # 显示滚动文本框

    button_frame = tk.Frame(root)  # 创建按钮框架
    button_frame.pack(pady=5)  # 显示按钮框架

    tk.Button(button_frame, text="加载题库", command=select_files).pack(side=tk.LEFT, padx=5)  # 加载题库按钮
    toggle_button = tk.Button(button_frame, text="开始监控", command=toggle_monitoring)  # 切换监控按钮
    toggle_button.pack(side=tk.LEFT, padx=5)  # 显示切换监控按钮

    status_frame = tk.Frame(root)
    status_frame.pack(fill=tk.X, pady=2, padx=10)

    help_button = tk.Button(status_frame, text="帮助", command=show_help)  # 帮助按钮
    help_button.pack(side=tk.LEFT, padx=5)  # 定位在左侧

    tk.Label(status_frame, textvariable=result).pack(side=tk.LEFT, expand=True)  # 状态信息标签并居中

    label = tk.Label(status_frame, text="by Corvus", font=("Arial", 10))  # 创建标签
    label.pack(side=tk.RIGHT)  # 定位在右边

    result.set("请先加载题库")  # 默认提示信息


def read_file(filepath):
    """根据文件扩展名选择合适的读取方式"""
    ext = os.path.splitext(filepath)[1].lower()  # 获取文件扩展名并转为小写
    if ext == '.docx':
        return read_docx(filepath)  # 读取docx文件
    elif ext in ('.xlsx', '.xls'):
        return read_excel(filepath)  # 统一调用读取Excel文件函数
    return []  # 不支持的文件类型返回空列表


def read_docx(filepath):
    """读取docx文件内容并按段落和表格存储"""
    paragraphs = []  # 存储结果
    try:
        doc = Document(filepath)  # 打开docx文件

        # 读取段落
        for para in doc.paragraphs:  # 遍历所有段落
            if para.text:  # 只取非空段落
                paragraphs.append(para.text)  # 添加段落内容

        # 读取表格
        for table in doc.tables:  # 遍历所有表格
            for row in table.rows:  # 遍历表格的每一行
                row_data = [cell.text.strip() for cell in row.cells if cell.text.strip()]  # 取出非空单元格内容
                if row_data:  # 如果行非空
                    paragraphs.append(' | '.join(row_data))  # 用 | 连接每行的内容并添加到结果中

        # 添加分隔符
        if paragraphs:
            paragraphs.append("-" * 40)  # 添加分隔符

    except Exception as e:
        print(f"Error reading docx file {filepath}: {e}")
        failed_files.append(filepath)  # 记录加载失败的文件
        return []  # 返回空列表表示失败

    return paragraphs  # 返回所有段落和表格内容


def read_excel(filepath):
    """读取Excel文件内容并按段落存储"""
    paragraphs = []
    try:
        if filepath.endswith('.xlsx'):
            wb = openpyxl.load_workbook(filepath, read_only=True)  # 以只读模式打开xlsx文件
        else:  # 处理xls文件
            wb = xlrd.open_workbook(filepath)  # 打开xls文件

        for sheet in wb.worksheets if hasattr(wb, 'worksheets') else wb.sheets():  # 遍历所有工作表
            for row in sheet.iter_rows(values_only=True) if hasattr(sheet, 'iter_rows') else range(sheet.nrows):
                row_contents = [str(cell) for cell in row if cell is not None]  # 取出非空单元格内容
                if row_contents:  # 如果行非空
                    paragraphs.append(' | '.join(row_contents))  # 将行内容拼接成字符串

        # 添加分隔符
        if paragraphs:
            paragraphs.append("-" * 40)  # 添加分隔符

    except Exception as e:
        print(f"Error reading file {filepath}: {e}")  # 打印错误信息
        failed_files.append(filepath)  # 记录加载失败的文件
    return paragraphs  # 返回所有段落和表格内容


def load_files_async(filepaths):
    """异步加载文件内容"""
    local_content = []  # 局部文件内容列表
    total_files = len(filepaths)
    batch_size = 10  # 每批处理10个文件
    for i in range(0, total_files, batch_size):
        batch_files = filepaths[i:i + batch_size]  # 获取当前批次文件
        with ThreadPoolExecutor(max_workers=4) as executor:  # 创建线程池
            futures = [executor.submit(read_file, filepath) for filepath in batch_files]  # 提交当前批次的文件读取任务
            for future in futures:
                local_content.extend(future.result())  # 合并任务结果
        # 更新状态信息,只有在每批处理完成后更新一次
        result.set(f"已加载 {min(i + batch_size, total_files)} / {total_files} 个文件")

    global file_content
    file_content = local_content  # 更新全局文件内容
    result.set("已加载所有题库")  # 更新状态信息

    # 显示加载失败的文件信息
    if failed_files:  # 如果有加载失败的文件
        result.set(f"已加载所有题库,但以下文件加载失败:")
        text_display.config(state=tk.NORMAL)  # 启用文本框编辑
        for file in failed_files:
            text_display.insert(tk.END, f"加载失败: {file}\n", "fail")  # 插入失败文件信息
        text_display.config(state=tk.DISABLED)  # 禁用文本框编辑
        failed_files.clear()  # 清空失败文件列表


def select_files():
    """打开文件选择对话框"""
    filepaths = filedialog.askopenfilenames(
        filetypes=[("All supported files", "*.docx;*.xlsx;*.xls"),
                   ("Word files", "*.docx"),
                   ("Excel files", "*.xlsx;*.xls")]
    )
    if filepaths:  # 如果选中文件
        result.set("正在加载文件...")  # 更新状态信息
        threading.Thread(target=load_files_async, args=(filepaths,), daemon=True).start()  # 异步加载文件


def toggle_monitoring():
    """切换剪贴板监控状态"""
    global monitoring, initial_clipboard_content
    monitoring = not monitoring  # 切换监控状态
    if monitoring:
        initial_clipboard_content = pyperclip.paste().strip()  # 获取并记录当前剪贴板内容
        toggle_button.config(text="停止监控")  # 更新按钮文本
        result.set("正在监控剪贴板...")  # 更新状态信息
        threading.Thread(target=monitor_clipboard, daemon=True).start()  # 启动监控线程
    else:
        toggle_button.config(text="开始监控")  # 更新按钮文本
        result.set("监控已停止")  # 更新状态信息


def monitor_clipboard():
    """监控剪贴板内容变化"""
    global monitoring, initial_clipboard_content
    while monitoring:  # 监控状态为True时
        try:
            tmp_value = pyperclip.paste().strip()  # 获取当前剪贴板内容
            if tmp_value and tmp_value != initial_clipboard_content:  # 只处理新复制的内容
                initial_clipboard_content = tmp_value  # 更新初始剪贴板内容
                keyword_var.set(tmp_value)  # 更新关键词变量
                threading.Thread(target=update_text_area, args=(tmp_value,), daemon=True).start()  # 更新文本区域
            time.sleep(0.5)  # 每0.5秒检查一次
        except Exception as e:
            print(f"Error accessing clipboard: {e}")  # 打印错误信息
            time.sleep(1)  # 出现错误等待1秒再试


def update_text_area(keyword_value):
    """更新文本显示区域"""
    result_text = search_context(file_content, keyword_value, batch_size=10)  # 在搜索时使用批处理
    text_display.config(state=tk.NORMAL)  # 启用文本框编辑
    text_display.delete(1.0, tk.END)  # 清空文本框
    text_display.insert(tk.END, result_text)  # 显示搜索结果
    text_display.config(state=tk.DISABLED)  # 禁用文本框编辑


def search_context(content_lines, keyword, batch_size=10):
    """在文件内容中搜索关键词,支持分批处理"""
    if not keyword:  # 如果关键词为空
        return "请输入关键词"  # 返回提示信息

    pattern = re.escape(keyword)  # 转义关键词
    contexts = []  # 初始化上下文列表

    total_lines = len(content_lines)

    for i in range(0, total_lines, batch_size):  # 按批次遍历内容
        batch_lines = content_lines[i:i + batch_size]  # 获取当前批次内容

        for idx, paragraph in enumerate(batch_lines):  # 遍历当前批次中的段落
            if re.search(pattern, paragraph):  # 如果段落匹配
                # 获取当前段落及其后面的六个段落
                start_idx = i + idx
                result_paragraphs = content_lines[start_idx:start_idx + 7]  # 取出当前段落和后面的六个段落
                # 添加每段首行缩进两个空格
                formatted_paragraphs = ["  " + p for p in result_paragraphs]
                # 在每行之间添加分隔符
                contexts.append('\n'.join(formatted_paragraphs))
                contexts.append("-" * 40)  # 添加分隔符

    if not contexts:  # 如果未找到匹配
        return f'未找到 "{keyword}"'  # 返回未找到信息

    return '\n\n'.join(contexts)  # 返回所有匹配段落之间添加空行


def show_help():
    """显示帮助信息"""
    help_text = (
        "帮助文档\n\n"
        "1. 使用指南:\n"
        "- 加载题库:点击'加载题库'按钮可以选择多个题库加载\n"
        "- 开始监控:点击'开始监控'按钮以监控剪贴板内容。\n\n"
        "2. 功能说明:\n"
        "- 本程序用于文件内容搜索,题库支持docx,xls,xlsx。\n"
        "- 题库内容没有固定格式要求,设定为自题库内关键词所在段落,往下共显示7个段落内容。\n"
        "- 剪贴板监控功能可自动检测并搜索新的剪贴板内容。\n"
        "- 该程序自动置顶,可用于测试进行中不允许切换页面的程序。\n"
        "- 关闭程序后,自动清空题库缓存,再次运行后,需要重新加载题库。\n"
    )
    messagebox.showinfo("帮助文档", help_text)  # 显示帮助信息的弹出窗口


if __name__ == "__main__":
    create_gui()  # 创建并显示GUI
    root.mainloop()  # 启动Tkinter事件循环

免费评分

参与人数 2吾爱币 +4 热心值 +2 收起 理由
dogox + 1 + 1 我很赞同!
wkdxz + 3 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

3#
hgd6367385 发表于 2024-11-21 17:20
4#
w-c-f5522 发表于 2024-11-21 17:32
这个是可以自己 找题库 , 帮助搜索 本地内容 的吧 . 感谢楼主的分享
5#
 楼主| Corvus 发表于 2024-11-21 17:34 |楼主
w-c-f5522 发表于 2024-11-21 17:32
这个是可以自己 找题库 , 帮助搜索 本地内容 的吧 . 感谢楼主的分享

嗯对的,用自己的题库,满足各种考试
6#
bp13 发表于 2024-11-21 17:37
这个一定要支持!!!
7#
zr2019 发表于 2024-11-21 17:38
楼主利害啊,实用工具,谢谢楼主分享
8#
zpwz 发表于 2024-11-21 17:41
感谢分享,用过第一版本,实用
9#
天天哈皮 发表于 2024-11-21 17:42
感谢分享!!
10#
liuminga88 发表于 2024-11-21 17:59
下载学习下谢谢楼主
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-22 03:42

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表