剪切板python自动处理

监听剪切板内容,在发生变化时,将内容替换为去除所有空白字符的新内容,如果是图片或剪切板为空则跳过

基本功能版

实现对于caj或PDF文件的文字复制处理,以及对于chat文本分段的处理

点击查看代码
import re
import time
import pyperclip


class TextProcessor:

    def __init__(self):
        self.regs = {
            # "去除空白字符": (r'\s', ""),
            "去除连续空白行": (r'[\n\s]*\n', '\n'), # 用于规整的分条文本,chat
            "去除引用角标": (r'$$.*?\d+$$', ""),
        }

    def process_text(self, text):
        for pattern, replacement in self.regs.values():
            text = re.sub(pattern, replacement, text)
        return text


class ClipboardMonitor:

    def __init__(self):
        self.last_content = None

    def get_clipboard_data(self):
        return pyperclip.paste()

    def monitor(self):
        while True:
            current_content = self.get_clipboard_data()
            if current_content != self.last_content:
                self.last_content = current_content
                return current_content
            time.sleep(0.2)


def main():
    processor = TextProcessor()
    monitor = ClipboardMonitor()

    print('程序已启动,复制内容会自动处理,直接粘贴即可,不需要时请关闭程序\n')

    while True:
        content = monitor.monitor()
        if content:  # 确保content不为空
            processed_content = processor.process_text(content)
            pyperclip.copy(processed_content)
            print(f'\n新的内容: {processed_content}')


if __name__ == '__main__':
    main()

UI版本

可通过UI界面控制功能启用及模式切换

点击查看代码
import re
import time
import pyperclip
import PySimpleGUI as sg
import threading
import os


class AppStateManager:

    def __init__(self):
        self.enable_process = True
        self.process_method = "chat"


class GUI_Control():
    # 功能线程管理列表
    thread_pool = []

    def __init__(self, app_state):
        self.app_state = app_state
        self.clipboard_monitor = ClipboardMonitor(app_state=self.app_state)
        self.first_run = True
        # 设置主题颜色
        sg.theme('SystemDefaultForReal')
        sg.SetOptions(
            margins=(10, 10),  # 设置元素间隔
            background_color='#f3f4f6',  # 设置背景颜色
            element_background_color='#f3f4f6',  # 设置元素颜色
            text_element_background_color='#f3f4f6',  # 设置文本框颜色
            input_elements_background_color='#fafafa',  # 设置输入元素颜色
            button_color=('white', '#fafafa'),  # 设置按钮颜色
            scrollbar_color='#fc5531',  # 设置滚动条颜色
            sbar_trough_color='#fc5531',  # 设置滚动条背景颜色
            progress_meter_color=('green', 'blue'),  # 设置进度条颜色
            titlebar_background_color='#f9f9fa',  # 设置标题栏颜色
            scaling=1.0,  # 设置缩放比例
        )

        # 定义GUI布局
        layout = [
            [
                # 功能开关
                sg.Checkbox('启用文本处理',
                            default=True,
                            key='ENABLE_PROCESS',
                            enable_events=True),
                # 间隔
                sg.Text(' ' * 10),
                # 下拉框
                sg.Combo(
                    ['chat', 'caj'],
                    default_value='chat',
                    key='PROCESS_METHOD',
                    readonly=True,  # 设置下拉框只读
                    enable_events=True,  # 设置下拉框状态发生改变时触发事件  
                    button_background_color='#e9ecf1',  # 设置按钮颜色
                    button_arrow_color='#4d85ff',  # 设置按钮箭头颜色
                    expand_x=True  # 设置下拉框大小随窗口大小改变
                )
            ],
            # 信息显示区域
            [
                sg.Multiline("",
                             autoscroll=True,
                             size=(40, 15),
                             no_scrollbar=True,
                             key='-OUT-')
            ]
        ]

        # 创建GUI窗口
        self.window = sg.Window(
            '剪切板自动处理',
            layout,
            font=('微软雅黑', '13'),
            alpha_channel=0.85,  # 设置透明度
            # no_titlebar=True,  # 去除顶部状态栏
            grab_anywhere=True  # 允许随意拖动窗口
        )
        # 设置图标
        try:
            self.window.set_icon(r"static\favicon.ico")
        except Exception as e:
            print(e)

    def ui_loop(self):
        while True:
            event, values = self.window.read(timeout=30)

            # 退出事件
            if event in [sg.WIN_CLOSED, None, 'exit']:
                break

            # 复选框事件
            if event == 'ENABLE_PROCESS':
                self.app_state.enable_process = values['ENABLE_PROCESS']

            # 下拉框事件
            if event == 'PROCESS_METHOD':
                self.app_state.process_method = values['PROCESS_METHOD']

            if self.first_run:
                self.first_run = False
        self.window.close()
        os._exit(0)

    def update_value(self):
        while True:
            time.sleep(30 / 1000)
            if len(self.thread_pool) >= 2:
                try:
                    processed_content = next(self.clipboard_monitor.monitor())
                    self.window["-OUT-"].update(processed_content)
                except StopIteration:
                    break

    def run(self):
        # ui线程
        thread_gui = threading.Thread(target=self.ui_loop)
        thread_gui.start()
        self.thread_pool.append(thread_gui)
        # 功能线程
        thread_clipboard = threading.Thread(
            target=self.clipboard_monitor.monitor)
        thread_clipboard.start()
        self.thread_pool.append(thread_clipboard)
        # 更新显示线程
        # 等待功能线程启动
        while self.first_run:
            time.sleep(50 / 1000)
        thread_update = threading.Thread(target=self.update_value)
        thread_update.start()
        self.thread_pool.append(thread_update)

        # 添加线程停止事件
        for thread in self.thread_pool:
            thread._stop_event = threading.Event()

    def stop_threads(self):
        for thread in self.thread_pool:
            thread._stop_event.set()


class ClipboardMonitor:

    def __init__(self, app_state):
        self.app_state = app_state
        self.last_content = None
        self.reg_base = {
            "去除引用角标": (r'$$.*?\d+$$', ""),
        }
        self.regs = {
            "caj": (r'\s', ""),  # 去除空白字符,用于caj或PDF复制的文本
            "chat": (r'[\n\s]*\n', '\n'),  # 去除连续空白行,用于规整的分条空行文本,AIchat
        }

    def process_text(self, text, method="chat", enable=True, times=2):
        if not enable:
            return text
        if method not in self.regs:
            print(f"未找到对应的处理方法{method}")
            return text
        if times >= 1:
            for _ in range(times):
                # 使用规则正则表达式
                text = re.sub(self.regs[method][0], self.regs[method][1], text)
                # 使用基础正则表达式
                for pattern, replacement in self.reg_base.values():
                    text = re.sub(pattern, replacement, text)
        return text

    def get_clipboard_data(self):
        return pyperclip.paste()

    def monitor(self):
        while True:
            time.sleep(50 / 1000)
            current_content = self.get_clipboard_data()
            if current_content == self.last_content:
                continue
            self.last_content = current_content
            if current_content:  # 确保content不为空,排除图片情况
                processed_content = self.process_text(
                    current_content,
                    method=self.app_state.process_method,
                    enable=self.app_state.enable_process)
                pyperclip.copy(processed_content)
                yield processed_content


if __name__ == '__main__':
    app_state = AppStateManager()
    gui = GUI_Control(app_state)
    gui.run()
    # 在程序退出前停止线程
    gui.stop_threads()


requirements.txt

点击查看代码
PySimpleGUI==4.60.5
pyperclip==1.8.2

环境配置.bat

点击查看代码
chcp 65001

cd /d "%~dp0"


pip install -r requirements.txt

pause

启动程序.bat

在文件所在同级目录创建一个bat文件,并修改python文件名适配即可

点击查看代码
chcp 65001

cd /d "%~dp0"


start /min "" "pasteDeal.py"

exit

posted @ 2022-08-29 21:13  Dapenson  阅读(54)  评论(0编辑  收藏  举报